diff --git a/stint/io.nim b/stint/io.nim index 07cbcd8..a512c05 100644 --- a/stint/io.nim +++ b/stint/io.nim @@ -218,17 +218,20 @@ func skipPrefixes(current_idx: var int, str: string, radix: range[2..16]) {.inli doAssert current_idx == 0, "skipPrefixes only works for prefixes (position 0 and 1 of the string)" if str[0] == '0': if str[1] in {'x', 'X'}: - if radix != 16: + if radix == 16: + current_idx = 2 + else: raise newException(ValueError,"Parsing mismatch, 0x prefix is only valid for a hexadecimal number (base 16)") - current_idx = 2 elif str[1] in {'o', 'O'}: - if radix != 8: + if radix == 8: + current_idx = 2 + else: raise newException(ValueError, "Parsing mismatch, 0o prefix is only valid for an octal number (base 8)") - current_idx = 2 elif str[1] in {'b', 'B'}: - if radix != 2: - raise newException(ValueError, "Parsing mismatch, 0b prefix is only valid for a binary number (base 2)") - current_idx = 2 + if radix == 2: + current_idx = 2 + elif radix != 16: + raise newException(ValueError, "Parsing mismatch, 0b prefix is only valid for a binary number (base 2) or as first byte of a hexadecimal number (base 16)") func nextNonBlank(current_idx: var int, s: string) {.inline.} = ## Move the current index, skipping white spaces and "_" characters. diff --git a/tests/test_io.nim b/tests/test_io.nim index d93d777..ace0b28 100644 --- a/tests/test_io.nim +++ b/tests/test_io.nim @@ -7,7 +7,7 @@ # # at your option. This file may not be copied, modified, or distributed except according to those terms. -import ../stint, unittest, strutils, math, test_helpers, tables +import ../stint, unittest, strutils, math, test_helpers, tables, std/strformat template nativeStuint(chk, nint: untyped, bits: int) = chk $(nint.stuint(bits)) == $(nint) @@ -1090,23 +1090,79 @@ proc main() = check: a == b check: -123456789'i64 == cast[int64](a) + test "Creation from binary strings": + block: + for i in 0..255: + let a = fmt("{i:#b}").parse(StInt[64], radix = 2) + let b = i.stint(64) + + check: a == b + check: int64(i) == cast[int64](a) + + block: + for i in 0..255: + let a = fmt("{i:#b}").parse(StUint[64], radix = 2) + let b = i.stuint(64) + + check: a == b + check: uint64(i) == cast[uint64](a) + + block: + let a = "0b1111111111111111".parse(StInt[16], 2) + let b = (-1'i16).stint(16) + + check: a == b + check: -1'i16 == cast[int16](a) + + test "Creation from octal strings": + block: + for i in 0..255: + let a = fmt("{i:#o}").parse(StInt[64], radix = 8) + let b = i.stint(64) + + check: a == b + check: int64(i) == cast[int64](a) + + block: + for i in 0..255: + let a = fmt("{i:#o}").parse(StUint[64], radix = 8) + let b = i.stuint(64) + + check: a == b + check: uint64(i) == cast[uint64](a) + + block: + let a = "0o177777".parse(StInt[16], 8) + let b = (-1'i16).stint(16) + + check: a == b + check: -1'i16 == cast[int16](a) + test "Creation from hex strings": block: - let a = "0xFF".parse(StInt[64], radix = 16) - let b = 255.stint(64) + for i in 0..255: + let a = fmt("{i:#x}").parse(StInt[64], radix = 16) + let aUppercase = fmt("{i:#X}").parse(StInt[64], radix = 16) + let b = i.stint(64) - check: a == b - check: 255'i64 == cast[int64](a) + check: a == aUppercase + check: a == b + check: int64(i) == cast[int64](a) block: - let a = "0xFF".parse(StUint[64], radix = 16) - let b = 255.stuint(64) + for i in 0..255: + let a = fmt("{i:#x}").parse(StUint[64], radix = 16) + let aUppercase = fmt("{i:#X}").parse(StUint[64], radix = 16) + let b = i.stuint(64) - check: a == b - check: 255'u64 == cast[uint64](a) + check: a == aUppercase + check: a == b + check: uint64(i) == cast[uint64](a) - let a2 = hexToUint[64]("0xFF") - check: a == a2 + let a2 = hexToUint[64](fmt("{i:#x}")) + let a3 = hexToUint[64](fmt("{i:#X}")) + check: a == a2 + check: a == a3 block: let a = "0xFFFF".parse(StInt[16], 16) @@ -1115,6 +1171,14 @@ proc main() = check: a == b check: -1'i16 == cast[int16](a) + block: + let a = "0b1234abcdef".parse(StInt[64], 16) + let b = "0x0b1234abcdef".parse(StInt[64], 16) + let c = 0x0b1234abcdef.stint(64) + + check: a == b + check: a == c + test "Conversion to decimal strings": block: let a = 1234567891234567890.stint(128)