Merge pull request #4013 from vegansk/parse_uints
parseUInt and parseBiggestUInt functions
This commit is contained in:
commit
b296e7c01f
3 changed files with 70 additions and 0 deletions
|
|
@ -234,6 +234,47 @@ proc parseInt*(s: string, number: var int, start = 0): int {.
|
||||||
elif result != 0:
|
elif result != 0:
|
||||||
number = int(res)
|
number = int(res)
|
||||||
|
|
||||||
|
# overflowChecks doesn't work with uint64
|
||||||
|
proc rawParseUInt(s: string, b: var uint64, start = 0): int =
|
||||||
|
var
|
||||||
|
res = 0'u64
|
||||||
|
prev = 0'u64
|
||||||
|
i = start
|
||||||
|
if s[i] == '+': inc(i) # Allow
|
||||||
|
if s[i] in {'0'..'9'}:
|
||||||
|
b = 0
|
||||||
|
while s[i] in {'0'..'9'}:
|
||||||
|
prev = res
|
||||||
|
res = res * 10 + (ord(s[i]) - ord('0')).uint64
|
||||||
|
if prev > res:
|
||||||
|
return 0 # overflowChecks emulation
|
||||||
|
inc(i)
|
||||||
|
while s[i] == '_': inc(i) # underscores are allowed and ignored
|
||||||
|
b = res
|
||||||
|
result = i - start
|
||||||
|
|
||||||
|
proc parseBiggestUInt*(s: string, number: var uint64, start = 0): int {.
|
||||||
|
rtl, extern: "npuParseBiggestUInt", noSideEffect.} =
|
||||||
|
## parses an unsigned integer starting at `start` and stores the value into `number`.
|
||||||
|
## Result is the number of processed chars or 0 if there is no integer or overflow detected.
|
||||||
|
var res: uint64
|
||||||
|
# use 'res' for exception safety (don't write to 'number' in case of an
|
||||||
|
# overflow exception):
|
||||||
|
result = rawParseUInt(s, res, start)
|
||||||
|
number = res
|
||||||
|
|
||||||
|
proc parseUInt*(s: string, number: var uint, start = 0): int {.
|
||||||
|
rtl, extern: "npuParseUInt", noSideEffect.} =
|
||||||
|
## parses an unsigned integer starting at `start` and stores the value into `number`.
|
||||||
|
## Result is the number of processed chars or 0 if there is no integer or overflow detected.
|
||||||
|
var res: uint64
|
||||||
|
result = parseBiggestUInt(s, res, start)
|
||||||
|
if (sizeof(uint) <= 4) and
|
||||||
|
(res > 0xFFFF_FFFF'u64):
|
||||||
|
raise newException(OverflowError, "overflow")
|
||||||
|
elif result != 0:
|
||||||
|
number = uint(res)
|
||||||
|
|
||||||
proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {.
|
proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {.
|
||||||
magic: "ParseBiggestFloat", importc: "nimParseBiggestFloat", noSideEffect.}
|
magic: "ParseBiggestFloat", importc: "nimParseBiggestFloat", noSideEffect.}
|
||||||
## parses a float starting at `start` and stores the value into `number`.
|
## parses a float starting at `start` and stores the value into `number`.
|
||||||
|
|
|
||||||
|
|
@ -560,6 +560,24 @@ proc parseBiggestInt*(s: string): BiggestInt {.noSideEffect, procvar,
|
||||||
if L != s.len or L == 0:
|
if L != s.len or L == 0:
|
||||||
raise newException(ValueError, "invalid integer: " & s)
|
raise newException(ValueError, "invalid integer: " & s)
|
||||||
|
|
||||||
|
proc parseUInt*(s: string): uint {.noSideEffect, procvar,
|
||||||
|
rtl, extern: "nsuParseUInt".} =
|
||||||
|
## Parses a decimal unsigned integer value contained in `s`.
|
||||||
|
##
|
||||||
|
## If `s` is not a valid integer, `ValueError` is raised.
|
||||||
|
var L = parseutils.parseUInt(s, result, 0)
|
||||||
|
if L != s.len or L == 0:
|
||||||
|
raise newException(ValueError, "invalid unsigned integer: " & s)
|
||||||
|
|
||||||
|
proc parseBiggestUInt*(s: string): uint64 {.noSideEffect, procvar,
|
||||||
|
rtl, extern: "nsuParseBiggestUInt".} =
|
||||||
|
## Parses a decimal unsigned integer value contained in `s`.
|
||||||
|
##
|
||||||
|
## If `s` is not a valid integer, `ValueError` is raised.
|
||||||
|
var L = parseutils.parseBiggestUInt(s, result, 0)
|
||||||
|
if L != s.len or L == 0:
|
||||||
|
raise newException(ValueError, "invalid unsigned integer: " & s)
|
||||||
|
|
||||||
proc parseFloat*(s: string): float {.noSideEffect, procvar,
|
proc parseFloat*(s: string): float {.noSideEffect, procvar,
|
||||||
rtl, extern: "nsuParseFloat".} =
|
rtl, extern: "nsuParseFloat".} =
|
||||||
## Parses a decimal floating point value contained in `s`. If `s` is not
|
## Parses a decimal floating point value contained in `s`. If `s` is not
|
||||||
|
|
|
||||||
11
tests/stdlib/tparseuints.nim
Normal file
11
tests/stdlib/tparseuints.nim
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
discard """
|
||||||
|
action: run
|
||||||
|
"""
|
||||||
|
import unittest, strutils
|
||||||
|
|
||||||
|
suite "parseutils":
|
||||||
|
test "uint":
|
||||||
|
check: parseBiggestUInt("0") == 0'u64
|
||||||
|
check: parseBiggestUInt("18446744073709551615") == 0xFFFF_FFFF_FFFF_FFFF'u64
|
||||||
|
expect(ValueError):
|
||||||
|
discard parseBiggestUInt("18446744073709551616")
|
||||||
Loading…
Add table
Add a link
Reference in a new issue