diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2016-03-31 16:35:25 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2016-03-31 16:35:25 +0200 |
commit | b296e7c01f3d29e2e429bfc1fc4203727cd3b1ce (patch) | |
tree | 5debdaf0b92934af508d9ef2568c654682f6fb64 /lib | |
parent | d836028fe7b18c93c9a9751f470da387eab09af1 (diff) | |
parent | c34a68d76f7f552b235592da7634acc333275df9 (diff) | |
download | Nim-b296e7c01f3d29e2e429bfc1fc4203727cd3b1ce.tar.gz |
Merge pull request #4013 from vegansk/parse_uints
parseUInt and parseBiggestUInt functions
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pure/parseutils.nim | 41 | ||||
-rw-r--r-- | lib/pure/strutils.nim | 18 |
2 files changed, 59 insertions, 0 deletions
diff --git a/lib/pure/parseutils.nim b/lib/pure/parseutils.nim index 698bde42a..3e25eba22 100644 --- a/lib/pure/parseutils.nim +++ b/lib/pure/parseutils.nim @@ -234,6 +234,47 @@ proc parseInt*(s: string, number: var int, start = 0): int {. elif result != 0: 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 {. magic: "ParseBiggestFloat", importc: "nimParseBiggestFloat", noSideEffect.} ## parses a float starting at `start` and stores the value into `number`. diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index f2c1e77e1..eebadf4c0 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -560,6 +560,24 @@ proc parseBiggestInt*(s: string): BiggestInt {.noSideEffect, procvar, if L != s.len or L == 0: 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, rtl, extern: "nsuParseFloat".} = ## Parses a decimal floating point value contained in `s`. If `s` is not |