1 /*
2  * A Lua userdata object for 64-bit signed/unsigned integers.
3  *
4  * I, Hadriel Kaplan, the author of wslua_int6464.c, wish to put it in
5  * the Public Domain.  That is not universally accepted, however,
6  * so you may license it under the FreeBSD License instead, which is an open
7  * source license approved for GPL use as well as commercial etc.
8  * It's even less restrictive than the MIT license, because it requires
9  * no attribution anywhere - I don't *want* attribution.
10 
11 Copyright (C) 2013 Hadriel Kaplan <hadrielk@yahoo.com>
12 All rights reserved.
13 
14 SPDX-License-Identifier: BSD-2-Clause
15 
16 The views and conclusions contained in the software and documentation are those
17 of the authors and should not be interpreted as representing official policies,
18 either expressed or implied, of the FreeBSD Project.
19 */
20 
21 #include "config.h"
22 
23 #include "wslua.h"
24 
25     /*
26     WSLUA_MODULE Int64 Handling 64-bit Integers
27 
28     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, one cannot store 64 bit integers with full precision.
29 
30     Lua numbers are stored as floating point (doubles) internally, not integers; thus while they can represent incredibly large numbers, above 2^53 they lose integral precision -- they can't represent every whole integer value.
31     For example if you set a lua variable to the number 9007199254740992 and tried to increment it by 1, you'd get the same number because it can't represent 9007199254740993 (only the even number 9007199254740994).
32 
33     Therefore, in order to count higher than 2^53 in integers, we need a true integer type.
34     The way this is done is with an explicit 'Int64' or 'UInt64' object (i.e., Lua userdata).
35     This object has metamethods for all of the math and comparison operators, so you can handle it like any number variable.
36     For the math operators, it can even be mixed with plain Lua numbers.
37 
38     For example 'my64num = my64num + 1' will work even if 'my64num' is a <<lua_class_Int64,`Int64`>> or <<lua_class_UInt64,`UInt64`>> object.
39     Note that comparison operators ('==','$$<=$$','>', etc.) will not work with plain numbers -- only other Int64/UInt64 objects.
40     This is a limitation of Lua itself, in terms of how it handles operator overloading.
41 
42     // Previous to Wireshark release 1.11, Int64 and UInt64 could only be created by tvbrange:int64() or tvbrange:le_int64(), or tvbrange:uint64() or tvbrange:le_uint64() or tvbrange:bitfield(), and had only a couple functions (the metamethods tostring() and concat()).
43     // All of the functions on this page are only available starting in Wireshark 1.11 and higher.
44 
45     [WARNING]
46     ====
47     Many of the UInt64/Int64 functions accept a Lua number as an argument.
48     You should be very careful to never use Lua numbers bigger than 32 bits (i.e., the number value 4,294,967,295 or the literal 0xFFFFFFFF) for such arguments, because Lua itself does not handle bigger numbers consistently across platforms (32-bit vs. 64-bit systems), and because a Lua number is a C-code double which cannot have more than 53 bits of precision.
49     Instead, use a Int64 or UInt64 for the argument.
50     ====
51 
52     For example, do this...
53 
54     [source,lua]
55     ----
56     local mynum = UInt64(0x2b89dd1e, 0x3f91df0b)
57     ----
58 
59     ...instead of this:
60 
61     [source,lua]
62     ----
63     -- Bad. Leads to inconsistent results across platforms
64     local mynum = UInt64(0x3f91df0b2b89dd1e)
65     ----
66 
67     And do this...
68 
69     [source,lua]
70     ----
71     local masked = mynum:band(UInt64(0, 0xFFFFFFFF))
72     ----
73 
74     ...instead of this:
75 
76     [source,lua]
77     ----
78     -- Bad. Leads to inconsistent results across platforms
79     local masked = mynum:band(0xFFFFFFFF00000000)
80     ----
81     */
82 
83 #define LUATYPE64_STRING_SIZE 21  /* string to hold 18446744073709551615 */
84 
85 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
86 #define IS_LITTLE_ENDIAN TRUE
87 #else
88 #define IS_LITTLE_ENDIAN FALSE
89 #endif
90 
91 WSLUA_CLASS_DEFINE_BASE(Int64,NOP,0);
92     /*
93     <<lua_class_Int64,`Int64`>> represents a 64 bit signed integer.
94 
95     Note the caveats <<lua_module_Int64,listed above>>.
96     */
97 
98 /* A checkInt64 but that also auto-converts numbers, strings, and UINT64 to a gint64 */
getInt64(lua_State * L,int i)99 static gint64 getInt64(lua_State *L, int i)
100 {
101     gchar *end = NULL;
102     (void) end;
103     switch (lua_type(L,i))
104     {
105         case LUA_TNUMBER:
106             return wslua_checkgint64(L,i);
107         case LUA_TSTRING:
108             return g_ascii_strtoll(luaL_checkstring(L,i),&end,10);
109         case LUA_TUSERDATA:
110             if (isUInt64(L, i)) {
111                 return (Int64) toUInt64(L, i);
112             }
113             /* fall through */
114         default:
115             return checkInt64(L,i);
116         }
117 }
118 
119 
120 /* Encodes Int64 userdata into Lua string struct with given endianness */
Int64_pack(lua_State * L,luaL_Buffer * b,gint idx,gboolean asLittleEndian)121 void Int64_pack(lua_State* L, luaL_Buffer *b, gint idx, gboolean asLittleEndian) {
122     gint64 value = checkInt64(L,idx);
123     gint8 buff[sizeof(gint64)];
124 
125     if (asLittleEndian) {
126         guint i;
127         for (i = 0; i < sizeof(gint64); i++) {
128             buff[i] = (value & 0xff);
129             value >>= 8;
130         }
131     }
132     else {
133         gint i;
134         for (i = sizeof(gint64) - 1; i >= 0; i--) {
135             buff[i] = (value & 0xff);
136             value >>= 8;
137         }
138     }
139     luaL_addlstring(b, (char*)buff, sizeof(gint64));
140 }
141 
Int64_encode(lua_State * L)142 WSLUA_METHOD Int64_encode(lua_State* L) {
143     /* Encodes the <<lua_class_Int64,`Int64`>> number into an 8-byte Lua string using the given endianness.
144        @since 1.11.3
145      */
146 #define WSLUA_OPTARG_Int64_encode_ENDIAN 2 /* If set to true then little-endian is used,
147                                               if false then big-endian; if missing or `nil`,
148                                               native host endian. */
149     luaL_Buffer b;
150     gboolean asLittleEndian = IS_LITTLE_ENDIAN;
151 
152     if (lua_gettop(L) >= WSLUA_OPTARG_Int64_encode_ENDIAN) {
153         if (lua_type(L,WSLUA_OPTARG_Int64_encode_ENDIAN) == LUA_TBOOLEAN)
154             asLittleEndian = lua_toboolean(L,WSLUA_OPTARG_Int64_encode_ENDIAN);
155     }
156 
157     luaL_buffinit(L, &b);
158 
159     Int64_pack(L, &b, 1, asLittleEndian);
160 
161     luaL_pushresult(&b);
162     WSLUA_RETURN(1); /* The Lua string. */
163 }
164 
165 /* Decodes from string buffer struct into Int64 userdata, with given endianness */
Int64_unpack(lua_State * L,const gchar * buff,gboolean asLittleEndian)166 int Int64_unpack(lua_State* L, const gchar *buff, gboolean asLittleEndian) {
167     gint64 value = 0;
168     gint i;
169 
170     if (asLittleEndian) {
171         for (i = sizeof(gint64) - 1; i >= 0; i--) {
172             value <<= 8;
173             value |= (gint64)(guchar)buff[i];
174         }
175     }
176     else {
177         for (i = 0; i < (gint) sizeof(gint64); i++) {
178             value <<= 8;
179             value |= (gint64)(guchar)buff[i];
180         }
181     }
182 
183     pushInt64(L,value);
184     return 1;
185 }
186 
Int64_decode(lua_State * L)187 WSLUA_CONSTRUCTOR Int64_decode(lua_State* L) {
188     /* Decodes an 8-byte Lua string, using the given endianness, into a new <<lua_class_Int64,`Int64`>> object.
189        @since 1.11.3
190      */
191 #define WSLUA_ARG_Int64_decode_STRING 1 /* The Lua string containing a binary 64-bit integer. */
192 #define WSLUA_OPTARG_Int64_decode_ENDIAN 2 /* If set to true then little-endian is used,
193                                               if false then big-endian; if missing or `nil`, native
194                                               host endian. */
195     gboolean asLittleEndian = IS_LITTLE_ENDIAN;
196     size_t len = 0;
197     const gchar *s = luaL_checklstring(L, WSLUA_ARG_Int64_decode_STRING, &len);
198 
199     if (lua_gettop(L) >= WSLUA_OPTARG_Int64_decode_ENDIAN) {
200         if (lua_type(L,WSLUA_OPTARG_Int64_decode_ENDIAN) == LUA_TBOOLEAN)
201             asLittleEndian = lua_toboolean(L,WSLUA_OPTARG_Int64_decode_ENDIAN);
202     }
203 
204     if (len == sizeof(gint64)) {
205         Int64_unpack(L, s, asLittleEndian);
206     } else {
207         lua_pushnil(L);
208     }
209 
210     WSLUA_RETURN(1); /* The <<lua_class_Int64,`Int64`>> object created, or nil on failure. */
211 }
212 
Int64_new(lua_State * L)213 WSLUA_CONSTRUCTOR Int64_new(lua_State* L) {
214     /* Creates a <<lua_class_Int64,`Int64`>> Object.
215        @since 1.11.3
216      */
217 #define WSLUA_OPTARG_Int64_new_VALUE 1 /* A number, <<lua_class_UInt64,`UInt64`>>, <<lua_class_Int64,`Int64`>>, or string of ASCII digits
218                                           to assign the value of the new <<lua_class_Int64,`Int64`>>. Default is 0. */
219 #define WSLUA_OPTARG_Int64_new_HIGHVALUE 2 /* If this is a number and the first argument was
220                                               a number, then the first will be treated as a
221                                               lower 32 bits, and this is the high-order 32
222                                               bit number. */
223     gint64 value = 0;
224 
225     if (lua_gettop(L) >= 1) {
226         switch(lua_type(L, WSLUA_OPTARG_Int64_new_VALUE)) {
227             case LUA_TNUMBER:
228                 value = wslua_togint64(L, WSLUA_OPTARG_Int64_new_VALUE);
229                 if (lua_gettop(L) == 2 &&
230                     lua_type(L, WSLUA_OPTARG_Int64_new_HIGHVALUE) == LUA_TNUMBER) {
231                     gint64 h = wslua_togint64(L, WSLUA_OPTARG_Int64_new_HIGHVALUE);
232                     value &= G_GUINT64_CONSTANT(0x00000000FFFFFFFF);
233                     h <<= 32; h &= G_GUINT64_CONSTANT(0xFFFFFFFF00000000);
234                     value += h;
235                 }
236                 break;
237             case LUA_TSTRING:
238             case LUA_TUSERDATA:
239                 value = getInt64(L,WSLUA_OPTARG_Int64_new_VALUE);
240                 break;
241             default:
242                 WSLUA_OPTARG_ERROR(Int64_new,VALUE,"must be a number, UInt64, Int64, or string");
243                 break;
244         }
245     }
246 
247     pushInt64(L,value);
248 
249     WSLUA_RETURN(1); /* The new <<lua_class_Int64,`Int64`>> object. */
250 }
251 
Int64__call(lua_State * L)252 WSLUA_METAMETHOD Int64__call(lua_State* L) {
253     /* Creates a <<lua_class_Int64,`Int64`>> object.
254        @since 1.11.3
255      */
256     lua_remove(L,1); /* remove the table */
257     WSLUA_RETURN(Int64_new(L)); /* The new <<lua_class_Int64,`Int64`>> object. */
258 }
259 
Int64_max(lua_State * L)260 WSLUA_CONSTRUCTOR Int64_max(lua_State* L) {
261     /* Creates an <<lua_class_Int64,`Int64`>> of the maximum possible positive value. In other words, this should return an Int64 object of the number 9,223,372,036,854,775,807.
262        @since 1.11.3
263      */
264     pushInt64(L, G_MAXINT64);
265     WSLUA_RETURN(1); /* The new <<lua_class_Int64,`Int64`>> object of the maximum value. */
266 }
267 
Int64_min(lua_State * L)268 WSLUA_CONSTRUCTOR Int64_min(lua_State* L) {
269     /* Creates an <<lua_class_Int64,`Int64`>> of the minimum possible negative value. In other words, this should return an Int64 object of the number -9,223,372,036,854,775,808.
270        @since 1.11.3
271      */
272     pushInt64(L, G_MININT64);
273     WSLUA_RETURN(1); /* The new <<lua_class_Int64,`Int64`>> object of the minimum value. */
274 }
275 
276 
Int64_tonumber(lua_State * L)277 WSLUA_METHOD Int64_tonumber(lua_State* L) {
278     /* Returns a Lua number of the <<lua_class_Int64,`Int64`>> value. Note that this may lose precision.
279        @since 1.11.3
280      */
281     lua_pushnumber(L, (lua_Number)(checkInt64(L,1)));
282     WSLUA_RETURN(1); /* The Lua number. */
283 }
284 
Int64_fromhex(lua_State * L)285 WSLUA_CONSTRUCTOR Int64_fromhex(lua_State* L) {
286     /* Creates an <<lua_class_Int64,`Int64`>> object from the given hexadecimal string.
287        @since 1.11.3
288      */
289 #define WSLUA_ARG_Int64_fromhex_HEX 1 /* The hex-ASCII Lua string. */
290     guint64 result = 0;
291     size_t len = 0;
292     const gchar *s = luaL_checklstring(L,WSLUA_ARG_Int64_fromhex_HEX,&len);
293 
294     if (len > 0) {
295         if (sscanf(s, "%" G_GINT64_MODIFIER "x", &result) != 1) {
296             return luaL_error(L, "Error decoding the passed-in hex string");
297         }
298     }
299     pushInt64(L,(gint64)result);
300     WSLUA_RETURN(1); /* The new <<lua_class_Int64,`Int64`>> object. */
301 }
302 
Int64_tohex(lua_State * L)303 WSLUA_METHOD Int64_tohex(lua_State* L) {
304     /* Returns a hexadecimal string of the <<lua_class_Int64,`Int64`>> value.
305        @since 1.11.3
306      */
307 #define WSLUA_OPTARG_Int64_new_NUMBYTES 2 /* The number of hex chars/nibbles to generate.
308                                              A negative value generates uppercase. Default is 16. */
309     gint64 b = getInt64(L,1);
310     lua_Integer n = luaL_optinteger(L, WSLUA_OPTARG_Int64_new_NUMBYTES, 16);
311     const gchar *hexdigits = "0123456789abcdef";
312     gchar buf[16];
313     lua_Integer i;
314     if (n < 0) { n = -n; hexdigits = "0123456789ABCDEF"; }
315     if (n > 16) n = 16;
316     for (i = n-1; i >= 0; --i) { buf[i] = hexdigits[b & 15]; b >>= 4; }
317     lua_pushlstring(L, buf, (size_t)n);
318     WSLUA_RETURN(1); /* The string hex. */
319 }
320 
Int64_higher(lua_State * L)321 WSLUA_METHOD Int64_higher(lua_State* L) {
322     /* Returns a Lua number of the higher 32 bits of the <<lua_class_Int64,`Int64`>> value. A negative <<lua_class_Int64,`Int64`>>
323        will return a negative Lua number.
324        @since 1.11.3
325      */
326     gint64 num = getInt64(L,1);
327     gint64 b = num;
328     lua_Number n = 0;
329     if (b < 0) b = -b; /* masking/shifting negative int64 isn't working on some platforms */
330     b &= G_GUINT64_CONSTANT(0x7FFFFFFF00000000);
331     b >>= 32;
332     n = (lua_Number)(guint32)(b & G_GUINT64_CONSTANT(0x00000000FFFFFFFFF));
333     if (num < 0) n = -n;
334     lua_pushnumber(L,n);
335     WSLUA_RETURN(1); /* The Lua number. */
336 }
337 
Int64_lower(lua_State * L)338 WSLUA_METHOD Int64_lower(lua_State* L) {
339     /* Returns a Lua number of the lower 32 bits of the <<lua_class_Int64,`Int64`>> value. This will always be positive.
340        @since 1.11.3
341      */
342     gint64 b = getInt64(L,1);
343     if (b < 0) b = -b; /* masking/shifting negative int64 isn't working on some platforms */
344     lua_pushnumber(L,(guint32)(b & G_GUINT64_CONSTANT(0x00000000FFFFFFFFF)));
345     WSLUA_RETURN(1); /* The Lua number. */
346 }
347 
Int64__tostring(lua_State * L)348 WSLUA_METAMETHOD Int64__tostring(lua_State* L) {
349     /* Converts the <<lua_class_Int64,`Int64`>> into a string of decimal digits. */
350     gint64 num = getInt64(L,1);
351     gchar s[LUATYPE64_STRING_SIZE];
352     if (g_snprintf(s, LUATYPE64_STRING_SIZE, "%" G_GINT64_MODIFIER "d", num) < 0) {
353         return luaL_error(L, "Error writing Int64 to a string");
354     }
355     lua_pushstring(L,s);
356     WSLUA_RETURN(1); /* The Lua string. */
357 }
358 
Int64__unm(lua_State * L)359 WSLUA_METAMETHOD Int64__unm(lua_State* L) {
360     /* Returns the negative of the <<lua_class_Int64,`Int64`>> as a new <<lua_class_Int64,`Int64`>>.
361        @since 1.11.3
362      */
363     pushInt64(L,-(getInt64(L,1)));
364     WSLUA_RETURN(1); /* The new <<lua_class_Int64,`Int64`>>. */
365 }
366 
367 #define WSLUA_MATH_OP_FUNC(obj,op) \
368     /* use the 'get' form so we can accept numbers as well */ \
369     obj num1 = get##obj(L,1); \
370     obj num2 = get##obj(L,2); \
371     push##obj(L,(num1) op (num2)); \
372     return 1
373 
Int64__add(lua_State * L)374 WSLUA_METAMETHOD Int64__add(lua_State* L) {
375     /* Adds two <<lua_class_Int64,`Int64`>> together and returns a new one. The value may wrapped.
376        @since 1.11.3
377      */
378     WSLUA_MATH_OP_FUNC(Int64,+);
379 }
380 
Int64__sub(lua_State * L)381 WSLUA_METAMETHOD Int64__sub(lua_State* L) {
382     /* Subtracts two <<lua_class_Int64,`Int64`>> and returns a new one. The value may wrapped.
383        @since 1.11.3
384      */
385     WSLUA_MATH_OP_FUNC(Int64,-);
386 }
387 
Int64__mul(lua_State * L)388 WSLUA_METAMETHOD Int64__mul(lua_State* L) {
389     /* Multiplies two <<lua_class_Int64,`Int64`>> and returns a new one. The value may truncated.
390        @since 1.11.3
391      */
392     WSLUA_MATH_OP_FUNC(Int64,*);
393 }
394 
Int64__div(lua_State * L)395 WSLUA_METAMETHOD Int64__div(lua_State* L) {
396     /* Divides two <<lua_class_Int64,`Int64`>> and returns a new one. Integer divide, no remainder.
397        Trying to divide by zero results in a Lua error.
398        @since 1.11.3
399      */
400     Int64 num1 = getInt64(L,1);
401     Int64 num2 = getInt64(L,2);
402     if (num2 == 0) {
403         return luaL_error(L, "Trying to divide Int64 by zero");
404     }
405     pushInt64(L, num1 / num2);
406     WSLUA_RETURN(1); /* The <<lua_class_Int64,`Int64`>> object. */
407 }
408 
Int64__mod(lua_State * L)409 WSLUA_METAMETHOD Int64__mod(lua_State* L) {
410     /* Divides two <<lua_class_Int64,`Int64`>> and returns a new one of the remainder.
411        Trying to modulo by zero results in a Lua error.
412        @since 1.11.3
413      */
414     Int64 num1 = getInt64(L,1);
415     Int64 num2 = getInt64(L,2);
416     if (num2 == 0) {
417         return luaL_error(L, "Trying to modulo Int64 by zero");
418     }
419     pushInt64(L, num1 % num2);
420     WSLUA_RETURN(1); /* The <<lua_class_Int64,`Int64`>> object. */
421 }
422 
Int64__pow(lua_State * L)423 WSLUA_METAMETHOD Int64__pow(lua_State* L) {
424     /* The first <<lua_class_Int64,`Int64`>> is taken to the power of the second <<lua_class_Int64,`Int64`>>, returning a new
425        one. This may truncate the value.
426        @since 1.11.3
427      */
428     gint64 num1 = getInt64(L,1);
429     gint64 num2 = getInt64(L,2);
430     gint64 result;
431     if (num1 == 2) {
432         result = (num2 >= 8 * (gint64) sizeof(gint64)) ? 0 : ((gint64)1 << num2);
433     }
434     else {
435         for (result = 1; num2 > 0; num2 >>= 1) {
436             if (num2 & 1) result *= num1;
437             num1 *= num1;
438         }
439     }
440     pushInt64(L,result);
441     WSLUA_RETURN(1); /* The <<lua_class_Int64,`Int64`>> object. */
442 }
443 
444 #define WSLUA_COMP_OP_FUNC(obj,op) \
445     obj num1 = get##obj(L,1); \
446     obj num2 = get##obj(L,2); \
447     lua_pushboolean(L,(num1) op (num2)); \
448     return 1
449 
Int64__eq(lua_State * L)450 WSLUA_METAMETHOD Int64__eq(lua_State* L) {
451     /* Returns `true` if both <<lua_class_Int64,`Int64`>> are equal.
452        @since 1.11.3
453      */
454     WSLUA_COMP_OP_FUNC(Int64,==);
455 }
456 
Int64__lt(lua_State * L)457 WSLUA_METAMETHOD Int64__lt(lua_State* L) {
458     /* Returns `true` if first <<lua_class_Int64,`Int64`>> is less than the second.
459        @since 1.11.3
460      */
461     WSLUA_COMP_OP_FUNC(Int64,<);
462 }
463 
Int64__le(lua_State * L)464 WSLUA_METAMETHOD Int64__le(lua_State* L) {
465     /* Returns `true` if the first <<lua_class_Int64,`Int64`>> is less than or equal to the second.
466        @since 1.11.3
467      */
468     WSLUA_COMP_OP_FUNC(Int64,<=);
469 }
470 
Int64_bnot(lua_State * L)471 WSLUA_METHOD Int64_bnot(lua_State* L) {
472     /* Returns a <<lua_class_Int64,`Int64`>> of the bitwise 'not' operation.
473        @since 1.11.3
474      */
475     pushInt64(L,~(getInt64(L,1)));
476     WSLUA_RETURN(1); /* The <<lua_class_Int64,`Int64`>> object. */
477 }
478 
479 #define WSLUA_BIT_OP_FUNC(obj,op) \
480     gint32 i; \
481     obj num = get##obj(L,1); \
482     for (i = lua_gettop(L); i > 1; i--) { \
483         num op get##obj(L,i); \
484     } \
485     push##obj(L,num); \
486     return 1
487 
Int64_band(lua_State * L)488 WSLUA_METHOD Int64_band(lua_State* L) {
489     /* Returns a <<lua_class_Int64,`Int64`>> of the bitwise 'and' operation with the given number/`Int64`/`UInt64`.
490        Note that multiple arguments are allowed.
491        @since 1.11.3
492      */
493     WSLUA_BIT_OP_FUNC(Int64,&=);
494 }
495 
Int64_bor(lua_State * L)496 WSLUA_METHOD Int64_bor(lua_State* L) {
497     /* Returns a <<lua_class_Int64,`Int64`>> of the bitwise 'or' operation, with the given number/`Int64`/`UInt64`.
498        Note that multiple arguments are allowed.
499        @since 1.11.3
500      */
501     WSLUA_BIT_OP_FUNC(Int64,|=);
502 }
503 
Int64_bxor(lua_State * L)504 WSLUA_METHOD Int64_bxor(lua_State* L) {
505     /* Returns a <<lua_class_Int64,`Int64`>> of the bitwise 'xor' operation, with the given number/`Int64`/`UInt64`.
506        Note that multiple arguments are allowed.
507        @since 1.11.3
508      */
509     WSLUA_BIT_OP_FUNC(Int64,^=);
510 }
511 
Int64_lshift(lua_State * L)512 WSLUA_METHOD Int64_lshift(lua_State* L) {
513     /* Returns a <<lua_class_Int64,`Int64`>> of the bitwise logical left-shift operation, by the given
514        number of bits.
515        @since 1.11.3
516      */
517 #define WSLUA_ARG_Int64_lshift_NUMBITS 2 /* The number of bits to left-shift by. */
518     guint64 b = (guint64) getInt64(L,1);
519     guint32 n = wslua_checkguint32(L,WSLUA_ARG_Int64_lshift_NUMBITS);
520     pushInt64(L,(gint64)(b << n));
521     WSLUA_RETURN(1); /* The <<lua_class_Int64,`Int64`>> object. */
522 }
523 
Int64_rshift(lua_State * L)524 WSLUA_METHOD Int64_rshift(lua_State* L) {
525     /* Returns a <<lua_class_Int64,`Int64`>> of the bitwise logical right-shift operation, by the
526        given number of bits.
527        @since 1.11.3
528      */
529 #define WSLUA_ARG_Int64_rshift_NUMBITS 2 /* The number of bits to right-shift by. */
530     guint64 b = (guint64) getInt64(L,1);
531     guint32 n = wslua_checkguint32(L,WSLUA_ARG_Int64_rshift_NUMBITS);
532     pushInt64(L,(gint64)(b >> n));
533     WSLUA_RETURN(1); /* The <<lua_class_Int64,`Int64`>> object. */
534 }
535 
Int64_arshift(lua_State * L)536 WSLUA_METHOD Int64_arshift(lua_State* L) {
537     /* Returns a <<lua_class_Int64,`Int64`>> of the bitwise arithmetic right-shift operation, by the
538        given number of bits.
539        @since 1.11.3
540      */
541 #define WSLUA_ARG_Int64_arshift_NUMBITS 2 /* The number of bits to right-shift by. */
542     gint64 b = getInt64(L,1);
543     gint32 n = wslua_checkgint32(L,WSLUA_ARG_Int64_arshift_NUMBITS);
544     pushInt64(L,(b >> n));
545     WSLUA_RETURN(1); /* The <<lua_class_Int64,`Int64`>> object. */
546 }
547 
Int64_rol(lua_State * L)548 WSLUA_METHOD Int64_rol(lua_State* L) {
549     /* Returns a <<lua_class_Int64,`Int64`>> of the bitwise left rotation operation, by the given number of
550        bits (up to 63).
551        @since 1.11.3
552      */
553 #define WSLUA_ARG_Int64_rol_NUMBITS 2 /* The number of bits to roll left by. */
554     guint64 b = (guint64) getInt64(L,1);
555     guint32 n = wslua_checkguint32(L,WSLUA_ARG_Int64_rol_NUMBITS);
556     pushInt64(L,(gint64)((b << n) | (b >> (64-n))));
557     WSLUA_RETURN(1); /* The <<lua_class_Int64,`Int64`>> object. */
558 }
559 
Int64_ror(lua_State * L)560 WSLUA_METHOD Int64_ror(lua_State* L) {
561     /* Returns a <<lua_class_Int64,`Int64`>> of the bitwise right rotation operation, by the given number of
562        bits (up to 63).
563        @since 1.11.3
564      */
565 #define WSLUA_ARG_Int64_ror_NUMBITS 2 /* The number of bits to roll right by. */
566     guint64 b = (guint64) getInt64(L,1);
567     guint32 n = wslua_checkguint32(L,WSLUA_ARG_Int64_ror_NUMBITS);
568     pushInt64(L,(gint64)((b << (64-n)) | (b >> n)));
569     WSLUA_RETURN(1); /* The <<lua_class_Int64,`Int64`>> object. */
570 }
571 
Int64_bswap(lua_State * L)572 WSLUA_METHOD Int64_bswap(lua_State* L) {
573     /* Returns a <<lua_class_Int64,`Int64`>> of the bytes swapped. This can be used to convert little-endian
574        64-bit numbers to big-endian 64 bit numbers or vice versa.
575        @since 1.11.3
576      */
577     guint64 b = (guint64) getInt64(L,1);
578     guint64 result = 0;
579     size_t i;
580     for (i = 0; i < sizeof(gint64); i++) {
581         result <<= 8;
582         result |= (b & G_GUINT64_CONSTANT(0x00000000000000FF));
583         b >>= 8;
584     }
585     pushInt64(L,(gint64)result);
586     WSLUA_RETURN(1); /* The <<lua_class_Int64,`Int64`>> object. */
587 }
588 
589 /* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META. */
Int64__gc(lua_State * L _U_)590 static int Int64__gc(lua_State* L _U_) {
591     return 0;
592 }
593 
594 WSLUA_METHODS Int64_methods[] = {
595     WSLUA_CLASS_FNREG(Int64,new),
596     WSLUA_CLASS_FNREG(Int64,max),
597     WSLUA_CLASS_FNREG(Int64,min),
598     WSLUA_CLASS_FNREG(Int64,tonumber),
599     WSLUA_CLASS_FNREG(Int64,fromhex),
600     WSLUA_CLASS_FNREG(Int64,tohex),
601     WSLUA_CLASS_FNREG(Int64,higher),
602     WSLUA_CLASS_FNREG(Int64,lower),
603     WSLUA_CLASS_FNREG(Int64,encode),
604     WSLUA_CLASS_FNREG(Int64,decode),
605     WSLUA_CLASS_FNREG(Int64,bnot),
606     WSLUA_CLASS_FNREG(Int64,band),
607     WSLUA_CLASS_FNREG(Int64,bor),
608     WSLUA_CLASS_FNREG(Int64,bxor),
609     WSLUA_CLASS_FNREG(Int64,lshift),
610     WSLUA_CLASS_FNREG(Int64,rshift),
611     WSLUA_CLASS_FNREG(Int64,arshift),
612     WSLUA_CLASS_FNREG(Int64,rol),
613     WSLUA_CLASS_FNREG(Int64,ror),
614     WSLUA_CLASS_FNREG(Int64,bswap),
615     { NULL, NULL }
616 };
617 
618 WSLUA_META Int64_meta[] = {
619     WSLUA_CLASS_MTREG(Int64,tostring),
620     WSLUA_CLASS_MTREG(Int64,call),
621     WSLUA_CLASS_MTREG(wslua,concat),
622     WSLUA_CLASS_MTREG(Int64,unm),
623     WSLUA_CLASS_MTREG(Int64,add),
624     WSLUA_CLASS_MTREG(Int64,sub),
625     WSLUA_CLASS_MTREG(Int64,mul),
626     WSLUA_CLASS_MTREG(Int64,div),
627     WSLUA_CLASS_MTREG(Int64,mod),
628     WSLUA_CLASS_MTREG(Int64,pow),
629     WSLUA_CLASS_MTREG(Int64,eq),
630     WSLUA_CLASS_MTREG(Int64,lt),
631     WSLUA_CLASS_MTREG(Int64,le),
632     { NULL, NULL }
633 };
634 
Int64_register(lua_State * L)635 LUALIB_API int Int64_register(lua_State* L) {
636     WSLUA_REGISTER_CLASS(Int64);
637     return 0;
638 }
639 
640 
641 
642 WSLUA_CLASS_DEFINE_BASE(UInt64,NOP,0);
643     /*
644     <<lua_class_UInt64,`UInt64`>> represents a 64 bit unsigned integer, similar to <<lua_class_Int64,`Int64`>>.
645 
646     Note the caveats <<lua_module_Int64,listed above>>.
647     */
648 
649 /* A checkUInt64 but that also auto-converts numbers, strings, and <<lua_class_Int64,`Int64`>> to a guint64. */
getUInt64(lua_State * L,int i)650 static guint64 getUInt64(lua_State *L, int i)
651 {
652     gchar *end = NULL;
653     (void) end;
654     switch (lua_type(L,i))
655     {
656         case LUA_TNUMBER:
657             return wslua_checkguint64(L,i);
658         case LUA_TSTRING:
659             return g_ascii_strtoull(luaL_checkstring(L,i), &end, 10);
660         case LUA_TUSERDATA:
661             if (isInt64(L, i)) {
662                 return (UInt64) toInt64(L, i);
663             }
664             /* fall through */
665         default:
666             return checkUInt64(L,i);
667         }
668 }
669 
670 /* Encodes <<lua_class_UInt64,`UInt64`>> userdata into Lua string struct with given endianness */
UInt64_pack(lua_State * L,luaL_Buffer * b,gint idx,gboolean asLittleEndian)671 void UInt64_pack(lua_State* L, luaL_Buffer *b, gint idx, gboolean asLittleEndian) {
672     guint64 value = checkUInt64(L,idx);
673     gint8 buff[sizeof(guint64)];
674 
675     if (asLittleEndian) {
676         guint i;
677         for (i = 0; i < sizeof(guint64); i++) {
678             buff[i] = (value & 0xff);
679             value >>= 8;
680         }
681     }
682     else {
683         gint i;
684         for (i = sizeof(guint64) - 1; i >= 0; i--) {
685             buff[i] = (value & 0xff);
686             value >>= 8;
687         }
688     }
689     luaL_addlstring(b, (char*)buff, sizeof(guint64));
690 }
691 
UInt64_encode(lua_State * L)692 WSLUA_METHOD UInt64_encode(lua_State* L) {
693     /* Encodes the <<lua_class_UInt64,`UInt64`>> number into an 8-byte Lua binary string, using given endianness.
694        @since 1.11.3
695      */
696 #define WSLUA_OPTARG_UInt64_encode_ENDIAN 2 /* If set to true then little-endian is used,
697                                                if false then big-endian; if missing or `nil`,
698                                                native host endian. */
699     luaL_Buffer b;
700     gboolean asLittleEndian = IS_LITTLE_ENDIAN;
701 
702     if (lua_gettop(L) >= 2) {
703         if (lua_type(L,2) == LUA_TBOOLEAN)
704             asLittleEndian = lua_toboolean(L,2);
705     }
706 
707     luaL_buffinit(L, &b);
708 
709     UInt64_pack(L, &b, 1, asLittleEndian);
710 
711     luaL_pushresult(&b);
712     WSLUA_RETURN(1); /* The Lua binary string. */
713 }
714 
715 /* Decodes from string buffer struct into <<lua_class_UInt64,`UInt64`>> userdata, with given endianness. */
UInt64_unpack(lua_State * L,const gchar * buff,gboolean asLittleEndian)716 int UInt64_unpack(lua_State* L, const gchar *buff, gboolean asLittleEndian) {
717     guint64 value = 0;
718     gint i;
719 
720     if (asLittleEndian) {
721         for (i = sizeof(guint64) - 1; i >= 0; i--) {
722             value <<= 8;
723             value |= (guint64)(guchar)buff[i];
724         }
725     }
726     else {
727         for (i = 0; i < (gint) sizeof(guint64); i++) {
728             value <<= 8;
729             value |= (guint64)(guchar)buff[i];
730         }
731     }
732 
733     pushUInt64(L,value);
734     return 1;
735 }
736 
UInt64_decode(lua_State * L)737 WSLUA_CONSTRUCTOR UInt64_decode(lua_State* L) {
738     /* Decodes an 8-byte Lua binary string, using given endianness, into a new <<lua_class_UInt64,`UInt64`>> object.
739        @since 1.11.3
740      */
741 #define WSLUA_ARG_UInt64_decode_STRING 1 /* The Lua string containing a binary 64-bit integer. */
742 #define WSLUA_OPTARG_UInt64_decode_ENDIAN 2 /* If set to true then little-endian is used,
743                                                if false then big-endian; if missing or `nil`,
744                                                native host endian. */
745     gboolean asLittleEndian = IS_LITTLE_ENDIAN;
746     size_t len = 0;
747     const gchar *s = luaL_checklstring(L, WSLUA_ARG_UInt64_decode_STRING, &len);
748 
749     if (lua_gettop(L) >= WSLUA_OPTARG_UInt64_decode_ENDIAN) {
750         if (lua_type(L,WSLUA_OPTARG_UInt64_decode_ENDIAN) == LUA_TBOOLEAN)
751             asLittleEndian = lua_toboolean(L,WSLUA_OPTARG_UInt64_decode_ENDIAN);
752     }
753 
754     if (len == sizeof(guint64)) {
755         UInt64_unpack(L, s, asLittleEndian);
756     } else {
757         lua_pushnil(L);
758     }
759 
760     WSLUA_RETURN(1); /* The <<lua_class_UInt64,`UInt64`>> object created, or nil on failure. */
761 }
762 
UInt64_new(lua_State * L)763 WSLUA_CONSTRUCTOR UInt64_new(lua_State* L) {
764     /* Creates a <<lua_class_UInt64,`UInt64`>> Object.
765        @since 1.11.3
766      */
767 #define WSLUA_OPTARG_UInt64_new_VALUE 1 /* A number, <<lua_class_UInt64,`UInt64`>>, <<lua_class_Int64,`Int64`>>, or string of digits
768                                            to assign the value of the new <<lua_class_UInt64,`UInt64`>>. Default is 0. */
769 #define WSLUA_OPTARG_UInt64_new_HIGHVALUE 2 /* If this is a number and the first argument was
770                                                a number, then the first will be treated as a
771                                                lower 32 bits, and this is the high-order
772                                                32-bit number. */
773     guint64 value = 0;
774 
775     if (lua_gettop(L) >= 1) {
776         switch(lua_type(L, WSLUA_OPTARG_UInt64_new_VALUE)) {
777             case LUA_TNUMBER:
778                 value = wslua_toguint64(L, WSLUA_OPTARG_UInt64_new_VALUE);
779                  if (lua_gettop(L) == 2 &&
780                      lua_type(L, WSLUA_OPTARG_UInt64_new_HIGHVALUE) == LUA_TNUMBER) {
781                     guint64 h = wslua_toguint64(L, WSLUA_OPTARG_UInt64_new_HIGHVALUE);
782                     value &= G_GUINT64_CONSTANT(0x00000000FFFFFFFF);
783                     h <<= 32; h &= G_GUINT64_CONSTANT(0xFFFFFFFF00000000);
784                     value += h;
785                 }
786                break;
787             case LUA_TSTRING:
788             case LUA_TUSERDATA:
789                 value = getUInt64(L, WSLUA_OPTARG_UInt64_new_VALUE);
790                 break;
791             default:
792                 WSLUA_OPTARG_ERROR(UInt64_new,VALUE,"must be a number, UInt64, Int64, or string");
793                 break;
794         }
795     }
796 
797     pushUInt64(L,value);
798 
799     WSLUA_RETURN(1); /* The new <<lua_class_UInt64,`UInt64`>> object. */
800 }
801 
UInt64__call(lua_State * L)802 WSLUA_METAMETHOD UInt64__call(lua_State* L) {
803     /* Creates a <<lua_class_UInt64,`UInt64`>> object.
804        @since 1.11.3
805      */
806     lua_remove(L,1); /* remove the table */
807     WSLUA_RETURN(UInt64_new(L)); /* The new <<lua_class_UInt64,`UInt64`>> object. */
808 }
809 
UInt64_max(lua_State * L)810 WSLUA_CONSTRUCTOR UInt64_max(lua_State* L) {
811     /* Creates a <<lua_class_UInt64,`UInt64`>> of the maximum possible value. In other words, this should return an UInt64 object of the number 18,446,744,073,709,551,615.
812        @since 1.11.3
813      */
814     pushUInt64(L,G_MAXUINT64);
815     WSLUA_RETURN(1); /* The maximum value. */
816 }
817 
UInt64_min(lua_State * L)818 WSLUA_CONSTRUCTOR UInt64_min(lua_State* L) {
819     /* Creates a <<lua_class_UInt64,`UInt64`>> of the minimum possible value. In other words, this should return an UInt64 object of the number 0.
820        @since 1.11.3
821      */
822     pushUInt64(L,0);
823     WSLUA_RETURN(1); /* The minimum value. */
824 }
825 
UInt64_tonumber(lua_State * L)826 WSLUA_METHOD UInt64_tonumber(lua_State* L) {
827     /* Returns a Lua number of the <<lua_class_UInt64,`UInt64`>> value. This may lose precision.
828        @since 1.11.3
829      */
830     lua_pushnumber(L,(lua_Number)(checkUInt64(L,1)));
831     WSLUA_RETURN(1); /* The Lua number. */
832 }
833 
UInt64__tostring(lua_State * L)834 WSLUA_METAMETHOD UInt64__tostring(lua_State* L) {
835     /* Converts the <<lua_class_UInt64,`UInt64`>> into a string. */
836     guint64 num = getUInt64(L,1);
837     gchar s[LUATYPE64_STRING_SIZE];
838     if (g_snprintf(s, LUATYPE64_STRING_SIZE, "%" G_GINT64_MODIFIER "u",(guint64)num) < 0) {
839         return luaL_error(L, "Error writing UInt64 to a string");
840     }
841     lua_pushstring(L,s);
842     WSLUA_RETURN(1); /* The Lua string. */
843 }
844 
UInt64_fromhex(lua_State * L)845 WSLUA_CONSTRUCTOR UInt64_fromhex(lua_State* L) {
846     /* Creates a <<lua_class_UInt64,`UInt64`>> object from the given hex string.
847        @since 1.11.3
848      */
849 #define WSLUA_ARG_UInt64_fromhex_HEX 1 /* The hex-ASCII Lua string. */
850     guint64 result = 0;
851     size_t len = 0;
852     const gchar *s = luaL_checklstring(L,WSLUA_ARG_UInt64_fromhex_HEX,&len);
853 
854     if (len > 0) {
855         if (sscanf(s, "%" G_GINT64_MODIFIER "x", &result) != 1) {
856             return luaL_error(L, "Error decoding the passed-in hex string");
857         }
858     }
859     pushUInt64(L,result);
860     WSLUA_RETURN(1); /* The new <<lua_class_UInt64,`UInt64`>> object. */
861 }
862 
UInt64_tohex(lua_State * L)863 WSLUA_METHOD UInt64_tohex(lua_State* L) {
864     /* Returns a hex string of the <<lua_class_UInt64,`UInt64`>> value.
865        @since 1.11.3
866      */
867 #define WSLUA_OPTARG_UInt64_new_NUMBYTES 2 /* The number of hex-chars/nibbles to generate.
868                                               Negative means uppercase Default is 16. */
869     guint64 b = getUInt64(L,1);
870     lua_Integer n = luaL_optinteger(L, WSLUA_OPTARG_UInt64_new_NUMBYTES, 16);
871     const gchar *hexdigits = "0123456789abcdef";
872     gchar buf[16];
873     lua_Integer i;
874     if (n < 0) { n = -n; hexdigits = "0123456789ABCDEF"; }
875     if (n > 16) n = 16;
876     for (i = n-1; i >= 0; --i) { buf[i] = hexdigits[b & 15]; b >>= 4; }
877     lua_pushlstring(L, buf, (size_t)n);
878     WSLUA_RETURN(1); /* The string hex. */
879 }
880 
UInt64_higher(lua_State * L)881 WSLUA_METHOD UInt64_higher(lua_State* L) {
882     /* Returns a Lua number of the higher 32 bits of the <<lua_class_UInt64,`UInt64`>> value. */
883     guint64 num = getUInt64(L,1);
884     guint64 b = num;
885     lua_Number n = 0;
886     b &= G_GUINT64_CONSTANT(0xFFFFFFFF00000000);
887     b >>= 32;
888     n = (lua_Number)(guint32)(b & G_GUINT64_CONSTANT(0x00000000FFFFFFFFF));
889     lua_pushnumber(L,n);
890     WSLUA_RETURN(1); /* The Lua number. */
891 }
892 
UInt64_lower(lua_State * L)893 WSLUA_METHOD UInt64_lower(lua_State* L) {
894     /* Returns a Lua number of the lower 32 bits of the <<lua_class_UInt64,`UInt64`>> value. */
895     guint64 b = getUInt64(L,1);
896     lua_pushnumber(L,(guint32)(b & G_GUINT64_CONSTANT(0x00000000FFFFFFFFF)));
897     WSLUA_RETURN(1); /* The Lua number. */
898 }
899 
UInt64__unm(lua_State * L)900 WSLUA_METAMETHOD UInt64__unm(lua_State* L) {
901     /* Returns the <<lua_class_UInt64,`UInt64`>> in a new <<lua_class_UInt64,`UInt64`>>, since unsigned integers can't be negated.
902        @since 1.11.3
903      */
904     pushUInt64(L,getUInt64(L,1));
905     WSLUA_RETURN(1); /* The <<lua_class_UInt64,`UInt64`>> object. */
906 }
907 
UInt64__add(lua_State * L)908 WSLUA_METAMETHOD UInt64__add(lua_State* L) {
909     /* Adds two <<lua_class_UInt64,`UInt64`>> together and returns a new one. This may wrap the value.
910        @since 1.11.3
911      */
912     WSLUA_MATH_OP_FUNC(UInt64,+);
913 }
914 
UInt64__sub(lua_State * L)915 WSLUA_METAMETHOD UInt64__sub(lua_State* L) {
916     /* Subtracts two <<lua_class_UInt64,`UInt64`>> and returns a new one. This may wrap the value.
917        @since 1.11.3
918      */
919     WSLUA_MATH_OP_FUNC(UInt64,-);
920 }
921 
UInt64__mul(lua_State * L)922 WSLUA_METAMETHOD UInt64__mul(lua_State* L) {
923     /* Multiplies two <<lua_class_UInt64,`UInt64`>> and returns a new one. This may truncate the value.
924        @since 1.11.3
925      */
926     WSLUA_MATH_OP_FUNC(UInt64,*);
927 }
928 
UInt64__div(lua_State * L)929 WSLUA_METAMETHOD UInt64__div(lua_State* L) {
930     /* Divides two <<lua_class_UInt64,`UInt64`>> and returns a new one. Integer divide, no remainder.
931        Trying to divide by zero results in a Lua error.
932        @since 1.11.3
933      */
934     UInt64 num1 = getUInt64(L,1);
935     UInt64 num2 = getUInt64(L,2);
936     if (num2 == 0) {
937         return luaL_error(L, "Trying to divide UInt64 by zero");
938     }
939     pushUInt64(L, num1 / num2);
940     WSLUA_RETURN(1); /* The <<lua_class_UInt64,`UInt64`>> result. */
941 }
942 
UInt64__mod(lua_State * L)943 WSLUA_METAMETHOD UInt64__mod(lua_State* L) {
944     /* Divides two <<lua_class_UInt64,`UInt64`>> and returns a new one of the remainder.
945        Trying to modulo by zero results in a Lua error.
946        @since 1.11.3
947      */
948     UInt64 num1 = getUInt64(L,1);
949     UInt64 num2 = getUInt64(L,2);
950     if (num2 == 0) {
951         return luaL_error(L, "Trying to modulo UInt64 by zero");
952     }
953     pushUInt64(L, num1 % num2);
954     WSLUA_RETURN(1); /* The <<lua_class_UInt64,`UInt64`>> result. */
955 }
956 
UInt64__pow(lua_State * L)957 WSLUA_METAMETHOD UInt64__pow(lua_State* L) {
958     /* The first <<lua_class_UInt64,`UInt64`>> is taken to the power of the second <<lua_class_UInt64,`UInt64`>>/number,
959        returning a new one. This may truncate the value.
960        @since 1.11.3
961      */
962     guint64 num1 = getUInt64(L,1);
963     guint64 num2 = getUInt64(L,2);
964     guint64 result;
965     if (num1 == 2) {
966         result = (num2 >= 8 * (guint64) sizeof(guint64)) ? 0 : ((guint64)1 << num2);
967     }
968     else {
969         for (result = 1; num2 > 0; num2 >>= 1) {
970             if (num2 & 1) result *= num1;
971             num1 *= num1;
972         }
973     }
974     pushUInt64(L,result);
975     WSLUA_RETURN(1); /* The <<lua_class_UInt64,`UInt64`>> object. */
976 }
977 
UInt64__eq(lua_State * L)978 WSLUA_METAMETHOD UInt64__eq(lua_State* L) {
979     /* Returns true if both <<lua_class_UInt64,`UInt64`>> are equal.
980        @since 1.11.3
981      */
982     WSLUA_COMP_OP_FUNC(UInt64,==);
983 }
984 
UInt64__lt(lua_State * L)985 WSLUA_METAMETHOD UInt64__lt(lua_State* L) {
986     /* Returns true if first <<lua_class_UInt64,`UInt64`>> is less than the second.
987        @since 1.11.3
988      */
989     WSLUA_COMP_OP_FUNC(UInt64,<);
990 }
991 
UInt64__le(lua_State * L)992 WSLUA_METAMETHOD UInt64__le(lua_State* L) {
993     /* Returns true if first <<lua_class_UInt64,`UInt64`>> is less than or equal to the second.
994        @since 1.11.3
995      */
996     WSLUA_COMP_OP_FUNC(UInt64,<=);
997 }
998 
UInt64_bnot(lua_State * L)999 WSLUA_METHOD UInt64_bnot(lua_State* L) {
1000     /* Returns a <<lua_class_UInt64,`UInt64`>> of the bitwise 'not' operation.
1001        @since 1.11.3
1002      */
1003     pushUInt64(L,~(getUInt64(L,1)));
1004     WSLUA_RETURN(1); /* The <<lua_class_UInt64,`UInt64`>> object. */
1005 }
1006 
UInt64_band(lua_State * L)1007 WSLUA_METHOD UInt64_band(lua_State* L) {
1008     /* Returns a <<lua_class_UInt64,`UInt64`>> of the bitwise 'and' operation, with the given number/`Int64`/`UInt64`.
1009        Note that multiple arguments are allowed.
1010        @since 1.11.3
1011      */
1012     WSLUA_BIT_OP_FUNC(UInt64,&=);
1013 }
1014 
UInt64_bor(lua_State * L)1015 WSLUA_METHOD UInt64_bor(lua_State* L) {
1016     /* Returns a <<lua_class_UInt64,`UInt64`>> of the bitwise 'or' operation, with the given number/`Int64`/`UInt64`.
1017        Note that multiple arguments are allowed.
1018        @since 1.11.3
1019      */
1020     WSLUA_BIT_OP_FUNC(UInt64,|=);
1021 }
1022 
UInt64_bxor(lua_State * L)1023 WSLUA_METHOD UInt64_bxor(lua_State* L) {
1024     /* Returns a <<lua_class_UInt64,`UInt64`>> of the bitwise 'xor' operation, with the given number/`Int64`/`UInt64`.
1025        Note that multiple arguments are allowed.
1026        @since 1.11.3
1027      */
1028     WSLUA_BIT_OP_FUNC(UInt64,^=);
1029 }
1030 
UInt64_lshift(lua_State * L)1031 WSLUA_METHOD UInt64_lshift(lua_State* L) {
1032     /* Returns a <<lua_class_UInt64,`UInt64`>> of the bitwise logical left-shift operation, by the
1033        given number of bits.
1034        @since 1.11.3
1035      */
1036 #define WSLUA_ARG_UInt64_lshift_NUMBITS 2 /* The number of bits to left-shift by. */
1037     guint64 b = getUInt64(L,1);
1038     guint32 n = wslua_checkguint32(L,WSLUA_ARG_UInt64_lshift_NUMBITS);
1039     pushUInt64(L,(b << n));
1040     WSLUA_RETURN(1); /* The <<lua_class_UInt64,`UInt64`>> object. */
1041 }
1042 
UInt64_rshift(lua_State * L)1043 WSLUA_METHOD UInt64_rshift(lua_State* L) {
1044     /* Returns a <<lua_class_UInt64,`UInt64`>> of the bitwise logical right-shift operation, by the
1045        given number of bits.
1046        @since 1.11.3
1047      */
1048 #define WSLUA_ARG_UInt64_rshift_NUMBITS 2 /* The number of bits to right-shift by. */
1049     guint64 b = getUInt64(L,1);
1050     guint32 n = wslua_checkguint32(L,WSLUA_ARG_UInt64_rshift_NUMBITS);
1051     pushUInt64(L,(b >> n));
1052     WSLUA_RETURN(1); /* The <<lua_class_UInt64,`UInt64`>> object. */
1053 }
1054 
UInt64_arshift(lua_State * L)1055 WSLUA_METHOD UInt64_arshift(lua_State* L) {
1056     /* Returns a <<lua_class_UInt64,`UInt64`>> of the bitwise arithmetic right-shift operation, by the
1057        given number of bits.
1058        @since 1.11.3
1059      */
1060 #define WSLUA_ARG_UInt64_arshift_NUMBITS 2 /* The number of bits to right-shift by. */
1061     guint64 b = getUInt64(L,1);
1062     guint32 n = wslua_checkguint32(L,WSLUA_ARG_UInt64_arshift_NUMBITS);
1063     pushUInt64(L,(b >> n));
1064     WSLUA_RETURN(1); /* The <<lua_class_UInt64,`UInt64`>> object. */
1065 }
1066 
UInt64_rol(lua_State * L)1067 WSLUA_METHOD UInt64_rol(lua_State* L) {
1068     /* Returns a <<lua_class_UInt64,`UInt64`>> of the bitwise left rotation operation, by the
1069        given number of bits (up to 63).
1070        @since 1.11.3
1071      */
1072 #define WSLUA_ARG_UInt64_rol_NUMBITS 2 /* The number of bits to roll left by. */
1073     guint64 b = getUInt64(L,1);
1074     guint32 n = wslua_checkguint32(L,WSLUA_ARG_UInt64_rol_NUMBITS);
1075     pushUInt64(L,((b << n) | (b >> (64-n))));
1076     WSLUA_RETURN(1); /* The <<lua_class_UInt64,`UInt64`>> object. */
1077 }
1078 
UInt64_ror(lua_State * L)1079 WSLUA_METHOD UInt64_ror(lua_State* L) {
1080     /* Returns a <<lua_class_UInt64,`UInt64`>> of the bitwise right rotation operation, by the
1081        given number of bits (up to 63).
1082        @since 1.11.3
1083      */
1084 #define WSLUA_ARG_UInt64_ror_NUMBITS 2 /* The number of bits to roll right by. */
1085     guint64 b = getUInt64(L,1);
1086     guint32 n = wslua_checkguint32(L,WSLUA_ARG_UInt64_ror_NUMBITS);
1087     pushUInt64(L,((b << (64-n)) | (b >> n)));
1088     WSLUA_RETURN(1); /* The <<lua_class_UInt64,`UInt64`>> object. */
1089 }
1090 
UInt64_bswap(lua_State * L)1091 WSLUA_METHOD UInt64_bswap(lua_State* L) {
1092     /* Returns a <<lua_class_UInt64,`UInt64`>> of the bytes swapped. This can be used to convert little-endian
1093        64-bit numbers to big-endian 64 bit numbers or vice versa.
1094        @since 1.11.3
1095      */
1096     guint64 b = getUInt64(L,1);
1097     guint64 result = 0;
1098     size_t i;
1099     for (i = 0; i < sizeof(guint64); i++) {
1100         result <<= 8;
1101         result |= (b & G_GUINT64_CONSTANT(0x00000000000000FF));
1102         b >>= 8;
1103     }
1104     pushUInt64(L,result);
1105     WSLUA_RETURN(1); /* The <<lua_class_UInt64,`UInt64`>> object. */
1106 }
1107 
1108 /* Gets registered as metamethod automatically by WSLUA_REGISTER_CLASS/META */
UInt64__gc(lua_State * L _U_)1109 static int UInt64__gc(lua_State* L _U_) {
1110     return 0;
1111 }
1112 
1113 WSLUA_METHODS UInt64_methods[] = {
1114     WSLUA_CLASS_FNREG(UInt64,new),
1115     WSLUA_CLASS_FNREG(UInt64,max),
1116     WSLUA_CLASS_FNREG(UInt64,min),
1117     WSLUA_CLASS_FNREG(UInt64,tonumber),
1118     WSLUA_CLASS_FNREG(UInt64,fromhex),
1119     WSLUA_CLASS_FNREG(UInt64,tohex),
1120     WSLUA_CLASS_FNREG(UInt64,higher),
1121     WSLUA_CLASS_FNREG(UInt64,lower),
1122     WSLUA_CLASS_FNREG(UInt64,encode),
1123     WSLUA_CLASS_FNREG(UInt64,decode),
1124     WSLUA_CLASS_FNREG(UInt64,bnot),
1125     WSLUA_CLASS_FNREG(UInt64,band),
1126     WSLUA_CLASS_FNREG(UInt64,bor),
1127     WSLUA_CLASS_FNREG(UInt64,bxor),
1128     WSLUA_CLASS_FNREG(UInt64,lshift),
1129     WSLUA_CLASS_FNREG(UInt64,rshift),
1130     WSLUA_CLASS_FNREG(UInt64,arshift),
1131     WSLUA_CLASS_FNREG(UInt64,rol),
1132     WSLUA_CLASS_FNREG(UInt64,ror),
1133     WSLUA_CLASS_FNREG(UInt64,bswap),
1134     { NULL, NULL }
1135 };
1136 
1137 WSLUA_META UInt64_meta[] = {
1138     WSLUA_CLASS_MTREG(UInt64,tostring),
1139     WSLUA_CLASS_MTREG(UInt64,call),
1140     WSLUA_CLASS_MTREG(wslua,concat),
1141     WSLUA_CLASS_MTREG(UInt64,unm),
1142     WSLUA_CLASS_MTREG(UInt64,add),
1143     WSLUA_CLASS_MTREG(UInt64,sub),
1144     WSLUA_CLASS_MTREG(UInt64,mul),
1145     WSLUA_CLASS_MTREG(UInt64,div),
1146     WSLUA_CLASS_MTREG(UInt64,mod),
1147     WSLUA_CLASS_MTREG(UInt64,pow),
1148     WSLUA_CLASS_MTREG(UInt64,eq),
1149     WSLUA_CLASS_MTREG(UInt64,lt),
1150     WSLUA_CLASS_MTREG(UInt64,le),
1151     { NULL, NULL }
1152 };
1153 
UInt64_register(lua_State * L)1154 LUALIB_API int UInt64_register(lua_State* L) {
1155     WSLUA_REGISTER_CLASS(UInt64);
1156     return 0;
1157 }
1158 
1159 /*
1160  * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
1161  *
1162  * Local variables:
1163  * c-basic-offset: 4
1164  * tab-width: 8
1165  * indent-tabs-mode: nil
1166  * End:
1167  *
1168  * vi: set shiftwidth=4 tabstop=8 expandtab:
1169  * :indentSize=4:tabSize=8:noTabs=true:
1170  */
1171