Browse Source

Make jim_float handle NaN-s and Inf-s

Close #2
rexim 4 years ago
parent
commit
5c9b05bccf
2 changed files with 28 additions and 14 deletions
  1. 5 0
      example.c
  2. 23 14
      jim.h

+ 5 - 0
example.c

@@ -29,9 +29,14 @@ int main()
 
         jim_member_key(&jim, "floats", NULL);
         jim_array_begin(&jim);
+            jim_float(&jim, 0.0, 4);
+            jim_float(&jim, -0.0, 4);
             jim_float(&jim, 3.1415, 4);
             jim_float(&jim, 2.71828, 5);
             jim_float(&jim, 1.6180, 4);
+            jim_float(&jim, 0.0 / 0.0, 4);
+            jim_float(&jim, 1.0 / 0.0, 4);
+            jim_float(&jim, -1.0 / 0.0, 4);
         jim_array_end(&jim);
 
         jim_member_key(&jim, "string", NULL);

+ 23 - 14
jim.h

@@ -229,26 +229,35 @@ void jim_integer(Jim *jim, long long int x)
     }
 }
 
+static int is_nan_or_inf(double x)
+{
+    unsigned long long int mask = (1ULL << 11ULL) - 1ULL;
+    return (((*(unsigned long long int*) &x) >> 52ULL) & mask) == mask;
+}
+
 void jim_float(Jim *jim, double x, int precision)
 {
-    // TODO(#2): jim_float does not support NaN and Inf-s
     if (jim->error == JIM_OK) {
-        jim_element_begin(jim);
+        if (is_nan_or_inf(x)) {
+            jim_null(jim);
+        } else {
+            jim_element_begin(jim);
 
-        jim_integer_no_element(jim, (long long int) x);
-        x -= (double) (long long int) x;
-        while (precision-- > 0) {
-            x *= 10.0;
-        }
-        jim_write_cstr(jim, ".");
+            jim_integer_no_element(jim, (long long int) x);
+            x -= (double) (long long int) x;
+            while (precision-- > 0) {
+                x *= 10.0;
+            }
+            jim_write_cstr(jim, ".");
 
-        long long int y = (long long int) x;
-        if (y < 0) {
-            y = -y;
-        }
-        jim_integer_no_element(jim, y);
+            long long int y = (long long int) x;
+            if (y < 0) {
+                y = -y;
+            }
+            jim_integer_no_element(jim, y);
 
-        jim_element_end(jim);
+            jim_element_end(jim);
+        }
     }
 }