Add string-to-hex and back conversions
Add parseHexStr and toHex and tests.
This commit is contained in:
parent
5e93eb9d7a
commit
4100932a4b
2 changed files with 68 additions and 0 deletions
|
|
@ -930,6 +930,19 @@ proc toHex*[T](x: T): string =
|
||||||
## Shortcut for ``toHex(x, T.sizeOf * 2)``
|
## Shortcut for ``toHex(x, T.sizeOf * 2)``
|
||||||
toHex(BiggestInt(x), T.sizeOf * 2)
|
toHex(BiggestInt(x), T.sizeOf * 2)
|
||||||
|
|
||||||
|
proc toHex*(s: string): string {.noSideEffect, rtl.} =
|
||||||
|
## Converts a bytes string to its hexadecimal representation.
|
||||||
|
##
|
||||||
|
## The output is twice the input long. No prefix like
|
||||||
|
## ``0x`` is generated.
|
||||||
|
const HexChars = "0123456789ABCDEF"
|
||||||
|
result = newString(s.len * 2)
|
||||||
|
for pos, c in s:
|
||||||
|
var n = ord(c)
|
||||||
|
result[pos * 2 + 1] = HexChars[n and 0xF]
|
||||||
|
n = n shr 4
|
||||||
|
result[pos * 2] = HexChars[n]
|
||||||
|
|
||||||
proc intToStr*(x: int, minchars: Positive = 1): string {.noSideEffect,
|
proc intToStr*(x: int, minchars: Positive = 1): string {.noSideEffect,
|
||||||
rtl, extern: "nsuIntToStr".} =
|
rtl, extern: "nsuIntToStr".} =
|
||||||
## Converts `x` to its decimal representation.
|
## Converts `x` to its decimal representation.
|
||||||
|
|
@ -1012,6 +1025,43 @@ proc parseHexInt*(s: string): int {.noSideEffect, procvar,
|
||||||
of '\0': break
|
of '\0': break
|
||||||
else: raise newException(ValueError, "invalid integer: " & s)
|
else: raise newException(ValueError, "invalid integer: " & s)
|
||||||
|
|
||||||
|
proc generateHexCharToValueMap(): string =
|
||||||
|
## Generate a string to map a hex digit to uint value
|
||||||
|
result = ""
|
||||||
|
for inp in 0..255:
|
||||||
|
let ch = chr(inp)
|
||||||
|
let o =
|
||||||
|
case ch:
|
||||||
|
of '0'..'9': inp - ord('0')
|
||||||
|
of 'a'..'f': inp - ord('a') + 10
|
||||||
|
of 'A'..'F': inp - ord('A') + 10
|
||||||
|
else: 17 # indicates an invalid hex char
|
||||||
|
result.add chr(o)
|
||||||
|
|
||||||
|
const hexCharToValueMap = generateHexCharToValueMap()
|
||||||
|
|
||||||
|
proc parseHexStr*(s: string): string {.noSideEffect, procvar,
|
||||||
|
rtl, extern: "nsuParseHexStr".} =
|
||||||
|
## Convert hex-encoded string to byte string, e.g.:
|
||||||
|
##
|
||||||
|
## .. code-block:: nim
|
||||||
|
## hexToStr("00ff") == "\0\255"
|
||||||
|
##
|
||||||
|
## Raises ``ValueError`` for an invalid hex values. The comparison is
|
||||||
|
## case-insensitive.
|
||||||
|
if s.len mod 2 != 0:
|
||||||
|
raise newException(ValueError, "Incorrect hex string len")
|
||||||
|
result = newString(s.len div 2)
|
||||||
|
var buf = 0
|
||||||
|
for pos, c in s:
|
||||||
|
let val = hexCharToValueMap[ord(c)].ord
|
||||||
|
if val == 17:
|
||||||
|
raise newException(ValueError, "Invalid hex char " & repr(c))
|
||||||
|
if pos mod 2 == 0:
|
||||||
|
buf = val
|
||||||
|
else:
|
||||||
|
result[pos div 2] = chr(val + buf shl 4)
|
||||||
|
|
||||||
proc parseBool*(s: string): bool =
|
proc parseBool*(s: string): bool =
|
||||||
## Parses a value into a `bool`.
|
## Parses a value into a `bool`.
|
||||||
##
|
##
|
||||||
|
|
|
||||||
|
|
@ -229,6 +229,24 @@ assert "/1/2/3".rfind('0') == -1
|
||||||
assert(toHex(100i16, 32) == "00000000000000000000000000000064")
|
assert(toHex(100i16, 32) == "00000000000000000000000000000064")
|
||||||
assert(toHex(-100i16, 32) == "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C")
|
assert(toHex(-100i16, 32) == "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C")
|
||||||
|
|
||||||
|
assert "".parseHexStr == ""
|
||||||
|
assert "00Ff80".parseHexStr == "\0\xFF\x80"
|
||||||
|
try:
|
||||||
|
discard "00Ff8".parseHexStr
|
||||||
|
assert false, "Should raise ValueError"
|
||||||
|
except ValueError:
|
||||||
|
discard
|
||||||
|
|
||||||
|
try:
|
||||||
|
discard "0k".parseHexStr
|
||||||
|
assert false, "Should raise ValueError"
|
||||||
|
except ValueError:
|
||||||
|
discard
|
||||||
|
|
||||||
|
assert "".toHex == ""
|
||||||
|
assert "\x00\xFF\x80".toHex == "00FF80"
|
||||||
|
assert "0123456789abcdef".parseHexStr.toHex == "0123456789ABCDEF"
|
||||||
|
|
||||||
assert(' '.repeat(8)== " ")
|
assert(' '.repeat(8)== " ")
|
||||||
assert(" ".repeat(8) == " ")
|
assert(" ".repeat(8) == " ")
|
||||||
assert(spaces(8) == " ")
|
assert(spaces(8) == " ")
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue