From 18bdf1d33c4be4c9ce1bc20911cc32ac7b059314 Mon Sep 17 00:00:00 2001 From: Dmitry Simonenko <pmwkaa@gmail.com> Date: Mon, 12 Mar 2012 17:46:02 +0400 Subject: [PATCH] core-lua-i64: lua cdata i64 support --- core/tarantool_lua.m | 43 +++++++++++++++++++++++++++++++++++++++++++ mod/box/box_lua.m | 21 +++++++++++++++++++++ mod/box/tuple.m | 3 +++ 3 files changed, 67 insertions(+) diff --git a/core/tarantool_lua.m b/core/tarantool_lua.m index a4ade18da2..5c91f90557 100644 --- a/core/tarantool_lua.m +++ b/core/tarantool_lua.m @@ -34,6 +34,11 @@ #include "lauxlib.h" #include "lualib.h" +#include "lj_obj.h" +#include "lj_ctype.h" +#include "lj_cdata.h" +#include "lj_cconv.h" + #include "pickle.h" #include "fiber.h" #include <ctype.h> @@ -151,6 +156,18 @@ lbox_pack(struct lua_State *L) luaL_addlstring(&b, (char *) &u32buf, sizeof(u32)); break; } + case 'L': + case 'l': + { + if (lua_type(L, i) != LUA_TCDATA) + luaL_error(L, "box.pack('%c'): expected to be cdata (i64)", *format); + GCcdata *cd = cdataV(L->base + (i - 1)); + if (cd->typeid != CTID_INT64 && cd->typeid != CTID_UINT64) + luaL_error(L, "box.pack('%c'): unsupported cdata type", *format); + char *p = (char*)cdataptr(cd); + luaL_addlstring(&b, p, sizeof(u64)); + break; + } /* Perl 'pack' BER-encoded integer */ case 'w': luaL_addvarint32(&b, lua_tointeger(L, i)); @@ -167,6 +184,13 @@ lbox_pack(struct lua_State *L) u32buf= (u32) lua_tointeger(L, i); str = (char *) &u32buf; size = sizeof(u32); + } else + if (lua_type(L, i) == LUA_TCDATA) { + GCcdata *cd = cdataV(L->base + (i - 1)); + if (cd->typeid != CTID_INT64 && cd->typeid != CTID_UINT64) + luaL_error(L, "box.pack('%c'): unsupported cdata type", *format); + str = (char*)cdataptr(cd); + size = sizeof(u64); } else { str = luaL_checklstring(L, i, &size); } @@ -215,6 +239,25 @@ lbox_unpack(struct lua_State *L) u32buf = * (u32 *) str; lua_pushnumber(L, u32buf); break; + case 'l': + { + str = lua_tolstring(L, i, &size); + if (str == NULL || size != sizeof(u64)) + luaL_error(L, "box.unpack('%c'): got %d bytes (expected: 8)", *format, (int) size); + TValue *o = L->base+1; + CTState *cts = ctype_cts(L); + CType *ct = ctype_raw(cts, CTID_UINT64); + CTSize sz; + lj_ctype_info(cts, CTID_UINT64, &sz); + GCcdata *cd = lj_cdata_new(cts, CTID_UINT64, 8); + setcdataV(L, o-1, cd); + lj_cconv_ct_init(cts, ct, sz, cdataptr(cd), o, 0); + L->top = o; + uint64_t *up = (uint64_t*)cdataptr(cd); + *up = *(u64*)str; + lj_gc_check(L); + break; + } default: luaL_error(L, "box.unpack: unsupported pack " "format specifier '%c'", *format); diff --git a/mod/box/box_lua.m b/mod/box/box_lua.m index eb643f1899..b46089ca53 100644 --- a/mod/box/box_lua.m +++ b/mod/box/box_lua.m @@ -36,6 +36,11 @@ #include "lauxlib.h" #include "lualib.h" +#include "lj_obj.h" +#include "lj_ctype.h" +#include "lj_cdata.h" +#include "lj_cconv.h" + #include "pickle.h" #include "tuple.h" #include "salloc.h" @@ -501,6 +506,19 @@ iov_add_lua_table(struct lua_State *L, int index) iov_dup(field, field_len); *tuple_len += field_len_len + field_len; break; + + case LUA_TCDATA: + field = tarantool_lua_tostring(L, -1); + field_len = strlen(field); + if (field_len) + field_len -= 3; /* chopping of ULL prefix */ + field_len_len = + save_varint32(field_len_buf, + field_len) - field_len_buf; + iov_dup(field_len_buf, field_len_len); + iov_dup(field, field_len); + *tuple_len += field_len_len + field_len; + break; default: tnt_raise(ClientError, :ER_PROC_RET, lua_typename(L, lua_type(L, -1))); @@ -532,9 +550,12 @@ void iov_add_ret(struct lua_State *L, int index) } case LUA_TNIL: case LUA_TBOOLEAN: + case LUA_TCDATA: { const char *str = tarantool_lua_tostring(L, index); size_t len = strlen(str); + if (type == LUA_TCDATA && len) + len -= 3; /* chopping of ULL prefix */ tuple = tuple_alloc(len + varint32_sizeof(len)); tuple->cardinality = 1; memcpy(save_varint32(tuple->data, len), str, len); diff --git a/mod/box/tuple.m b/mod/box/tuple.m index 76475b1150..c6af90b5b0 100644 --- a/mod/box/tuple.m +++ b/mod/box/tuple.m @@ -118,6 +118,9 @@ print_field(struct tbuf *buf, void *f) case 4: tbuf_printf(buf, "%u", *(u32 *)f); break; + case 8: + tbuf_printf(buf, "%"PRIu64, *(u64 *)f); + break; default: tbuf_printf(buf, "'"); while (size-- > 0) { -- GitLab