mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-29 01:14:41 +00:00
Add string-to-hex and back conversions
Add parseHexStr and toHex and tests.
This commit is contained in:
@@ -930,6 +930,19 @@ proc toHex*[T](x: T): string =
|
||||
## Shortcut for ``toHex(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,
|
||||
rtl, extern: "nsuIntToStr".} =
|
||||
## Converts `x` to its decimal representation.
|
||||
@@ -1012,6 +1025,43 @@ proc parseHexInt*(s: string): int {.noSideEffect, procvar,
|
||||
of '\0': break
|
||||
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 =
|
||||
## 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) == "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(spaces(8) == " ")
|
||||
|
||||
Reference in New Issue
Block a user