summary refs log tree commit diff stats
path: root/lib/pure
diff options
context:
space:
mode:
authorMiran <narimiran@disroot.org>2020-09-04 09:23:27 +0200
committerGitHub <noreply@github.com>2020-09-04 09:23:27 +0200
commit4fb17bc03be3046d8ff619a74eec7cb7ce02b4d2 (patch)
tree64e1452f63bb3b4c986842b398cafe877a6ebfc6 /lib/pure
parent48f29972210612b41cb6d98122672b1713edc907 (diff)
downloadNim-4fb17bc03be3046d8ff619a74eec7cb7ce02b4d2.tar.gz
fix #15257, `toHex` couldn't handle large uint64 (#15261) [backport:1.2]
Diffstat (limited to 'lib/pure')
-rw-r--r--lib/pure/strutils.nim43
1 files changed, 31 insertions, 12 deletions
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index a0a172430..20010ff81 100644
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -938,6 +938,31 @@ proc toOct*(x: BiggestInt, len: Positive): string {.noSideEffect,
     inc shift, 3
     mask = mask shl BiggestUInt(3)
 
+proc toHexImpl(x: BiggestUInt, len: Positive, handleNegative: bool): string {.noSideEffect.} =
+  const
+    HexChars = "0123456789ABCDEF"
+  var n = x
+  result = newString(len)
+  for j in countdown(len-1, 0):
+    result[j] = HexChars[int(n and 0xF)]
+    n = n shr 4
+    # handle negative overflow
+    if n == 0 and handleNegative: n = not(BiggestUInt 0)
+
+proc toHex*(x: BiggestUInt, len: Positive): string {.noSideEffect.} =
+  ## Converts `x` to its hexadecimal representation.
+  ##
+  ## The resulting string will be exactly `len` characters long. No prefix like
+  ## ``0x`` is generated.
+  runnableExamples:
+    let
+      a = 62'u64
+      b = 4097'u64
+    doAssert a.toHex(3) == "03E"
+    doAssert b.toHex(3) == "001"
+    doAssert b.toHex(4) == "1001"
+  toHexImpl(x, len, false)
+
 proc toHex*(x: BiggestInt, len: Positive): string {.noSideEffect,
   rtl, extern: "nsuToHex".} =
   ## Converts `x` to its hexadecimal representation.
@@ -948,25 +973,19 @@ proc toHex*(x: BiggestInt, len: Positive): string {.noSideEffect,
     let
       a = 62
       b = 4097
+      c = -8
     doAssert a.toHex(3) == "03E"
     doAssert b.toHex(3) == "001"
     doAssert b.toHex(4) == "1001"
-  const
-    HexChars = "0123456789ABCDEF"
-  var
-    n = x
-  result = newString(len)
-  for j in countdown(len-1, 0):
-    result[j] = HexChars[int(n and 0xF)]
-    n = n shr 4
-    # handle negative overflow
-    if n == 0 and x < 0: n = -1
+    doAssert c.toHex(6) == "FFFFF8"
+  toHexImpl(cast[BiggestUInt](x), len, x < 0)
 
-proc toHex*[T: SomeInteger](x: T): string =
+proc toHex*[T: SomeInteger](x: T): string {.noSideEffect.} =
   ## Shortcut for ``toHex(x, T.sizeof * 2)``
   runnableExamples:
     doAssert toHex(1984'i64) == "00000000000007C0"
-  toHex(BiggestInt(x), T.sizeof * 2)
+    doAssert toHex(1984'i16) == "07C0"
+  toHexImpl(cast[BiggestUInt](x), 2*sizeof(T), x < 0)
 
 proc toHex*(s: string): string {.noSideEffect, rtl.} =
   ## Converts a bytes string to its hexadecimal representation.