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