summary refs log tree commit diff stats
path: root/compiler/rodutils.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rodutils.nim')
-rw-r--r--compiler/rodutils.nim97
1 files changed, 67 insertions, 30 deletions
diff --git a/compiler/rodutils.nim b/compiler/rodutils.nim
index 0456e9349..5355829c1 100644
--- a/compiler/rodutils.nim
+++ b/compiler/rodutils.nim
@@ -8,33 +8,68 @@
 #
 
 ## Serialization utilities for the compiler.
-import strutils
-
-proc c_snprintf(s: cstring; n:uint; frmt: cstring): cint {.importc: "snprintf", header: "<stdio.h>", nodecl, varargs.}
-
-proc toStrMaxPrecision*(f: BiggestFloat, literalPostfix = ""): string =
-  if f != f:
-    result = "NAN"
-  elif f == 0.0:
+import std/[strutils, math]
+
+when defined(nimPreviewSlimSystem):
+  import std/assertions
+
+# bcc on windows doesn't have C99 functions
+when defined(windows) and defined(bcc):
+  {.emit: """#if defined(_MSC_VER) && _MSC_VER < 1900
+  #include <stdarg.h>
+  static int c99_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) {
+    int count = -1;
+    if (size != 0) count = _vsnprintf_s(outBuf, size, _TRUNCATE, format, ap);
+    if (count == -1) count = _vscprintf(format, ap);
+    return count;
+  }
+  int snprintf(char *outBuf, size_t size, const char *format, ...) {
+    int count;
+    va_list ap;
+    va_start(ap, format);
+    count = c99_vsnprintf(outBuf, size, format, ap);
+    va_end(ap);
+    return count;
+  }
+  #endif
+  """.}
+
+proc c_snprintf(s: cstring; n: uint; frmt: cstring): cint {.importc: "snprintf", header: "<stdio.h>", nodecl, varargs.}
+
+
+when not declared(signbit):
+  proc c_signbit(x: SomeFloat): cint {.importc: "signbit", header: "<math.h>".}
+  proc signbit*(x: SomeFloat): bool {.inline.} =
+    result = c_signbit(x) != 0
+
+import std/formatfloat
+
+proc toStrMaxPrecision*(f: BiggestFloat | float32): string =
+  const literalPostfix = when f is float32: "f" else: ""
+  case classify(f)
+  of fcNan:
+    if signbit(f):
+      result = "-NAN"
+    else:
+      result = "NAN"
+  of fcNegZero:
+    result = "-0.0" & literalPostfix
+  of fcZero:
     result = "0.0" & literalPostfix
-  elif f == 0.5 * f:
-    if f > 0.0: result = "INF"
-    else: result = "-INF"
+  of fcInf:
+    result = "INF"
+  of fcNegInf:
+    result = "-INF"
   else:
-    when defined(nimNoArrayToCstringConversion):
-      result = newString(81)
-      let n = c_snprintf(result.cstring, result.len.uint, "%#.16e%s", f, literalPostfix.cstring)
-      setLen(result, n)
-    else:
-      var buf: array[0..80, char]
-      discard c_snprintf(buf.cstring, buf.len.uint, "%#.16e%s", f, literalPostfix.cstring)
-      result = $buf.cstring
+    result = ""
+    result.addFloatRoundtrip(f)
+    result.add literalPostfix
 
 proc encodeStr*(s: string, result: var string) =
-  for i in countup(0, len(s) - 1):
+  for i in 0..<s.len:
     case s[i]
-    of 'a'..'z', 'A'..'Z', '0'..'9', '_': add(result, s[i])
-    else: add(result, '\\' & toHex(ord(s[i]), 2))
+    of 'a'..'z', 'A'..'Z', '0'..'9', '_': result.add(s[i])
+    else: result.add('\\' & toHex(ord(s[i]), 2))
 
 proc hexChar(c: char, xi: var int) =
   case c
@@ -53,28 +88,28 @@ proc decodeStr*(s: cstring, pos: var int): string =
       var xi = 0
       hexChar(s[i-2], xi)
       hexChar(s[i-1], xi)
-      add(result, chr(xi))
+      result.add(chr(xi))
     of 'a'..'z', 'A'..'Z', '0'..'9', '_':
-      add(result, s[i])
+      result.add(s[i])
       inc(i)
     else: break
   pos = i
 
-const
-  chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+const chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
+
+{.push overflowChecks: off.}
 
 # since negative numbers require a leading '-' they use up 1 byte. Thus we
 # subtract/add `vintDelta` here to save space for small negative numbers
 # which are common in ROD files:
-const
-  vintDelta = 5
+const vintDelta = 5
 
 template encodeIntImpl(self) =
   var d: char
   var v = x
   var rem = v mod 190
   if rem < 0:
-    add(result, '-')
+    result.add('-')
     v = - (v div 190)
     rem = - rem
   else:
@@ -83,7 +118,7 @@ template encodeIntImpl(self) =
   if idx < 62: d = chars[idx]
   else: d = chr(idx - 62 + 128)
   if v != 0: self(v, result)
-  add(result, d)
+  result.add(d)
 
 proc encodeVBiggestIntAux(x: BiggestInt, result: var string) =
   ## encode a biggest int as a variable length base 190 int.
@@ -127,6 +162,8 @@ proc decodeVInt*(s: cstring, pos: var int): int =
 proc decodeVBiggestInt*(s: cstring, pos: var int): BiggestInt =
   decodeIntImpl()
 
+{.pop.}
+
 iterator decodeVIntArray*(s: cstring): int =
   var i = 0
   while s[i] != '\0':