wslua: fix NSTime:__tostring for negative values
authorPeter Wu <peter@lekensteyn.nl>
Thu, 24 May 2018 11:57:37 +0000 (13:57 +0200)
committerAnders Broman <a.broman58@gmail.com>
Fri, 25 May 2018 12:50:18 +0000 (12:50 +0000)
"nstime_t{A, B}" is defined as "A + B * 10^9" rather than an integer
part A and fractional part B.

Bug: 14720
Change-Id: I5321db7d5ecea8f976291d2a22667b02162194e2
Reviewed-on: https://code.wireshark.org/review/27775
Petri-Dish: Peter Wu <peter@lekensteyn.nl>
Tested-by: Petri Dish Buildbot
Reviewed-by: Anders Broman <a.broman58@gmail.com>
epan/wslua/wslua_nstime.c
test/lua/nstime.lua

index 749f1f7..0353735 100644 (file)
@@ -20,6 +20,9 @@
 #include "wslua.h"
 #include <wsutil/nstime.h>
 
+/* 1s = 10^9 ns. */
+#define NS_PER_S 1000000000
+
 /* WSLUA_CONTINUE_MODULE Pinfo */
 
 
@@ -61,8 +64,33 @@ WSLUA_METHOD NSTime_tonumber(lua_State* L) {
 WSLUA_METAMETHOD NSTime__tostring(lua_State* L) {
     NSTime nstime = checkNSTime(L,1);
     gchar *str;
-
-    str = wmem_strdup_printf(NULL, "%ld.%09d", (long)nstime->secs, nstime->nsecs);
+    long secs = (long)nstime->secs;
+    gint nsecs = nstime->nsecs;
+    gboolean negative_zero = FALSE;
+
+    /* Time is defined as sec + nsec/10^9, both parts can be negative.
+     * Translate this into the more familiar sec.nsec notation instead. */
+    if (secs > 0 && nsecs < 0) {
+        /* sign mismatch: (2, -3ns) -> 1.7 */
+        nsecs += NS_PER_S;
+        secs--;
+    } else if (secs < 0 && nsecs > 0) {
+        /* sign mismatch: (-2, 3ns) -> -1.7 */
+        nsecs = NS_PER_S - nsecs;
+        secs--;
+    } else if (nsecs < 0) {
+        /* Drop sign, the integer part already has it: (-2, -3ns) -> -2.3 */
+        nsecs = -nsecs;
+        /* In case the integer part is zero, it does not has a sign, so remember
+         * that it must be explicitly added. */
+        negative_zero = secs == 0;
+    }
+
+    if (negative_zero) {
+        str = wmem_strdup_printf(NULL, "-0.%09d", nsecs);
+    } else {
+        str = wmem_strdup_printf(NULL, "%ld.%09d", secs, nsecs);
+    }
     lua_pushstring(L, str);
     wmem_free(NULL, str);
 
index c8ecdd2..00daa3e 100644 (file)
@@ -31,7 +31,7 @@ end
 -- note ip only runs 3 times because it gets removed
 -- and bootp only runs twice because the filter makes it run
 -- once and then it gets replaced with a different one for the second time
-local taptests = { [FRAME]=4, [OTHER]=40 }
+local taptests = { [FRAME]=4, [OTHER]=44 }
 local function getResults()
     print("\n-----------------------------\n")
     for k,v in pairs(taptests) do
@@ -143,6 +143,13 @@ test("NSTime.set-38", first == NSTime(123,100))
 test("NSTime.get-39", first.secs == 123)
 test("NSTime.get-40", first.nsecs == 100)
 
+local minus0_4 = NSTime() - NSTime(0,400000000)
+test("NSTime.negative_tonumber-41", minus0_4:tonumber() == -0.4)
+test("NSTime.negative_tostring-42", tostring(minus0_4) == "-0.400000000")
+local minus0_4 = NSTime() - NSTime(1,400000000)
+test("NSTime.negative_tonumber-43", minus0_4:tonumber() == -1.4)
+test("NSTime.negative_tostring-44", tostring(minus0_4) == "-1.400000000")
+
 
 ----------------------------------
 -- revert to original test function, kinda sorta