diff options
Diffstat (limited to 'compiler/rodutils.nim')
-rw-r--r-- | compiler/rodutils.nim | 97 |
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': |