diff options
author | Hadriel Kaplan <hadrielk@yahoo.com> | 2014-02-02 22:49:30 -0500 |
---|---|---|
committer | Evan Huus <eapache@gmail.com> | 2014-02-04 00:37:46 +0000 |
commit | 2e7f771a182df815e8c3d38986a1df0c77d7e4aa (patch) | |
tree | 7e0fb8f65c75c19788fb3af273ec9228e696206e | |
parent | caed2818c94312d5df5d66fa20c6bba28fd49499 (diff) |
Adds support for Lua Int64 and UInt64 operators, functions, and general
usefulness, working around bug #9162 until Lua 5.3 is released.
The existing Int64 and UInt64 classes provide virtually no
usefullness, other than for creating a string of their value. While
one could then write Lua code to convert the string to Lua numbers and
such, ultimately Lua has no native 64-bit integer support, making such
a task difficult to handle in Lua. This change adds a host of
functions and operators to the existing Int64 (gint64) and UInt64
(guint64) classes, to enable true 64-bit integer support on par with
native Lua numbers.
A test script is also provided, which tests the functions/operators.
Change-Id: I4c5f8f5219b9a88198902283bd32ddf24c346bbe
Reviewed-on: https://code.wireshark.org/review/83
Tested-by: Evan Huus <eapache@gmail.com>
Reviewed-by: Evan Huus <eapache@gmail.com>
-rw-r--r-- | docbook/CMakeLists.txt | 1 | ||||
-rw-r--r-- | docbook/Makefile.common | 1 | ||||
-rw-r--r-- | docbook/user-guide.xml | 1 | ||||
-rw-r--r-- | docbook/wsluarm.xml | 1 | ||||
-rw-r--r-- | epan/wslua/CMakeLists.txt | 1 | ||||
-rw-r--r-- | epan/wslua/Makefile.am | 2 | ||||
-rw-r--r-- | epan/wslua/Makefile.nmake | 2 | ||||
-rwxr-xr-x | epan/wslua/make-reg.pl | 2 | ||||
-rw-r--r-- | epan/wslua/wslua.h | 16 | ||||
-rw-r--r-- | epan/wslua/wslua_field.c | 8 | ||||
-rw-r--r-- | epan/wslua/wslua_int64.c | 911 | ||||
-rw-r--r-- | epan/wslua/wslua_tree.c | 4 | ||||
-rw-r--r-- | epan/wslua/wslua_tvb.c | 110 | ||||
-rw-r--r-- | epan/wslua/wslua_util.c | 13 | ||||
-rwxr-xr-x | test/lua/int64.lua | 341 | ||||
-rwxr-xr-x | test/suite-unittests.sh | 12 |
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 |