diff options
author | Dominik Picheta <dominikpicheta@googlemail.com> | 2018-01-26 15:32:28 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-01-26 15:32:28 +0000 |
commit | 1a565d7b2087f603a450527ab81e9d5a5f4ad831 (patch) | |
tree | 8ba2bf7996168a3d072720f03406fc92a3de831e /lib | |
parent | 394757dbf521b8b4a16dd694a687039faeb21682 (diff) | |
parent | 4100932a4b9abc184aa59e7e78dc975331eff920 (diff) | |
download | Nim-1a565d7b2087f603a450527ab81e9d5a5f4ad831.tar.gz |
Merge pull request #6517 from FedericoCeratto/hexstr
Add string-to-hex and back conversions
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pure/strutils.nim | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index dbb4db781..2ad006001 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -944,6 +944,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. @@ -1026,6 +1039,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`. ## |