mirror of
https://github.com/nim-lang/Nim.git
synced 2026-05-05 05:24:49 +00:00
* clarify `parseHexInt`, `parseOctInt` docstring and exception msgs * add `parseBinInt` based on `parseutil.parseBin` implementation Adds a `parseBinInt`, which parses a binary integer string and returns it as an integer. This is based on the implementation of `parseutil.parseBin`, removing the unnecessary parts. * add tests for all `parse(Hex|Oct|Bin)Int` procs * replace `parse*Int` proc impls by call to parseutil procs Replaces the `parse(Hex|Oct|Bin)Int` procedure implementation by calls to the `parseutil` procs, which receive a mutable argument. Has the main advantage that the empty string as well as a "prefix only" string, e.g. "0x" counts as an invalid integer. Also moves the `parseOctInt` proc further up in the file so that all `parse` procs are below one another. * replace `var L` by `let L` in `parse` procs There's no reason for the usage of `var` here. * add `maxLen` optional arg for `parseutil.parse(Oct|Bin)` Plus small change to test cases. * update changelog about `parse*Int` procs * fix `rejectParse` template in `tstrutils` * make sure only `s.len` chars are parsed, if `maxLen+start` > s.len Fixes a previous bug in `parseHex` (and now affected `parseOct` and `parseBin`), which allowed to set `start + maxLen` to be larger than the strings length. This resulted in an out of bounds access. * move `parse*Int` proc change to breaking changes, add double `
This commit is contained in:
@@ -47,12 +47,14 @@ proc parseHex*(s: string, number: var int, start = 0; maxLen = 0): int {.
|
||||
## discard parseHex("0x38", value)
|
||||
## assert value == -200
|
||||
##
|
||||
## If 'maxLen==0' the length of the hexadecimal number has no
|
||||
## upper bound. Not more than ```maxLen`` characters are parsed.
|
||||
## If ``maxLen == 0`` the length of the hexadecimal number has no upper bound.
|
||||
## Else no more than ``start + maxLen`` characters are parsed, up to the
|
||||
## length of the string.
|
||||
var i = start
|
||||
var foundDigit = false
|
||||
let last = if maxLen == 0: s.len else: i+maxLen
|
||||
if i+1 < last and s[i] == '0' and (s[i+1] == 'x' or s[i+1] == 'X'): inc(i, 2)
|
||||
# get last index based on minimum `start + maxLen` or `s.len`
|
||||
let last = min(s.len, if maxLen == 0: s.len else: i+maxLen)
|
||||
if i+1 < last and s[i] == '0' and (s[i+1] in {'x', 'X'}): inc(i, 2)
|
||||
elif i < last and s[i] == '#': inc(i)
|
||||
while i < last:
|
||||
case s[i]
|
||||
@@ -70,14 +72,20 @@ proc parseHex*(s: string, number: var int, start = 0; maxLen = 0): int {.
|
||||
inc(i)
|
||||
if foundDigit: result = i-start
|
||||
|
||||
proc parseOct*(s: string, number: var int, start = 0): int {.
|
||||
proc parseOct*(s: string, number: var int, start = 0, maxLen = 0): int {.
|
||||
rtl, extern: "npuParseOct", noSideEffect.} =
|
||||
## parses an octal number and stores its value in ``number``. Returns
|
||||
## Parses an octal number and stores its value in ``number``. Returns
|
||||
## the number of the parsed characters or 0 in case of an error.
|
||||
##
|
||||
## If ``maxLen == 0`` the length of the octal number has no upper bound.
|
||||
## Else no more than ``start + maxLen`` characters are parsed, up to the
|
||||
## length of the string.
|
||||
var i = start
|
||||
var foundDigit = false
|
||||
if i+1 < s.len and s[i] == '0' and (s[i+1] == 'o' or s[i+1] == 'O'): inc(i, 2)
|
||||
while i < s.len:
|
||||
# get last index based on minimum `start + maxLen` or `s.len`
|
||||
let last = min(s.len, if maxLen == 0: s.len else: i+maxLen)
|
||||
if i+1 < last and s[i] == '0' and (s[i+1] in {'o', 'O'}): inc(i, 2)
|
||||
while i < last:
|
||||
case s[i]
|
||||
of '_': discard
|
||||
of '0'..'7':
|
||||
@@ -87,14 +95,20 @@ proc parseOct*(s: string, number: var int, start = 0): int {.
|
||||
inc(i)
|
||||
if foundDigit: result = i-start
|
||||
|
||||
proc parseBin*(s: string, number: var int, start = 0): int {.
|
||||
proc parseBin*(s: string, number: var int, start = 0, maxLen = 0): int {.
|
||||
rtl, extern: "npuParseBin", noSideEffect.} =
|
||||
## parses an binary number and stores its value in ``number``. Returns
|
||||
## Parses an binary number and stores its value in ``number``. Returns
|
||||
## the number of the parsed characters or 0 in case of an error.
|
||||
##
|
||||
## If ``maxLen == 0`` the length of the binary number has no upper bound.
|
||||
## Else no more than ``start + maxLen`` characters are parsed, up to the
|
||||
## length of the string.
|
||||
var i = start
|
||||
var foundDigit = false
|
||||
if i+1 < s.len and s[i] == '0' and (s[i+1] == 'b' or s[i+1] == 'B'): inc(i, 2)
|
||||
while i < s.len:
|
||||
# get last index based on minimum `start + maxLen` or `s.len`
|
||||
let last = min(s.len, if maxLen == 0: s.len else: i+maxLen)
|
||||
if i+1 < last and s[i] == '0' and (s[i+1] in {'b', 'B'}): inc(i, 2)
|
||||
while i < last:
|
||||
case s[i]
|
||||
of '_': discard
|
||||
of '0'..'1':
|
||||
|
||||
@@ -844,7 +844,7 @@ proc parseInt*(s: string): int {.noSideEffect, procvar,
|
||||
## Parses a decimal integer value contained in `s`.
|
||||
##
|
||||
## If `s` is not a valid integer, `ValueError` is raised.
|
||||
var L = parseutils.parseInt(s, result, 0)
|
||||
let L = parseutils.parseInt(s, result, 0)
|
||||
if L != s.len or L == 0:
|
||||
raise newException(ValueError, "invalid integer: " & s)
|
||||
|
||||
@@ -853,7 +853,7 @@ proc parseBiggestInt*(s: string): BiggestInt {.noSideEffect, procvar,
|
||||
## Parses a decimal integer value contained in `s`.
|
||||
##
|
||||
## If `s` is not a valid integer, `ValueError` is raised.
|
||||
var L = parseutils.parseBiggestInt(s, result, 0)
|
||||
let L = parseutils.parseBiggestInt(s, result, 0)
|
||||
if L != s.len or L == 0:
|
||||
raise newException(ValueError, "invalid integer: " & s)
|
||||
|
||||
@@ -862,7 +862,7 @@ proc parseUInt*(s: string): uint {.noSideEffect, procvar,
|
||||
## 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)
|
||||
let L = parseutils.parseUInt(s, result, 0)
|
||||
if L != s.len or L == 0:
|
||||
raise newException(ValueError, "invalid unsigned integer: " & s)
|
||||
|
||||
@@ -871,7 +871,7 @@ proc parseBiggestUInt*(s: string): BiggestUInt {.noSideEffect, procvar,
|
||||
## 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)
|
||||
let L = parseutils.parseBiggestUInt(s, result, 0)
|
||||
if L != s.len or L == 0:
|
||||
raise newException(ValueError, "invalid unsigned integer: " & s)
|
||||
|
||||
@@ -880,33 +880,42 @@ proc parseFloat*(s: string): float {.noSideEffect, procvar,
|
||||
## Parses a decimal floating point value contained in `s`. If `s` is not
|
||||
## a valid floating point number, `ValueError` is raised. ``NAN``,
|
||||
## ``INF``, ``-INF`` are also supported (case insensitive comparison).
|
||||
var L = parseutils.parseFloat(s, result, 0)
|
||||
let L = parseutils.parseFloat(s, result, 0)
|
||||
if L != s.len or L == 0:
|
||||
raise newException(ValueError, "invalid float: " & s)
|
||||
|
||||
proc parseBinInt*(s: string): int {.noSideEffect, procvar,
|
||||
rtl, extern: "nsuParseBinInt".} =
|
||||
## Parses a binary integer value contained in `s`.
|
||||
##
|
||||
## If `s` is not a valid binary integer, `ValueError` is raised. `s` can have
|
||||
## one of the following optional prefixes: ``0b``, ``0B``. Underscores within
|
||||
## `s` are ignored.
|
||||
let L = parseutils.parseBin(s, result, 0)
|
||||
if L != s.len or L == 0:
|
||||
raise newException(ValueError, "invalid binary integer: " & s)
|
||||
|
||||
proc parseOctInt*(s: string): int {.noSideEffect,
|
||||
rtl, extern: "nsuParseOctInt".} =
|
||||
## Parses an octal integer value contained in `s`.
|
||||
##
|
||||
## If `s` is not a valid oct integer, `ValueError` is raised. `s` can have one
|
||||
## of the following optional prefixes: ``0o``, ``0O``. Underscores within
|
||||
## `s` are ignored.
|
||||
let L = parseutils.parseOct(s, result, 0)
|
||||
if L != s.len or L == 0:
|
||||
raise newException(ValueError, "invalid oct integer: " & s)
|
||||
|
||||
proc parseHexInt*(s: string): int {.noSideEffect, procvar,
|
||||
rtl, extern: "nsuParseHexInt".} =
|
||||
## Parses a hexadecimal integer value contained in `s`.
|
||||
##
|
||||
## If `s` is not a valid integer, `ValueError` is raised. `s` can have one
|
||||
## If `s` is not a valid hex integer, `ValueError` is raised. `s` can have one
|
||||
## of the following optional prefixes: ``0x``, ``0X``, ``#``. Underscores
|
||||
## within `s` are ignored.
|
||||
var i = 0
|
||||
if i+1 < s.len and s[i] == '0' and (s[i+1] == 'x' or s[i+1] == 'X'): inc(i, 2)
|
||||
elif i < s.len and s[i] == '#': inc(i)
|
||||
while i < s.len:
|
||||
case s[i]
|
||||
of '_': inc(i)
|
||||
of '0'..'9':
|
||||
result = result shl 4 or (ord(s[i]) - ord('0'))
|
||||
inc(i)
|
||||
of 'a'..'f':
|
||||
result = result shl 4 or (ord(s[i]) - ord('a') + 10)
|
||||
inc(i)
|
||||
of 'A'..'F':
|
||||
result = result shl 4 or (ord(s[i]) - ord('A') + 10)
|
||||
inc(i)
|
||||
else: raise newException(ValueError, "invalid integer: " & s)
|
||||
let L = parseutils.parseHex(s, result, 0)
|
||||
if L != s.len or L == 0:
|
||||
raise newException(ValueError, "invalid hex integer: " & s)
|
||||
|
||||
proc generateHexCharToValueMap(): string =
|
||||
## Generate a string to map a hex digit to uint value
|
||||
@@ -1616,23 +1625,6 @@ proc delete*(s: var string, first, last: int) {.noSideEffect,
|
||||
inc(j)
|
||||
setLen(s, newLen)
|
||||
|
||||
proc parseOctInt*(s: string): int {.noSideEffect,
|
||||
rtl, extern: "nsuParseOctInt".} =
|
||||
## Parses an octal integer value contained in `s`.
|
||||
##
|
||||
## If `s` is not a valid integer, `ValueError` is raised. `s` can have one
|
||||
## of the following optional prefixes: ``0o``, ``0O``. Underscores within
|
||||
## `s` are ignored.
|
||||
var i = 0
|
||||
if i+1 < s.len and s[i] == '0' and (s[i+1] == 'o' or s[i+1] == 'O'): inc(i, 2)
|
||||
while i < s.len:
|
||||
case s[i]
|
||||
of '_': inc(i)
|
||||
of '0'..'7':
|
||||
result = result shl 3 or (ord(s[i]) - ord('0'))
|
||||
inc(i)
|
||||
else: raise newException(ValueError, "invalid integer: " & s)
|
||||
|
||||
proc toOct*(x: BiggestInt, len: Positive): string {.noSideEffect,
|
||||
rtl, extern: "nsuToOct".} =
|
||||
## Converts `x` into its octal representation.
|
||||
|
||||
Reference in New Issue
Block a user