summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docbook/CMakeLists.txt1
-rw-r--r--docbook/Makefile.common1
-rw-r--r--docbook/user-guide.xml1
-rw-r--r--docbook/wsluarm.xml1
-rw-r--r--epan/wslua/CMakeLists.txt1
-rw-r--r--epan/wslua/Makefile.am2
-rw-r--r--epan/wslua/Makefile.nmake2
-rwxr-xr-xepan/wslua/make-reg.pl2
-rw-r--r--epan/wslua/wslua.h16
-rw-r--r--epan/wslua/wslua_field.c8
-rw-r--r--epan/wslua/wslua_int64.c911
-rw-r--r--epan/wslua/wslua_tree.c4
-rw-r--r--epan/wslua/wslua_tvb.c110
-rw-r--r--epan/wslua/wslua_util.c13
-rwxr-xr-xtest/lua/int64.lua341
-rwxr-xr-xtest/suite-unittests.sh12
16 files changed, 1306 insertions, 120 deletions
diff --git a/docbook/CMakeLists.txt b/docbook/CMakeLists.txt
index 8faee7c266..2c03b72c2b 100644
--- a/docbook/CMakeLists.txt
+++ b/docbook/CMakeLists.txt
@@ -289,6 +289,7 @@ set(WSLUA_MODULES
${CMAKE_SOURCE_DIR}/epan/wslua/wslua_dumper.c
${CMAKE_SOURCE_DIR}/epan/wslua/wslua_field.c
${CMAKE_SOURCE_DIR}/epan/wslua/wslua_gui.c
+ ${CMAKE_SOURCE_DIR}/epan/wslua/wslua_int64.c
${CMAKE_SOURCE_DIR}/epan/wslua/wslua_listener.c
${CMAKE_SOURCE_DIR}/epan/wslua/wslua_pinfo.c
${CMAKE_SOURCE_DIR}/epan/wslua/wslua_proto.c
diff --git a/docbook/Makefile.common b/docbook/Makefile.common
index 88e6635d03..c83c2a5874 100644
--- a/docbook/Makefile.common
+++ b/docbook/Makefile.common
@@ -262,6 +262,7 @@ WSLUA_MODULES = \
../epan/wslua/wslua_listener.c \
../epan/wslua/wslua_pinfo.c \
../epan/wslua/wslua_proto.c \
+ ../epan/wslua/wslua_int64.c \
../epan/wslua/wslua_tree.c \
../epan/wslua/wslua_tvb.c \
../epan/wslua/wslua_util.c
diff --git a/docbook/user-guide.xml b/docbook/user-guide.xml
index 2289a74982..997190f315 100644
--- a/docbook/user-guide.xml
+++ b/docbook/user-guide.xml
@@ -347,6 +347,7 @@ WSLua Reference Manual
<!ENTITY WsLuaTree SYSTEM "wsluarm_src/wslua_tree.xml">
<!ENTITY WsLuaTvb SYSTEM "wsluarm_src/wslua_tvb.xml">
<!ENTITY WsLuaUtility SYSTEM "wsluarm_src/wslua_util.xml">
+ <!ENTITY WsLuaInt64 SYSTEM "wsluarm_src/wslua_int64.xml">
]>
diff --git a/docbook/wsluarm.xml b/docbook/wsluarm.xml
index 0e769511ec..07f44ac368 100644
--- a/docbook/wsluarm.xml
+++ b/docbook/wsluarm.xml
@@ -177,4 +177,5 @@ end
&WsLuaTree;
&WsLuaTvb;
&WsLuaUtility;
+ &WsLuaInt64;
</chapter>
diff --git a/epan/wslua/CMakeLists.txt b/epan/wslua/CMakeLists.txt
index a244687103..4332200a72 100644
--- a/epan/wslua/CMakeLists.txt
+++ b/epan/wslua/CMakeLists.txt
@@ -25,6 +25,7 @@
set(WSLUA_MODULES
${CMAKE_CURRENT_SOURCE_DIR}/wslua/lua_bitop.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/wslua/wslua_int64.c
${CMAKE_CURRENT_SOURCE_DIR}/wslua/wslua_tvb.c
${CMAKE_CURRENT_SOURCE_DIR}/wslua/wslua_proto.c
${CMAKE_CURRENT_SOURCE_DIR}/wslua/wslua_tree.c
diff --git a/epan/wslua/Makefile.am b/epan/wslua/Makefile.am
index 88f063c84d..e5789c1d7d 100644
--- a/epan/wslua/Makefile.am
+++ b/epan/wslua/Makefile.am
@@ -33,6 +33,7 @@ wslua_modules = \
$(srcdir)/lua_bitop.c \
$(srcdir)/wslua_tvb.c \
$(srcdir)/wslua_proto.c \
+ $(srcdir)/wslua_int64.c \
$(srcdir)/wslua_tree.c \
$(srcdir)/wslua_pinfo.c \
$(srcdir)/wslua_listener.c \
@@ -125,6 +126,7 @@ checkapi:
wslua_dumper.c \
wslua_field.c \
wslua_gui.c \
+ wslua_int64.c \
wslua_pinfo.c \
wslua_proto.c \
wslua_listener.c \
diff --git a/epan/wslua/Makefile.nmake b/epan/wslua/Makefile.nmake
index 0898e94814..f9c63d21a4 100644
--- a/epan/wslua/Makefile.nmake
+++ b/epan/wslua/Makefile.nmake
@@ -18,6 +18,7 @@ MODULES = \
lua_bitop.c \
wslua_tvb.c \
wslua_proto.c \
+ wslua_int64.c \
wslua_tree.c \
wslua_pinfo.c \
wslua_listener.c \
@@ -37,6 +38,7 @@ OBJECTS= \
wslua_pinfo.obj \
wslua_proto.obj \
wslua_listener.obj \
+ wslua_int64.obj \
wslua_tree.obj \
wslua_tvb.obj \
wslua_util.obj
diff --git a/epan/wslua/make-reg.pl b/epan/wslua/make-reg.pl
index 3c8b4afa60..7f7408dc99 100755
--- a/epan/wslua/make-reg.pl
+++ b/epan/wslua/make-reg.pl
@@ -31,7 +31,7 @@ my @classes = ();
my @functions = ();
while (<>) {
- push @classes, $1 if /WSLUA_CLASS_DEFINE\050\s*([A-Za-z0-9]+)/;
+ push @classes, $1 if /WSLUA_CLASS_DEFINE(?:_BASE)?\050\s*([A-Za-z0-9]+)/;
push @functions, $1 if /WSLUA_FUNCTION\s+wslua_([a-z_0-9]+)/;
}
diff --git a/epan/wslua/wslua.h b/epan/wslua/wslua.h
index fd223f382f..bb4eab2c20 100644
--- a/epan/wslua/wslua.h
+++ b/epan/wslua/wslua.h
@@ -240,8 +240,8 @@ typedef struct _wslua_pinfo* Pinfo;
typedef struct _wslua_treeitem* TreeItem;
typedef address* Address;
typedef nstime_t* NSTime;
-typedef gint64* Int64;
-typedef guint64* UInt64;
+typedef gint64 Int64;
+typedef guint64 UInt64;
typedef header_field_info** Field;
typedef struct _wslua_field_info* FieldInfo;
typedef struct _wslua_tap* Listener;
@@ -267,17 +267,20 @@ typedef struct _wslua_private_table* PrivateTable;
* (a dummy typedef is used to be syntactically correct)
*/
#define WSLUA_CLASS_DEFINE(C,check_code,push_code) \
+ WSLUA_CLASS_DEFINE_BASE(C,check_code,push_code,NULL)
+
+#define WSLUA_CLASS_DEFINE_BASE(C,check_code,push_code,retval) \
C to##C(lua_State* L, int idx) { \
C* v = (C*)lua_touserdata (L, idx); \
if (!v) luaL_error(L, "bad argument %d (%s expected, got %s)", idx, #C, lua_typename(L, lua_type(L, idx))); \
- return v ? *v : NULL; \
+ return v ? *v : retval; \
} \
C check##C(lua_State* L, int idx) { \
C* p; \
luaL_checktype(L,idx,LUA_TUSERDATA); \
p = (C*)luaL_checkudata(L, idx, #C); \
check_code; \
- return p ? *p : NULL; \
+ return p ? *p : retval; \
} \
C* push##C(lua_State* L, C v) { \
C* p; \
@@ -298,13 +301,13 @@ gboolean is##C(lua_State* L,int i) { \
} \
C shift##C(lua_State* L,int i) { \
C* p; \
- if(!lua_isuserdata(L,i)) return NULL; \
+ if(!lua_isuserdata(L,i)) return retval; \
p = (C*)lua_touserdata(L, i); \
lua_getfield(L, LUA_REGISTRYINDEX, #C); \
if (p == NULL || !lua_getmetatable(L, i) || !lua_rawequal(L, -1, -2)) p=NULL; \
lua_pop(L, 2); \
if (p) { lua_remove(L,i); return *p; }\
- else return NULL;\
+ else return retval;\
} \
typedef int dummy##C
@@ -437,6 +440,7 @@ WSLUA_DECLARE_FUNCTIONS()
extern lua_State* wslua_state(void);
+extern int wslua__concat(lua_State* L);
extern gboolean wslua_optbool(lua_State* L, int n, gboolean def);
extern const gchar* lua_shiftstring(lua_State* L,int idx);
extern void wslua_setfuncs(lua_State *L, const luaL_Reg *l, int nup);
diff --git a/epan/wslua/wslua_field.c b/epan/wslua/wslua_field.c
index 5b1393ea0c..55ca858dcf 100644
--- a/epan/wslua/wslua_field.c
+++ b/epan/wslua/wslua_field.c
@@ -113,15 +113,11 @@ WSLUA_METAMETHOD FieldInfo__call(lua_State* L) {
lua_pushnumber(L,(lua_Number)fvalue_get_floating(&(fi->ws_fi->value)));
return 1;
case FT_INT64: {
- Int64 num = (Int64)g_malloc(sizeof(gint64));
- *num = fvalue_get_integer64(&(fi->ws_fi->value));
- pushInt64(L,num);
+ pushInt64(L,(Int64)fvalue_get_integer64(&(fi->ws_fi->value)));
return 1;
}
case FT_UINT64: {
- UInt64 num = (UInt64)g_malloc(sizeof(guint64));
- *num = fvalue_get_integer64(&(fi->ws_fi->value));
- pushUInt64(L,num);
+ pushUInt64(L,fvalue_get_integer64(&(fi->ws_fi->value)));
return 1;
}
case FT_ETHER: {
diff --git a/epan/wslua/wslua_int64.c b/epan/wslua/wslua_int64.c
new file mode 100644
index 0000000000..693e80be3f
--- /dev/null
+++ b/epan/wslua/wslua_int64.c
@@ -0,0 +1,911 @@
+
+/*
+ * A Lua userdata object for 64-bit signed/unsigned integers.
+ * $Id: wslua_int64.c,v 1.0 2013/03/31 02:08:32 hadrielk Exp $
+ * See Copyright Notice at the end of this file
+ */
+
+#include "config.h"
+
+#include "wslua.h"
+
+/* WSLUA_MODULE Int64 Handling 64-bit Integers */
+
+#define LUATYPE64_STRING_SIZE 21 /* string to hold 18446744073709551615 */
+
+
+WSLUA_CLASS_DEFINE_BASE(Int64,NOP,NOP,0);
+/*
+ Int64 represents a 64 bit signed integer.
+ Lua uses one single number representation which can be chosen at compile time and since
+ it is often set to IEEE 754 double precision floating point, we cannot store a 64 bit integer
+ with full precision.
+ For details, see: http://lua-users.org/wiki/FloatingPoint
+ */
+
+/* these declarations are here because some funcs in Int64 need to know about UInt64 */
+UInt64 toUInt64(lua_State* L, int i);
+gboolean isUInt64(lua_State* L, int i);
+UInt64 checkUInt64(lua_State* L, int i);
+
+/* A checkInt64 but that also auto-converts numbers, strings, and UINT64 to a gint64 */
+static gint64 getInt64(lua_State *L, int i)
+{
+ gchar *end = NULL;
+ (void) end;
+ switch (lua_type(L,i))
+ {
+ case LUA_TNUMBER:
+ return (gint64)luaL_checknumber(L,i);
+ case LUA_TSTRING:
+ return g_ascii_strtoll(luaL_checkstring(L,i),&end,10);
+ case LUA_TUSERDATA:
+ if (isUInt64(L, i)) {
+ return (Int64) toUInt64(L, i);
+ break;
+ }
+ /* fall through */
+ default:
+ return checkInt64(L,i);
+ }
+}
+
+
+/* Encodes Int64 userdata into Lua string struct with given endianess */
+void Int64_pack(lua_State* L, luaL_Buffer *b, gint idx, gboolean asLittleEndian) {
+ gint64 value = checkInt64(L,idx);
+ gint8 buff[sizeof(gint64)];
+
+ if (asLittleEndian) {
+ guint i;
+ for (i = 0; i < sizeof(gint64); i++) {
+ buff[i] = (value & 0xff);
+ value >>= 8;
+ }
+ }
+ else {
+ gint i;
+ for (i = sizeof(gint64) - 1; i >= 0; i--) {
+ buff[i] = (value & 0xff);
+ value >>= 8;
+ }
+ }
+ luaL_addlstring(b, (char*)buff, sizeof(gint64));
+}
+
+WSLUA_METHOD Int64_encode(lua_State* L) {
+ /* Encodes the Int64 number into an 8-byte Lua string, using given endianess */
+#define WSLUA_OPTARG_Int64_encode_ENDIAN 2 /* If set to true then little-endian is used, if false then big-endian; if missing/nil, native host endian */
+ luaL_Buffer b;
+ gboolean asLittleEndian = (G_BYTE_ORDER == G_LITTLE_ENDIAN)? TRUE : FALSE;
+
+ if (lua_gettop(L) >= WSLUA_OPTARG_Int64_encode_ENDIAN) {
+ if (lua_type(L,WSLUA_OPTARG_Int64_encode_ENDIAN) == LUA_TBOOLEAN)
+ asLittleEndian = lua_toboolean(L,WSLUA_OPTARG_Int64_encode_ENDIAN);
+ }
+
+ luaL_buffinit(L, &b);
+
+ Int64_pack(L, &b, 1, asLittleEndian);
+
+ luaL_pushresult(&b);
+ WSLUA_RETURN(1); /* The Lua string */
+}
+
+/* Decodes from string buffer struct into Int64 userdata, with given endianess */
+int Int64_unpack(lua_State* L, const gchar *buff, gboolean asLittleEndian) {
+ gint64 value = 0;
+ gint i;
+
+ if (asLittleEndian) {
+ for (i = sizeof(gint64) - 1; i >= 0; i--) {
+ value <<= 8;
+ value |= (gint64)(guchar)buff[i];
+ }
+ }
+ else {
+ for (i = 0; i < (gint) sizeof(gint64); i++) {
+ value <<= 8;
+ value |= (gint64)(guchar)buff[i];
+ }
+ }
+
+ pushInt64(L,value);
+ return 1;
+}
+
+WSLUA_CONSTRUCTOR Int64_decode(lua_State* L) {
+ /* Decodes an 8-byte Lua string, using given endianess, into a new Int64 object */
+#define WSLUA_ARG_Int64_decode_STRING 1 /* The Lua string containing a binary 64-bit integer */
+#define WSLUA_OPTARG_Int64_decode_ENDIAN 2 /* If set to true then little-endian is used, if false then big-endian; if missing/nil, native host endian */
+ gboolean asLittleEndian = (G_BYTE_ORDER == G_LITTLE_ENDIAN)? TRUE : FALSE;
+ size_t len = 0;
+ const gchar *s = luaL_checklstring(L, WSLUA_ARG_Int64_decode_STRING, &len);
+
+ if (lua_gettop(L) >= WSLUA_OPTARG_Int64_decode_ENDIAN) {
+ if (lua_type(L,WSLUA_OPTARG_Int64_decode_ENDIAN) == LUA_TBOOLEAN)
+ asLittleEndian = lua_toboolean(L,WSLUA_OPTARG_Int64_decode_ENDIAN);
+ }
+
+ if (len == sizeof(gint64)) {
+ Int64_unpack(L, s, asLittleEndian);
+ } else {
+ lua_pushnil(L);
+ }
+
+ WSLUA_RETURN(1); /* The Int64 object created, or nil on failure */
+}
+
+WSLUA_CONSTRUCTOR Int64_new(lua_State* L) { /* Creates a Int64 Object */
+#define WSLUA_OPTARG_Int64_new_VALUE 1 /* A number, UInt64, Int64, or string of ascii digits to assign the value of the new Int64 (default=0) */
+#define WSLUA_OPTARG_Int64_new_HIGHVALUE 2 /* If this is a number and the first argument was a number, then the first will be treated as a lower 32-bits, and this is the high-order 32 bit number */
+ gint64 value = 0;
+
+ if (lua_gettop(L) >= 1) {
+ switch(lua_type(L, WSLUA_OPTARG_Int64_new_VALUE)) {
+ case LUA_TNUMBER:
+ value = (gint64)lua_tonumber(L, WSLUA_OPTARG_Int64_new_VALUE);
+ if (lua_gettop(L) == 2 && lua_type(L, WSLUA_OPTARG_Int64_new_HIGHVALUE) == LUA_TNUMBER) {
+ gint64 h = (gint64)lua_tonumber(L, WSLUA_OPTARG_Int64_new_HIGHVALUE);
+ value &= 0x00000000FFFFFFFF;
+ h <<= 32; h &= 0xFFFFFFFF00000000;
+ value += h;
+ }
+ break;
+ case LUA_TSTRING:
+ case LUA_TUSERDATA:
+ value = getInt64(L,WSLUA_OPTARG_Int64_new_VALUE);
+ break;
+ default:
+ WSLUA_OPTARG_ERROR(Int64_new,VALUE,"must be a number, UInt64, Int64, or string");
+ break;
+ }
+ }
+
+ pushInt64(L,value);
+
+ WSLUA_RETURN(1); /* The new Int64 object. */
+}
+
+WSLUA_CONSTRUCTOR Int64_max(lua_State* L) { /* Gets the max possible value */
+ pushInt64(L, G_MAXINT64);
+ WSLUA_RETURN(1); /* The new Int64 object of the max value. */
+}
+
+WSLUA_CONSTRUCTOR Int64_min(lua_State* L) { /* Gets the min possible value */
+ pushInt64(L, G_MININT64);
+ WSLUA_RETURN(1); /* The new Int64 object of the min value. */
+}
+
+
+WSLUA_METHOD Int64_tonumber(lua_State* L) {
+ /* Returns a Lua number of the Int64 value - this may lose precision. */
+ lua_pushnumber(L, (lua_Number)checkInt64(L,1));
+ WSLUA_RETURN(1); /* The Lua number */
+}
+
+WSLUA_CONSTRUCTOR Int64_fromhex(lua_State* L) { /* Creates an Int64 object from the given hex string */
+ guint64 result = 0;
+ size_t len = 0;
+ const gchar *s = luaL_checklstring(L,1,&len);
+
+ if (s && len > 0) {
+ sscanf(s, "%" G_GINT64_MODIFIER "x", &result);
+ }
+ pushInt64(L,(gint64)result);
+ WSLUA_RETURN(1); /* The new Int64 object. */
+}
+
+WSLUA_METHOD Int64_tohex(lua_State* L) {
+ /* Returns a hex string of the Int64 value. */
+#define WSLUA_OPTARG_Int64_new_NUMBYTES 2 /* The number of hex-chars/nibbles to generate, negative means uppercase (default=16) */
+ gint64 b = getInt64(L,1);
+ gint n = luaL_optint(L, WSLUA_OPTARG_Int64_new_NUMBYTES, 16);
+ const gchar *hexdigits = "0123456789abcdef";
+ gchar buf[16];
+ gint i;
+ if (n < 0) { n = -n; hexdigits = "0123456789ABCDEF"; }
+ if (n > 16) n = 16;
+ for (i = n-1; i >= 0; --i) { buf[i] = hexdigits[b & 15]; b >>= 4; }
+ lua_pushlstring(L, buf, (size_t)n);
+ WSLUA_RETURN(1); /* The string hex */
+}
+
+WSLUA_METHOD Int64_higher(lua_State* L) {
+ /* Returns a Lua number of the higher 32-bits of the Int64 value. (negative Int64 will return a negative Lua number) */
+ gint64 num = getInt64(L,1);
+ gint64 b = num;
+ lua_Number n;
+ if (b < 0) b = -b; /* masking/shifting negative int64 isn't working on some platforms */
+ b &= 0x7FFFFFFF00000000;
+ b >>= 32;
+ n = (lua_Number)(guint32)(b & 0x00000000FFFFFFFFF);
+ if (num < 0) n = -n;
+ lua_pushnumber(L,n);
+ WSLUA_RETURN(1); /* The Lua number */
+}
+
+WSLUA_METHOD Int64_lower(lua_State* L) {
+ /* Returns a Lua number of the lower 32-bits of the Int64 value. (always positive) */
+ gint64 b = getInt64(L,1);
+ if (b < 0) b = -b; /* masking/shifting negative int64 isn't working on some platforms */
+ lua_pushnumber(L,(guint32)(b & 0x00000000FFFFFFFFF));
+ WSLUA_RETURN(1); /* The Lua number */
+}
+
+WSLUA_METAMETHOD Int64__tostring(lua_State* L) {
+ /* Converts the Int64 into a string of decimal digits */
+ gint64 num = getInt64(L,1);
+ gchar s[LUATYPE64_STRING_SIZE];
+ if (sprintf(s, "%" G_GINT64_MODIFIER "d", num) < 0)
+ luaL_error(L, "Error writing Int64 to a string");
+ lua_pushstring(L,s);
+ WSLUA_RETURN(1); /* The Lua string */
+}
+
+WSLUA_METAMETHOD Int64__unm(lua_State* L) {
+ /* Returns the negative of the Int64, in a new Int64 */
+ pushInt64(L,-(getInt64(L,1)));
+ WSLUA_RETURN(1); /* The new Int64 */
+}
+
+#define WSLUA_MATH_OP_FUNC(obj,op) \
+ /* use the 'get' form so we can accept numbers as well */ \
+ obj num1 = get##obj(L,1); \
+ obj num2 = get##obj(L,2); \
+ push##obj(L,(num1) op (num2)); \
+ return 1
+
+WSLUA_METAMETHOD Int64__add(lua_State* L) {
+ /* Adds two Int64 together and returns a new one (this may wrap the value) */
+ WSLUA_MATH_OP_FUNC(Int64,+);
+}
+
+WSLUA_METAMETHOD Int64__sub(lua_State* L) {
+ /* Subtracts two Int64 and returns a new one (this may wrap the value) */
+ WSLUA_MATH_OP_FUNC(Int64,-);
+}
+
+WSLUA_METAMETHOD Int64__mul(lua_State* L) {
+ /* Multiplies two Int64 and returns a new one (this may truncate the value) */
+ WSLUA_MATH_OP_FUNC(Int64,*);
+}
+
+WSLUA_METAMETHOD Int64__div(lua_State* L) {
+ /* Divides two Int64 and returns a new one (integer divide, no remainder) */
+ WSLUA_MATH_OP_FUNC(Int64,/);
+}
+
+WSLUA_METAMETHOD Int64__mod(lua_State* L) {
+ /* Divides two Int64 and returns a new one of the remainder */
+ WSLUA_MATH_OP_FUNC(Int64,%);
+}
+
+WSLUA_METAMETHOD Int64__pow(lua_State* L) {
+ /* The first Int64 is taken to the power of the second Int64, returning a new one (this may truncate the value) */
+ gint64 num1 = getInt64(L,1);
+ gint64 num2 = getInt64(L,2);
+ gint64 result;
+ if (num1 == 2) {
+ result = (num2 >= 8 * (gint64) sizeof(gint64)) ? 0 : ((gint64)1 << num2);
+ }
+ else {
+ for (result = 1; num2 > 0; num2 >>= 1) {
+ if (num2 & 1) result *= num1;
+ num1 *= num1;
+ }
+ }
+ pushInt64(L,result);
+ WSLUA_RETURN(1); /* The Int64 object */
+}
+
+#define WSLUA_COMP_OP_FUNC(obj,op) \
+ obj num1 = get##obj(L,1); \
+ obj num2 = get##obj(L,2); \
+ lua_pushboolean(L,(num1) op (num2)); \
+ return 1
+
+WSLUA_METAMETHOD Int64__eq(lua_State* L) {
+ /* Returns true if both Int64 are equal */
+ WSLUA_COMP_OP_FUNC(Int64,==);
+}
+
+WSLUA_METAMETHOD Int64__lt(lua_State* L) {
+ /* Returns true if first Int64 < second */
+ WSLUA_COMP_OP_FUNC(Int64,<);
+}
+
+WSLUA_METAMETHOD Int64__le(lua_State* L) {
+ /* Returns true if first Int64 <= second */
+ WSLUA_COMP_OP_FUNC(Int64,<=);
+}
+
+WSLUA_METHOD Int64_bnot(lua_State* L) {
+ /* Returns a Int64 of the bitwise 'not' operation. */
+ pushInt64(L,~(getInt64(L,1)));
+ WSLUA_RETURN(1); /* The Int64 object */
+}
+
+#define WSLUA_BIT_OP_FUNC(obj,op) \
+ gint32 i; \
+ obj num = get##obj(L,1); \
+ for (i = lua_gettop(L); i > 1; i--) { \
+ num op get##obj(L,i); \
+ } \
+ push##obj(L,num); \
+ return 1
+
+WSLUA_METHOD Int64_band(lua_State* L) {
+ /* Returns a Int64 of the bitwise 'and' operation, with the given number/Int64/UIn64. Note that multiple arguments are allowed. */
+ WSLUA_BIT_OP_FUNC(Int64,&=);
+ WSLUA_RETURN(1); /* The Int64 object */
+}
+
+WSLUA_METHOD Int64_bor(lua_State* L) {
+ /* Returns a Int64 of the bitwise 'or' operation, with the given number/Int64/UIn64. Note that multiple arguments are allowed. */
+ WSLUA_BIT_OP_FUNC(Int64,|=);
+ WSLUA_RETURN(1); /* The Int64 object */
+}
+
+WSLUA_METHOD Int64_bxor(lua_State* L) {
+ /* Returns a Int64 of the bitwise 'xor' operation, with the given number/Int64/UIn64. Note that multiple arguments are allowed. */
+ WSLUA_BIT_OP_FUNC(Int64,^=);
+ WSLUA_RETURN(1); /* The Int64 object */
+}
+
+WSLUA_METHOD Int64_lshift(lua_State* L) {
+ /* Returns a Int64 of the bitwise logical left-shift operation, by the given number of bits. */
+#define WSLUA_ARG_Int64_lshift_NUMBITS 2 /* The number of bits to left-shift by */
+ guint64 b = (guint64) getInt64(L,1);
+ guint32 n = luaL_checknumber(L,WSLUA_ARG_Int64_lshift_NUMBITS);
+ pushInt64(L,(gint64)(b << n));
+ WSLUA_RETURN(1); /* The Int64 object */
+}
+
+WSLUA_METHOD Int64_rshift(lua_State* L) {
+ /* Returns a Int64 of the bitwise logical right-shift operation, by the given number of bits. */
+#define WSLUA_ARG_Int64_rshift_NUMBITS 2 /* The number of bits to right-shift by */
+ guint64 b = (guint64) getInt64(L,1);
+ guint32 n = luaL_checknumber(L,WSLUA_ARG_Int64_rshift_NUMBITS);
+ pushInt64(L,(gint64)(b >> n));
+ WSLUA_RETURN(1); /* The Int64 object */
+}
+
+WSLUA_METHOD Int64_arshift(lua_State* L) {
+ /* Returns a Int64 of the bitwise arithmetic right-shift operation, by the given number of bits. */
+#define WSLUA_ARG_Int64_arshift_NUMBITS 2 /* The number of bits to right-shift by */
+ gint64 b = getInt64(L,1);
+ gint32 n = luaL_checknumber(L,WSLUA_ARG_Int64_arshift_NUMBITS);
+ pushInt64(L,(b >> n));
+ WSLUA_RETURN(1); /* The Int64 object */
+}
+
+WSLUA_METHOD Int64_rol(lua_State* L) {
+ /* Returns a Int64 of the bitwise left rotation operation, by the given number of bits (up to 63). */
+#define WSLUA_ARG_Int64_rol_NUMBITS 2 /* The number of bits to roll left by */
+ guint64 b = (guint64) getInt64(L,1);
+ guint32 n = luaL_checknumber(L,WSLUA_ARG_Int64_rol_NUMBITS);
+ pushInt64(L,(gint64)((b << n) | (b >> (64-n))));
+ WSLUA_RETURN(1); /* The Int64 object */
+}
+
+WSLUA_METHOD Int64_ror(lua_State* L) {
+ /* Returns a Int64 of the bitwise right rotation operation, by the given number of bits (up to 63). */
+#define WSLUA_ARG_Int64_ror_NUMBITS 2 /* The number of bits to roll right by */
+ guint64 b = (guint64) getInt64(L,1);
+ guint32 n = luaL_checknumber(L,WSLUA_ARG_Int64_ror_NUMBITS);
+ pushInt64(L,(gint64)((b << (64-n)) | (b >> n)));
+ WSLUA_RETURN(1); /* The Int64 object */
+}
+
+WSLUA_METHOD Int64_bswap(lua_State* L) {
+ /* Returns a Int64 of the bytes swapped. This can be used to convert little-endian 64 bit numbers to big-endian 64 bit numbers or vice versa. */
+ guint64 b = (guint64) getInt64(L,1);
+ guint64 result = 0;
+ size_t i;
+ for (i = 0; i < sizeof(gint64); i++) {
+ result <<= 8;
+ result |= (b & 0x00000000000000FF);
+ b >>= 8;
+ }
+ pushInt64(L,(gint64)result);
+ WSLUA_RETURN(1); /* The Int64 object */
+}
+
+/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */
+static int Int64__gc(lua_State* L _U_) {
+ return 0;
+}
+
+static const luaL_Reg Int64_methods[] = {
+ { "new", Int64_new },
+ { "max", Int64_max },
+ { "min", Int64_min },
+ { "tonumber", Int64_tonumber },
+ { "fromhex", Int64_fromhex },
+ { "tohex", Int64_tohex },
+ { "higher", Int64_higher },
+ { "lower", Int64_lower },
+ { "encode", Int64_encode },
+ { "decode", Int64_decode },
+ { "bnot", Int64_bnot },
+ { "band", Int64_band },
+ { "bor", Int64_bor },
+ { "bxor", Int64_bxor },
+ { "lshift", Int64_lshift },
+ { "rshift", Int64_rshift },
+ { "arshift", Int64_arshift },
+ { "rol", Int64_rol },
+ { "ror", Int64_ror },
+ { "bswap", Int64_bswap },
+ { NULL, NULL }
+};
+
+static const luaL_Reg Int64_meta[] = {
+ {"__tostring", Int64__tostring},
+ {"__concat", wslua__concat},
+ {"__unm", Int64__unm},
+ {"__add", Int64__add},
+ {"__sub", Int64__sub},
+ {"__mul", Int64__mul},
+ {"__div", Int64__div},
+ {"__mod", Int64__mod},
+ {"__pow", Int64__pow},
+ {"__eq", Int64__eq},
+ {"__lt", Int64__lt},
+ {"__le", Int64__le},
+ { NULL, NULL }
+};
+
+LUALIB_API int Int64_register(lua_State* L) {
+ WSLUA_REGISTER_CLASS(Int64);
+ return 0;
+}
+
+
+
+WSLUA_CLASS_DEFINE_BASE(UInt64,NOP,NOP,0);
+ /* UInt64 represents a 64 bit unsigned integer, similar to Int64. */
+
+/* A checkUInt64 but that also auto-converts numbers, strings, and Int64 to a guint64 */
+static guint64 getUInt64(lua_State *L, int i)
+{
+ gchar *end = NULL;
+ (void) end;
+ switch (lua_type(L,i))
+ {
+ case LUA_TNUMBER:
+ return luaL_checknumber(L,i);
+ case LUA_TSTRING:
+ return g_ascii_strtoull(luaL_checkstring(L,i), &end, 10);
+ case LUA_TUSERDATA:
+ if (isInt64(L, i)) {
+ return (UInt64) toInt64(L, i);
+ break;
+ }
+ /* fall through */
+ default:
+ return checkUInt64(L,i);
+ }
+}
+
+/* Encodes UInt64 userdata into Lua string struct with given endianess */
+void UInt64_pack(lua_State* L, luaL_Buffer *b, gint idx, gboolean asLittleEndian) {
+ guint64 value = checkUInt64(L,idx);
+ gint8 buff[sizeof(guint64)];
+
+ if (asLittleEndian) {
+ guint i;
+ for (i = 0; i < sizeof(guint64); i++) {
+ buff[i] = (value & 0xff);
+ value >>= 8;
+ }
+ }
+ else {
+ gint i;
+ for (i = sizeof(guint64) - 1; i >= 0; i--) {
+ buff[i] = (value & 0xff);
+ value >>= 8;
+ }
+ }
+ luaL_addlstring(b, (char*)buff, sizeof(guint64));
+}
+
+WSLUA_METHOD UInt64_encode(lua_State* L) {
+ /* Encodes the UInt64 number into an 8-byte Lua binary string, using given endianess */
+#define WSLUA_OPTARG_UInt64_encode_ENDIAN 2 /* If set to true then little-endian is used, if false then big-endian; if missing/nil, native host endian */
+ luaL_Buffer b;
+ gboolean asLittleEndian = (G_BYTE_ORDER == G_LITTLE_ENDIAN)? TRUE : FALSE;
+
+ if (lua_gettop(L) >= 2) {
+ if (lua_type(L,2) == LUA_TBOOLEAN)
+ asLittleEndian = lua_toboolean(L,2);
+ }
+
+ luaL_buffinit(L, &b);
+
+ UInt64_pack(L, &b, 1, asLittleEndian);
+
+ luaL_pushresult(&b);
+ WSLUA_RETURN(1); /* The Lua binary string */
+}
+
+/* Decodes from string buffer struct into UInt64 userdata, with given endianess */
+int UInt64_unpack(lua_State* L, const gchar *buff, gboolean asLittleEndian) {
+ guint64 value = 0;
+ gint i;
+
+ if (asLittleEndian) {
+ for (i = sizeof(guint64) - 1; i >= 0; i--) {
+ value <<= 8;
+ value |= (guint64)(guchar)buff[i];
+ }
+ }
+ else {
+ for (i = 0; i < (gint) sizeof(guint64); i++) {
+ value <<= 8;
+ value |= (guint64)(guchar)buff[i];
+ }
+ }
+
+ pushUInt64(L,value);
+ return 1;
+}
+
+WSLUA_CONSTRUCTOR UInt64_decode(lua_State* L) {
+ /* Decodes an 8-byte Lua binary string, using given endianess, into a new UInt64 object */
+#define WSLUA_ARG_UInt64_decode_STRING 1 /* The Lua string containing a binary 64-bit integer */
+#define WSLUA_OPTARG_UInt64_decode_ENDIAN 2 /* If set to true then little-endian is used, if false then big-endian; if missing/nil, native host endian */
+ gboolean asLittleEndian = (G_BYTE_ORDER == G_LITTLE_ENDIAN)? TRUE : FALSE;
+ size_t len = 0;
+ const gchar *s = luaL_checklstring(L, WSLUA_ARG_UInt64_decode_STRING, &len);
+
+ if (lua_gettop(L) >= WSLUA_OPTARG_UInt64_decode_ENDIAN) {
+ if (lua_type(L,WSLUA_OPTARG_UInt64_decode_ENDIAN) == LUA_TBOOLEAN)
+ asLittleEndian = lua_toboolean(L,WSLUA_OPTARG_UInt64_decode_ENDIAN);
+ }
+
+ if (len == sizeof(guint64)) {
+ UInt64_unpack(L, s, asLittleEndian);
+ } else {
+ lua_pushnil(L);
+ }
+
+ WSLUA_RETURN(1); /* The UInt64 object created, or nil on failure */
+}
+
+WSLUA_CONSTRUCTOR UInt64_new(lua_State* L) { /* Creates a UInt64 Object */
+#define WSLUA_OPTARG_UInt64_new_VALUE 1 /* A number, UInt64, Int64, or string of digits to assign the value of the new UInt64 (default=0) */
+#define WSLUA_OPTARG_UInt64_new_HIGHVALUE 2 /* If this is a number and the first argument was a number, then the first will be treated as a lower 32-bits, and this is the high-order 32 bit number */
+ guint64 value = 0;
+
+ if (lua_gettop(L) >= 1) {
+ switch(lua_type(L, WSLUA_OPTARG_UInt64_new_VALUE)) {
+ case LUA_TNUMBER:
+ value = (guint64)lua_tonumber(L, WSLUA_OPTARG_UInt64_new_VALUE);
+ if (lua_gettop(L) == 2 && lua_type(L, WSLUA_OPTARG_UInt64_new_HIGHVALUE) == LUA_TNUMBER) {
+ guint64 h = (guint64)lua_tonumber(L, WSLUA_OPTARG_UInt64_new_HIGHVALUE);
+ value &= 0x00000000FFFFFFFF;
+ h <<= 32; h &= 0xFFFFFFFF00000000;
+ value += h;
+ }
+ break;
+ case LUA_TSTRING:
+ case LUA_TUSERDATA:
+ value = getUInt64(L, WSLUA_OPTARG_UInt64_new_VALUE);
+ break;
+ default:
+ WSLUA_OPTARG_ERROR(UInt64_new,VALUE,"must be a number, UInt64, Int64, or string");
+ break;
+ }
+ }
+
+ pushUInt64(L,value);
+
+ WSLUA_RETURN(1); /* The new UInt64 object. */
+}
+
+WSLUA_CONSTRUCTOR UInt64_max(lua_State* L) { /* Gets the max possible value */
+ pushUInt64(L,G_MAXUINT64);
+ WSLUA_RETURN(1); /* The max value. */
+}
+
+WSLUA_CONSTRUCTOR UInt64_min(lua_State* L) { /* Gets the min possible value (i.e., 0) */
+ pushUInt64(L,0);
+ WSLUA_RETURN(1); /* The min value. */
+}
+
+WSLUA_METHOD UInt64_tonumber(lua_State* L) {
+ /* Returns a Lua number of the UInt64 value - this may lose precision. */
+ lua_pushnumber(L,(lua_Number)checkUInt64(L,1));
+ WSLUA_RETURN(1); /* The Lua number */
+}
+
+WSLUA_METAMETHOD UInt64__tostring(lua_State* L) {
+ /* Converts the UInt64 into a string */
+ guint64 num = getUInt64(L,1);
+ gchar s[LUATYPE64_STRING_SIZE];
+ if (sprintf(s, "%" G_GINT64_MODIFIER "u",(guint64)num) < 0)
+ luaL_error(L, "Error writing UInt64 to a string");
+ lua_pushstring(L,s);
+ WSLUA_RETURN(1); /* The Lua string */
+}
+
+WSLUA_CONSTRUCTOR UInt64_fromhex(lua_State* L) { /* Creates a UInt64 object from the given hex string */
+ guint64 result = 0;
+ size_t len = 0;
+ const gchar *s = luaL_checklstring(L,1,&len);
+
+ if (s && len > 0) {
+ sscanf(s, "%" G_GINT64_MODIFIER "x", &result);
+ }
+ pushUInt64(L,result);
+ WSLUA_RETURN(1); /* The new UInt64 object. */
+}
+
+WSLUA_METHOD UInt64_tohex(lua_State* L) {
+ /* Returns a hex string of the UInt64 value. */
+#define WSLUA_OPTARG_Int64_new_NUMBYTES 2 /* The number of hex-chars/nibbles to generate, negative means uppercase (default=16) */
+ guint64 b = getUInt64(L,1);
+ gint n = luaL_optint(L, WSLUA_OPTARG_Int64_new_NUMBYTES, 16);
+ const gchar *hexdigits = "0123456789abcdef";
+ gchar buf[16];
+ gint i;
+ if (n < 0) { n = -n; hexdigits = "0123456789ABCDEF"; }
+ if (n > 16) n = 16;
+ for (i = n-1; i >= 0; --i) { buf[i] = hexdigits[b & 15]; b >>= 4; }
+ lua_pushlstring(L, buf, (size_t)n);
+ WSLUA_RETURN(1); /* The string hex */
+}
+
+WSLUA_METHOD UInt64_higher(lua_State* L) {
+ /* Returns a Lua number of the higher 32-bits of the UInt64 value. */
+ guint64 num = getUInt64(L,1);
+ guint64 b = num;
+ lua_Number n;
+ b &= 0xFFFFFFFF00000000;
+ b >>= 32;
+ n = (lua_Number)(guint32)(b & 0x00000000FFFFFFFFF);
+ lua_pushnumber(L,n);
+ WSLUA_RETURN(1); /* The Lua number */
+}
+
+WSLUA_METHOD UInt64_lower(lua_State* L) {
+ /* Returns a Lua number of the lower 32-bits of the UInt64 value. */
+ guint64 b = getUInt64(L,1);
+ lua_pushnumber(L,(guint32)(b & 0x00000000FFFFFFFFF));
+ WSLUA_RETURN(1); /* The Lua number */
+}
+
+WSLUA_METAMETHOD UInt64__unm(lua_State* L) {
+ /* Returns the UInt64, in a new UInt64, since unsigned integers can't be negated. */
+ pushUInt64(L,getUInt64(L,1));
+ WSLUA_RETURN(1); /* The UInt64 object */
+}
+
+WSLUA_METAMETHOD UInt64__add(lua_State* L) {
+ /* Adds two UInt64 together and returns a new one (this may wrap the value) */
+ WSLUA_MATH_OP_FUNC(UInt64,+);
+}
+
+WSLUA_METAMETHOD UInt64__sub(lua_State* L) {
+ /* Subtracts two UInt64 and returns a new one (this may wrap the value) */
+ WSLUA_MATH_OP_FUNC(UInt64,-);
+}
+
+WSLUA_METAMETHOD UInt64__mul(lua_State* L) {
+ /* Multiplies two UInt64 and returns a new one (this may truncate the value) */
+ WSLUA_MATH_OP_FUNC(UInt64,*);
+}
+
+WSLUA_METAMETHOD UInt64__div(lua_State* L) {
+ /* Divides two UInt64 and returns a new one (integer divide, no remainder) */
+ WSLUA_MATH_OP_FUNC(UInt64,/);
+}
+
+WSLUA_METAMETHOD UInt64__mod(lua_State* L) {
+ /* Divides two UInt64 and returns a new one of the remainder */
+ WSLUA_MATH_OP_FUNC(UInt64,%);
+}
+
+WSLUA_METAMETHOD UInt64__pow(lua_State* L) {
+ /* The first UInt64 is taken to the power of the second UInt64/number, returning a new one (this may truncate the value) */
+ guint64 num1 = getUInt64(L,1);
+ guint64 num2 = getUInt64(L,2);
+ guint64 result;
+ if (num1 == 2) {
+ result = (num2 >= 8 * (guint64) sizeof(guint64)) ? 0 : ((guint64)1 << num2);
+ }
+ else {
+ for (result = 1; num2 > 0; num2 >>= 1) {
+ if (num2 & 1) result *= num1;
+ num1 *= num1;
+ }
+ }
+ pushUInt64(L,result);
+ WSLUA_RETURN(1); /* The UInt64 object */
+}
+
+WSLUA_METAMETHOD UInt64__eq(lua_State* L) {
+ /* Returns true if both UInt64 are equal */
+ WSLUA_COMP_OP_FUNC(UInt64,==);
+}
+
+WSLUA_METAMETHOD UInt64__lt(lua_State* L) {
+ /* Returns true if first UInt64 < second */
+ WSLUA_COMP_OP_FUNC(UInt64,<);
+}
+
+WSLUA_METAMETHOD UInt64__le(lua_State* L) {
+ /* Returns true if first UInt64 <= second */
+ WSLUA_COMP_OP_FUNC(UInt64,<=);
+}
+
+WSLUA_METHOD UInt64_bnot(lua_State* L) {
+ /* Returns a UInt64 of the bitwise 'not' operation. */
+ pushUInt64(L,~(getUInt64(L,1)));
+ WSLUA_RETURN(1); /* The UInt64 object */
+}
+
+WSLUA_METHOD UInt64_band(lua_State* L) {
+ /* Returns a UInt64 of the bitwise 'and' operation, with the given number/Int64/UIn64. Note that multiple arguments are allowed. */
+ WSLUA_BIT_OP_FUNC(UInt64,&=);
+ WSLUA_RETURN(1); /* The UInt64 object */
+}
+
+WSLUA_METHOD UInt64_bor(lua_State* L) {
+ /* Returns a UInt64 of the bitwise 'or' operation, with the given number/Int64/UIn64. Note that multiple arguments are allowed. */
+ WSLUA_BIT_OP_FUNC(UInt64,|=);
+ WSLUA_RETURN(1); /* The UInt64 object */
+}
+
+WSLUA_METHOD UInt64_bxor(lua_State* L) {
+ /* Returns a UInt64 of the bitwise 'xor' operation, with the given number/Int64/UIn64. Note that multiple arguments are allowed. */
+ WSLUA_BIT_OP_FUNC(UInt64,^=);
+ WSLUA_RETURN(1); /* The UInt64 object */
+}
+
+WSLUA_METHOD UInt64_lshift(lua_State* L) {
+ /* Returns a UInt64 of the bitwise logical left-shift operation, by the given number of bits. */
+#define WSLUA_ARG_UInt64_lshift_NUMBITS 2 /* The number of bits to left-shift by */
+ guint64 b = getUInt64(L,1);
+ guint32 n = luaL_checknumber(L,WSLUA_ARG_UInt64_lshift_NUMBITS);
+ pushUInt64(L,(b << n));
+ WSLUA_RETURN(1); /* The UInt64 object */
+}
+
+WSLUA_METHOD UInt64_rshift(lua_State* L) {
+ /* Returns a UInt64 of the bitwise logical right-shift operation, by the given number of bits. */
+#define WSLUA_ARG_UInt64_rshift_NUMBITS 2 /* The number of bits to right-shift by */
+ guint64 b = getUInt64(L,1);
+ guint32 n = luaL_checknumber(L,WSLUA_ARG_UInt64_rshift_NUMBITS);
+ pushUInt64(L,(b >> n));
+ WSLUA_RETURN(1); /* The UInt64 object */
+}
+
+WSLUA_METHOD UInt64_arshift(lua_State* L) {
+ /* Returns a UInt64 of the bitwise arithmetic right-shift operation, by the given number of bits. */
+#define WSLUA_ARG_UInt64_arshift_NUMBITS 2 /* The number of bits to right-shift by */
+ guint64 b = getUInt64(L,1);
+ guint32 n = luaL_checknumber(L,WSLUA_ARG_UInt64_arshift_NUMBITS);
+ pushUInt64(L,(b >> n));
+ WSLUA_RETURN(1); /* The UInt64 object */
+}
+
+WSLUA_METHOD UInt64_rol(lua_State* L) {
+ /* Returns a UInt64 of the bitwise left rotation operation, by the given number of bits (up to 63). */
+#define WSLUA_ARG_UInt64_rol_NUMBITS 2 /* The number of bits to roll left by */
+ guint64 b = getUInt64(L,1);
+ guint32 n = luaL_checknumber(L,WSLUA_ARG_UInt64_rol_NUMBITS);
+ pushUInt64(L,((b << n) | (b >> (64-n))));
+ WSLUA_RETURN(1); /* The UInt64 object */
+}
+
+WSLUA_METHOD UInt64_ror(lua_State* L) {
+ /* Returns a UInt64 of the bitwise right rotation operation, by the given number of bits (up to 63). */
+#define WSLUA_ARG_UInt64_ror_NUMBITS 2 /* The number of bits to roll right by */
+ guint64 b = getUInt64(L,1);
+ guint32 n = luaL_checknumber(L,WSLUA_ARG_UInt64_ror_NUMBITS);
+ pushUInt64(L,((b << (64-n)) | (b >> n)));
+ WSLUA_RETURN(1); /* The UInt64 object */
+}
+
+WSLUA_METHOD UInt64_bswap(lua_State* L) {
+ /* Returns a UInt64 of the bytes swapped. This can be used to convert little-endian 64 bit numbers to big-endian 64 bit numbers or vice versa. */
+ guint64 b = getUInt64(L,1);
+ guint64 result = 0;
+ size_t i;
+ for (i = 0; i < sizeof(guint64); i++) {
+ result <<= 8;
+ result |= (b & 0x00000000000000FF);
+ b >>= 8;
+ }
+ pushUInt64(L,result);
+ WSLUA_RETURN(1); /* The UInt64 object */
+}
+
+/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */
+static int UInt64__gc(lua_State* L _U_) {
+ return 0;
+}
+
+static const luaL_Reg UInt64_methods[] = {
+ { "new", UInt64_new },
+ { "max", UInt64_max },
+ { "min", UInt64_min },
+ { "tonumber", UInt64_tonumber },
+ { "fromhex", UInt64_fromhex },
+ { "tohex", UInt64_tohex },
+ { "higher", UInt64_higher },
+ { "lower", UInt64_lower },
+ { "encode", UInt64_encode },
+ { "decode", UInt64_decode },
+ { "bnot", UInt64_bnot },
+ { "band", UInt64_band },
+ { "bor", UInt64_bor },
+ { "bxor", UInt64_bxor },
+ { "lshift", UInt64_lshift },
+ { "rshift", UInt64_rshift },
+ { "arshift", UInt64_arshift },
+ { "rol", UInt64_rol },
+ { "ror", UInt64_ror },
+ { "bswap", UInt64_bswap },
+ { NULL, NULL }
+};
+
+static const luaL_Reg UInt64_meta[] = {
+ {"__tostring", UInt64__tostring},
+ {"__concat", wslua__concat},
+ {"__unm", UInt64__unm},
+ {"__add", UInt64__add},
+ {"__sub", UInt64__sub},
+ {"__mul", UInt64__mul},
+ {"__div", UInt64__div},
+ {"__mod", UInt64__mod},
+ {"__pow", UInt64__pow},
+ {"__eq", UInt64__eq},
+ {"__lt", UInt64__lt},
+ {"__le", UInt64__le},
+ { NULL, NULL }
+};
+
+LUALIB_API int UInt64_register(lua_State* L) {
+ WSLUA_REGISTER_CLASS(UInt64);
+ return 0;
+}
+
+
+/* I, Hadriel Kaplan, the author of wslua_int6464.c, wish to put it in
+ * the Public Domain. That is not universally accepted, however,
+ * so you may license it under the FreeBSD License instead, which is an open
+ * source license approved for GPL use as well as commercial etc.
+ * It's even less restrictive than the MIT license, because it requires
+ * no attribution anywhere - I don't *want* attribution.
+ *
+Copyright (C) 2013 Hadriel Kaplan <hadrielk@yahoo.com>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The views and conclusions contained in the software and documentation are those
+of the authors and should not be interpreted as representing official policies,
+either expressed or implied, of the FreeBSD Project.
+*/
diff --git a/epan/wslua/wslua_tree.c b/epan/wslua/wslua_tree.c
index de1ef14790..1cbc6253a7 100644
--- a/epan/wslua/wslua_tree.c
+++ b/epan/wslua/wslua_tree.c
@@ -211,10 +211,10 @@ static int TreeItem_add_item_any(lua_State *L, gboolean little_endian) {
item = proto_tree_add_bytes(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len, (const guint8*) luaL_checkstring(L,1));
break;
case FT_UINT64:
- item = proto_tree_add_uint64(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,*(UInt64)checkUInt64(L,1));
+ item = proto_tree_add_uint64(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,checkUInt64(L,1));
break;
case FT_INT64:
- item = proto_tree_add_int64(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,*(Int64)checkInt64(L,1));
+ item = proto_tree_add_int64(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,checkInt64(L,1));
break;
case FT_IPv4:
item = proto_tree_add_ipv4(tree_item->tree,hfid,tvbr->tvb->ws_tvb,tvbr->offset,tvbr->len,*((const guint32*)(checkAddress(L,1)->data)));
diff --git a/epan/wslua/wslua_tvb.c b/epan/wslua/wslua_tvb.c
index 8ef7108b27..3c67bd3ffc 100644
--- a/epan/wslua/wslua_tvb.c
+++ b/epan/wslua/wslua_tvb.c
@@ -575,18 +575,6 @@ WSLUA_METAMETHOD Tvb__call(lua_State* L) {
}
#endif
-WSLUA_METAMETHOD wslua__concat(lua_State* L) {
- /* Concatenate two objects to a string */
- if (!luaL_callmeta(L,1,"__tostring"))
- lua_pushvalue(L,1);
- if (!luaL_callmeta(L,2,"__tostring"))
- lua_pushvalue(L,2);
-
- lua_concat(L,2);
-
- return 1;
-}
-
WSLUA_CLASS_DEFINE(TvbRange,FAIL_ON_NULL("expired tvbrange"),NOP);
/*
A TvbRange represents a usable range of a Tvb and is used to extract data from the Tvb that generated it
@@ -761,9 +749,7 @@ WSLUA_METHOD TvbRange_uint64(lua_State* L) {
case 6:
case 7:
case 8: {
- UInt64 num = (UInt64)g_malloc(sizeof(guint64));
- *num = tvb_get_ntoh64(tvbr->tvb->ws_tvb,tvbr->offset);
- pushUInt64(L,num);
+ pushUInt64(L,tvb_get_ntoh64(tvbr->tvb->ws_tvb,tvbr->offset));
WSLUA_RETURN(1);
}
default:
@@ -793,9 +779,7 @@ WSLUA_METHOD TvbRange_le_uint64(lua_State* L) {
case 6:
case 7:
case 8: {
- UInt64 num = (UInt64)g_malloc(sizeof(guint64));
- *num = tvb_get_letoh64(tvbr->tvb->ws_tvb,tvbr->offset);
- pushUInt64(L,num);
+ pushUInt64(L,tvb_get_letoh64(tvbr->tvb->ws_tvb,tvbr->offset));
WSLUA_RETURN(1);
}
default:
@@ -888,9 +872,7 @@ WSLUA_METHOD TvbRange_int64(lua_State* L) {
case 6:
case 7:
case 8: {
- Int64 num = (Int64)g_malloc(sizeof(gint64));
- *num = (gint64)tvb_get_ntoh64(tvbr->tvb->ws_tvb,tvbr->offset);
- pushInt64(L,num);
+ pushInt64(L,(gint64)tvb_get_ntoh64(tvbr->tvb->ws_tvb,tvbr->offset));
WSLUA_RETURN(1);
}
default:
@@ -920,9 +902,7 @@ WSLUA_METHOD TvbRange_le_int64(lua_State* L) {
case 6:
case 7:
case 8: {
- Int64 num = (Int64)g_malloc(sizeof(gint64));
- *num = (gint64)tvb_get_letoh64(tvbr->tvb->ws_tvb,tvbr->offset);
- pushInt64(L,num);
+ pushInt64(L,(gint64)tvb_get_letoh64(tvbr->tvb->ws_tvb,tvbr->offset));
WSLUA_RETURN(1);
}
default:
@@ -1335,9 +1315,7 @@ WSLUA_METHOD TvbRange_bitfield(lua_State* L) {
lua_pushnumber(L,tvb_get_bits32(tvbr->tvb->ws_tvb,tvbr->offset*8 + pos, len, FALSE));
return 1;
} else if (len <= 64) {
- UInt64 num = (UInt64)g_malloc(sizeof(guint64));
- *num = tvb_get_bits64(tvbr->tvb->ws_tvb,tvbr->offset*8 + pos, len, FALSE);
- pushUInt64(L,num);
+ pushUInt64(L,tvb_get_bits64(tvbr->tvb->ws_tvb,tvbr->offset*8 + pos, len, FALSE));
WSLUA_RETURN(1); /* The bitfield value */
} else {
luaL_error(L,"TvbRange:bitfield() does not handle %d bits",len);
@@ -1504,81 +1482,3 @@ int TvbRange_register(lua_State* L) {
return 0;
}
-WSLUA_CLASS_DEFINE(Int64,FAIL_ON_NULL("null int64"),NOP);
-/*
- Int64 represents a 64 bit integer.
- Lua uses one single number representation which can be chosen at compile time and since
- it is often set to IEEE 754 double precision floating point, we cannot store a 64 bit integer
- with full precision.
- For details, see: http://lua-users.org/wiki/FloatingPoint
- */
-
-WSLUA_METAMETHOD Int64__tostring(lua_State* L) {
- /* Converts the Int64 into a string */
- Int64 num = checkInt64(L,1);
- lua_pushstring(L,ep_strdup_printf("%" G_GINT64_MODIFIER "d",(gint64)*(num)));
- return 1;
-}
-
-/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */
-static int Int64__gc(lua_State* L) {
- Int64 num = checkInt64(L,1);
-
- if (!num) return 0;
-
- g_free(num);
-
- return 0;
-}
-
-static const luaL_Reg Int64_methods[] = {
- { NULL, NULL }
-};
-
-static const luaL_Reg Int64_meta[] = {
- {"__tostring", Int64__tostring},
- {"__concat", wslua__concat},
- { NULL, NULL }
-};
-
-int Int64_register(lua_State* L) {
- WSLUA_REGISTER_CLASS(Int64);
- return 0;
-}
-
-WSLUA_CLASS_DEFINE(UInt64,FAIL_ON_NULL("null uint64"),NOP);
- /* UInt64 represents a 64 bit unsigned integer. */
-
-WSLUA_METAMETHOD UInt64__tostring(lua_State* L) {
- /* Converts the UInt64 into a string */
- UInt64 num = checkUInt64(L,1);
- lua_pushstring(L,ep_strdup_printf("%" G_GINT64_MODIFIER "u",(guint64)*(num)));
- return 1;
-}
-
-/* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */
-static int UInt64__gc(lua_State* L) {
- UInt64 num = checkUInt64(L,1);
-
- if (!num) return 0;
-
- g_free(num);
-
- return 0;
-}
-
-static const luaL_Reg UInt64_methods[] = {
- { NULL, NULL }
-};
-
-static const luaL_Reg UInt64_meta[] = {
- {"__tostring", UInt64__tostring},
- {"__concat", wslua__concat},
- { NULL, NULL }
-};
-
-int UInt64_register(lua_State* L) {
- WSLUA_REGISTER_CLASS(UInt64);
- return 0;
-}
-
diff --git a/epan/wslua/wslua_util.c b/epan/wslua/wslua_util.c
index cc89e99198..9e95d557f4 100644
--- a/epan/wslua/wslua_util.c
+++ b/epan/wslua/wslua_util.c
@@ -32,6 +32,19 @@
#include <math.h>
#include <epan/stat_cmd_args.h>
+
+WSLUA_API int wslua__concat(lua_State* L) {
+ /* Concatenate two objects to a string */
+ if (!luaL_callmeta(L,1,"__tostring"))
+ lua_pushvalue(L,1);
+ if (!luaL_callmeta(L,2,"__tostring"))
+ lua_pushvalue(L,2);
+
+ lua_concat(L,2);
+
+ return 1;
+}
+
WSLUA_API gboolean wslua_optbool(lua_State* L, int n, gboolean def) {
gboolean val = FALSE;
diff --git a/test/lua/int64.lua b/test/lua/int64.lua
new file mode 100755
index 0000000000..c0c8f9dd45
--- /dev/null
+++ b/test/lua/int64.lua
@@ -0,0 +1,341 @@
+
+-- This is a test script for tshark/wireshark.
+-- This script runs inside tshark/wireshark, so to run it do:
+-- wireshark -X lua_script:<path_to_testdir>/lua/int64.lua
+-- tshark -r bogus.cap -X lua_script:<path_to_testdir>/lua/int64.lua
+
+-- Tests Int64/UInt64 functions
+
+local function testing(...)
+ print("---- Testing "..tostring(...).." ----")
+end
+
+local function test(name, ...)
+ io.stdout:write("test "..name.."...")
+ if (...) == true then
+ io.stdout:write("passed\n")
+ else
+ io.stdout:write("failed!\n")
+ error(name.." test failed!")
+ end
+end
+
+-- you can't compare (use the '==') userdata objects with numbers, so this function does it instead.
+function checkeq(arg1,arg2)
+ if arg1 == arg2 then
+ return true
+ elseif type(arg1) == 'userdata' and arg1.tonumber then
+ if type(arg2) == 'userdata' and arg2.tonumber then
+ return arg1:tonumber() == arg2:tonumber()
+ else
+ return arg1:tonumber() == arg2
+ end
+ elseif type(arg2) == 'userdata' and arg2.tonumber then
+ return arg1 == arg2:tonumber()
+ else
+ return false
+ end
+end
+
+-----------------------------
+
+testing("Int64/UInt64 library")
+
+local testtbl = { { ["type"]=Int64, ["name"]="Int64" } , { ["type"]=UInt64, ["name"]="UInt64" } }
+
+for i,t in ipairs(testtbl) do
+
+ local function testing(...)
+ print("---- Testing "..t.name..": "..tostring(...).." ----")
+ end
+
+ local function test(name, ...)
+ io.stdout:write("test "..t.name.."-"..name.."...")
+ if (...) == true then
+ io.stdout:write("passed\n")
+ else
+ io.stdout:write("failed!\n")
+ error(name.." test failed!")
+ end
+ end
+
+ testing("class")
+ local obj = t.type
+
+ for name, val in pairs(obj) do
+ print("\t"..name.." = "..type(val))
+ end
+
+ test("class1",type(obj) == 'table')
+ test("class2",type(obj.new) == 'function')
+ test("class3",type(obj.max) == 'function')
+ test("class4",type(obj.min) == 'function')
+ test("class5",type(obj.tonumber) == 'function')
+ test("class6",type(obj.fromhex) == 'function')
+ test("class7",type(obj.tohex) == 'function')
+ test("class8",type(obj.higher) == 'function')
+ test("class9",type(obj.lower) == 'function')
+
+
+ testing("new, tonumber, tostring")
+ local val = 12345
+ local my64a = obj.new(val)
+ local my64b = obj.new(tostring(val))
+ local zero = obj.new(0)
+ -- remember in Lua it's a double, so only precise up to 9,007,199,254,740,992
+ local my64c = obj.new(val,100)
+ local valc = (100 * 4294967296) + val
+ print(tostring(my64c))
+ local my64z = obj.new(0,0)
+ local my64d = obj.new(0,100)
+ local vald = (100 * 4294967296)
+
+ test("new1",checkeq(my64a,val))
+ test("new2",checkeq(my64b,val))
+ test("new3",checkeq(my64a,obj.new(my64b)))
+ test("new4",checkeq(valc,my64c))
+ test("new5",checkeq(0,my64z))
+ test("new6",obj.new(0,1):tonumber() == (2^32))
+ if t.name == "Int64" then
+ test("new7",obj.new(-1):tonumber() == -1)
+ test("new8",obj.new(0,-1):tonumber() == -4294967296)
+ test("new9",obj.new(obj.new(-1)):tonumber() == -1)
+ end
+
+ test("tonumber1",val == my64a:tonumber())
+ test("tonumber2",valc == my64c:tonumber())
+ test("tonumber3",vald == my64d:tonumber())
+ test("tonumber4",0 == my64z:tonumber())
+
+ test("tostring1", tostring(my64a)==tostring(val))
+ test("tostring2",tostring(my64b)==tostring(val))
+ test("tostring3",tostring(my64c)==tostring(valc))
+ test("tostring4",tostring(my64d)==tostring(vald))
+
+
+ testing("compare ops")
+
+ test("eq", my64a == my64b)
+
+ test("le1", my64a <= my64b)
+ test("le2", my64a <= my64c)
+ test("le3", my64z <= my64c)
+
+ test("ge1", my64a >= my64b)
+ test("ge2", my64c >= my64b)
+ test("ge2", my64c >= my64z)
+
+ test("neq1",not(my64a ~= my64b))
+ test("neq2",my64a ~= obj.new(0))
+ test("neq2",my64a ~= my64c)
+
+ test("gt1",my64a > my64z)
+ test("gt2",my64c > my64a)
+
+ test("lt1",not(my64a < my64b))
+ test("lt2",my64a < my64c)
+
+
+ testing("math ops")
+
+ test("add1",checkeq(my64a + my64b, val + val))
+ test("add2",my64a + my64z == my64b)
+ test("add3",my64a + my64b == my64b + my64a)
+ test("add4",my64d + my64a == my64c)
+ test("add5",checkeq(my64a + vald, valc))
+ test("add6",checkeq(vald + my64a, valc))
+
+ test("sub1",checkeq(my64a - my64b, 0))
+ test("sub2",my64a - my64b == my64z)
+ test("sub3",my64a - my64b == my64b - my64a)
+ test("sub4",my64c - my64a == my64d)
+ test("sub5",checkeq(my64a - val, 0))
+
+ test("mod1",checkeq(my64a % my64b, 0))
+ test("mod2",checkeq(my64c % my64b, valc % val))
+ test("mod3",checkeq(my64c % val, valc % val))
+ test("mod4",checkeq(val % my64c, val % valc))
+
+ test("div1",checkeq(my64a / my64b, 1))
+ test("div2",checkeq(my64a / val, 1))
+ test("div3",checkeq(val / my64a, 1))
+ test("div4",my64c / my64d == obj.new(1))
+
+ test("pow1",checkeq(my64a ^ 1, val))
+ test("pow2",checkeq(my64a ^ obj.new(2), val ^ 2))
+ test("pow3",checkeq(my64a ^ obj.new(3), val ^ 3))
+ test("pow4",checkeq(my64c ^ 1, valc ^ 1))
+
+ test("mul1",checkeq(my64a * obj.new(1), my64b))
+ test("mul2",checkeq(my64a * my64b, my64b * my64a))
+ test("mul3",checkeq(my64a * 1, my64b))
+ test("mul4",checkeq(2 * my64c, 2 * valc))
+
+ if t.name == "Int64" then
+ -- unary minus on UInt64 is illogical, but oh well
+ test("unm1",checkeq(-my64a,-val))
+ test("unm2",checkeq(string.sub(tostring(-my64a),1,1), "-"))
+ test("unm3",checkeq(-my64c,-valc))
+ else
+ test("unm1",checkeq(-my64a,val))
+ test("unm2",checkeq(string.sub(tostring(-my64a),1,1), "1"))
+ test("unm3",checkeq(-my64c,valc))
+ end
+ test("unm4",checkeq(-my64z,0))
+
+ testing("methods")
+
+ test("higher1",my64a:higher() == 0)
+ test("higher2",my64c:higher() == 100)
+
+ test("lower1",my64a:lower() == val)
+ test("lower2",my64c:lower() == val)
+ test("lower3",my64d:lower() == 0)
+
+ local vale1 = 3735928559 -- yields hex of deadbeef
+ local vale2 = 5045997 -- yields 4cfeed
+ local my64e = obj.new(vale1, vale2)
+ test("fromhex1",obj.fromhex("0000000000003039") == my64a);
+ test("fromhex2",obj.fromhex("3039") == my64a);
+ test("fromhex3",obj.fromhex("0000006400003039") == my64c);
+ test("fromhex4",obj.fromhex("0000000000000000") == my64z);
+ test("fromhex5",obj.fromhex("004cfeeddeadbeef") == my64e);
+ test("fromhex6",obj.fromhex("4cFEEDDEADBEEF") == my64e);
+
+ test("tohex1",my64a:tohex() == "0000000000003039")
+ test("tohex2",my64c:tohex(16) == "0000006400003039")
+ test("tohex3",my64z:tohex() == "0000000000000000")
+ test("tohex4",my64e:tohex() == "004cfeeddeadbeef")
+ test("tohex5",my64e:tohex(8) == "deadbeef")
+ test("tohex6",my64e:tohex(-8) == "DEADBEEF")
+
+ test("encode1",my64a:encode(true) == "\57\48\00\00\00\00\00\00")
+ test("encode2",my64a:encode(false) == "\00\00\00\00\00\00\48\57")
+ test("encode3",my64c:encode(false) == "\00\00\00\100\00\00\48\57")
+
+ test("decode1",obj.decode("\57\48\00\00\00\00\00\00", true) == my64a)
+ test("decode2",obj.decode("\00\00\00\00\00\00\48\57", false) == my64a)
+ test("decode3",obj.decode("\00\00\00\100\00\00\48\57", false) == my64c)
+
+
+ local function testpower(b)
+ testing("powers of "..b)
+ b=obj.new(b)
+ local z=obj.new(1)
+ for i=0,100 do
+ print(i,z,b^i)
+ assert(z==b^i)
+ z=b*z
+ end
+ end
+
+ testpower(2)
+ testpower(3)
+
+ testing"factorials"
+
+ F={
+ [1]="1",
+ [2]="2",
+ [3]="6",
+ [4]="24",
+ [5]="120",
+ [6]="720",
+ [7]="5040",
+ [8]="40320",
+ [9]="362880",
+ [10]="3628800",
+ [11]="39916800",
+ [12]="479001600",
+ [13]="6227020800",
+ [14]="87178291200",
+ [15]="1307674368000",
+ [16]="20922789888000",
+ [17]="355687428096000",
+ [18]="6402373705728000",
+ [19]="121645100408832000",
+ [20]="2432902008176640000",
+ }
+ z=obj.new(1)
+ f=1
+ for i=1,20 do
+ z=z*i
+ f=f*i
+ s=obj.tonumber(z)
+ print(i,z,f,f==obj.tonumber(z),tostring(z)==F[i])
+ --print(i,int64.new(F[i]))
+ end
+
+ testing("bit operations")
+
+ test("band1",checkeq(obj.new(1):band(1), 1))
+ test("band2",checkeq(obj.new(1):band(0), 0))
+ test("band3",checkeq(obj.new(4294967295,100):band(4294967295), 4294967295))
+ test("band4",obj.new(4294967295,100):band(obj.new(0,100),obj.new(0,100),obj.new(0,100)) == obj.new(0,100))
+ test("band5",checkeq(obj.new(4294967295,100):band(obj.new(0,100),obj.new(0)), 0))
+
+ test("bor1",checkeq(obj.new(1):bor(1), 1))
+ test("bor2",checkeq(obj.new(1):bor(0), 1))
+ test("bor3",checkeq(obj.new(0):bor(0), 0))
+ test("bor4",obj.new(0,100):bor(4294967295) == obj.new(4294967295,100))
+ test("bor5",obj.new(1):bor(obj.new(2),obj.new(4),obj.new(8),16,32,64,128) == obj.new(255))
+
+ test("bxor1",checkeq(obj.new(1):bxor(1), 0))
+ test("bxor2",checkeq(obj.new(1):bxor(0), 1))
+ test("bxor3",checkeq(obj.new(0):bxor(0), 0))
+ test("bxor4",obj.new(4294967295,100):bxor(obj.new(0,100)) == obj.new(4294967295))
+ test("bxor5",obj.new(1):bxor(obj.new(2),obj.new(4),obj.new(8),16,32,64,128) == obj.new(255))
+
+ test("bnot1",checkeq(obj.new(4294967295,4294967295):bnot(), 0))
+ test("bnot2",obj.new(0):bnot() == obj.new(4294967295,4294967295))
+ test("bnot3",obj.new(0xaaaaaaaa,0xaaaaaaaa):bnot() == obj.new( 0x55555555, 0x55555555))
+
+ test("bsawp1",obj.new( 0x01020304, 0x05060708 ):bswap() == obj.new( 0x08070605, 0x04030201 ))
+ test("bsawp2",obj.new( 0xFF020304, 0xFF060708 ):bswap() == obj.new( 0x080706FF, 0x040302FF ))
+
+ test("lshift1",obj.new( 0x01020304, 0x0506070F ):lshift(4) == obj.new( 0x10203040, 0x506070f0 ))
+ test("lshift2",obj.new( 0x0102030F, 0x05060708 ):lshift(63) == obj.new( 0, 0x80000000 ))
+ if t.name == "Int64" then
+ test("lshift3",checkeq(obj.new( 0x0102030F, 0x05060708 ):lshift(63), -9223372036854775808))
+ else
+ test("lshift3",obj.new( 0x0102030F, 0x05060708 ):lshift(63) == obj.new( 0, 0x80000000 ))
+ end
+
+ test("rshift1",obj.new( 0x01020304, 0xF5060708 ):rshift(4) == obj.new( 0x80102030, 0x0F506070 ))
+ test("rshift2",checkeq(obj.new( 0x01020304, 0xF5060708 ):rshift(63), 1))
+
+ if t.name == "Int64" then
+ test("arshift1",obj.new( 0x01020304, 0xF5060708 ):arshift(4) == obj.new( 0x80102030, 0xFF506070 ))
+ test("arshift2",obj.new( 0x01020304, 0xF5060708 ):arshift(63) == obj.new( 0xFFFFFFFF, 0xFFFFFFFF ))
+ else
+ test("arshift1",obj.new( 0x01020304, 0xF5060708 ):arshift(4) == obj.new( 0x80102030, 0x0F506070 ))
+ test("arshift2",checkeq(obj.new( 0x01020304, 0xF5060708 ):arshift(63),1))
+ end
+ test("arshift3",obj.new( 0x01020304, 0x05060708 ):arshift(4) == obj.new( 0x80102030, 0x00506070 ))
+ test("arshift4",checkeq(obj.new( 0x01020304, 0x05060708 ):arshift(63), 0))
+
+ test("rol1",obj.new( 0x01020304, 0xF5060708 ):rol(4) == obj.new( 0x1020304F, 0x50607080 ))
+ test("rol2",obj.new( 0x01020304, 0xF5060708 ):rol(32):rol(32) == obj.new( 0x01020304, 0xF5060708 ))
+
+ test("ror1",obj.new( 0x01020304, 0xF5060708 ):ror(4) == obj.new( 0x80102030, 0x4F506070 ))
+ test("ror2",obj.new( 0x01020304, 0xF5060708 ):ror(32):ror(32) == obj.new( 0x01020304, 0xF5060708 ))
+
+end
+
+testing("min and max values")
+z=Int64.new(2)
+z=z^63-1
+test("max1",tostring(Int64.max()) == "9223372036854775807")
+test("max2",Int64.max() == Int64.new(4294967295, 2147483647))
+test("max3",z==Int64.max())
+test("min1",tostring(Int64.min()) == "-9223372036854775808")
+test("min2",Int64.min() == Int64.new(0,2147483648))
+z=-z
+z=z-1
+test("min3",z==Int64.min())
+
+test("minmax",Int64.min()== - Int64.max() - 1)
+
+print("\n-----------------------------\n")
+
+print("All tests passed!\n\n")
diff --git a/test/suite-unittests.sh b/test/suite-unittests.sh
index 7883aa3104..f10c65a00a 100755
--- a/test/suite-unittests.sh
+++ b/test/suite-unittests.sh
@@ -69,6 +69,17 @@ unittests_step_exntest() {
unittests_step_test
}
+unittests_step_lua_int64_test() {
+ $TSHARK -r $CAPTURE_DIR/dhcp.pcap -X lua_script:$TESTS_DIR/lua/int64.lua > testout.txt 2>&1
+ # Tshark catches lua script failures, so we have to parse the output.
+ if grep -q "All tests passed!" testout.txt; then
+ test_step_ok
+ else
+ cat testout.txt
+ test_step_failed "didn't find pass marker"
+ fi
+}
+
unittests_step_oids_test() {
DUT=$SOURCE_DIR/epan/oids_test
ARGS=
@@ -101,6 +112,7 @@ unittests_suite() {
test_step_set_pre unittests_cleanup_step
test_step_set_post unittests_cleanup_step
test_step_add "exntest" unittests_step_exntest
+ test_step_add "lua int64" unittests_step_lua_int64_test
test_step_add "oids_test" unittests_step_oids_test
test_step_add "reassemble_test" unittests_step_reassemble_test
test_step_add "tvbtest" unittests_step_tvbtest