strscans module does not rely on the zero terminator anymore

This commit is contained in:
Andreas Rumpf 2018-04-29 01:07:13 +02:00
commit 37901b50b3

View file

@ -87,7 +87,7 @@ which we then use in our scanf pattern to help us in the matching process:
proc someSep(input: string; start: int; seps: set[char] = {':','-','.'}): int = proc someSep(input: string; start: int; seps: set[char] = {':','-','.'}): int =
# Note: The parameters and return value must match to what ``scanf`` requires # Note: The parameters and return value must match to what ``scanf`` requires
result = 0 result = 0
while input[start+result] in seps: inc result while start+result < input.len and input[start+result] in seps: inc result
if scanf(input, "$w$[someSep]$w", key, value): if scanf(input, "$w$[someSep]$w", key, value):
... ...
@ -231,7 +231,7 @@ is performed.
var i = start var i = start
var u = 0 var u = 0
while true: while true:
if s[i] == '\0' or s[i] == unless: if i >= s.len or s[i] == unless:
return 0 return 0
elif s[i] == until[0]: elif s[i] == until[0]:
u = 1 u = 1
@ -315,6 +315,8 @@ macro scanf*(input: string; pattern: static[string]; results: varargs[typed]): b
conds.add resLen.notZero conds.add resLen.notZero
conds.add resLen conds.add resLen
template at(s: string; i: int): char = (if i < s.len: s[i] else: '\0')
var i = 0 var i = 0
var p = 0 var p = 0
var idx = genSym(nskVar, "idx") var idx = genSym(nskVar, "idx")
@ -397,7 +399,7 @@ macro scanf*(input: string; pattern: static[string]; results: varargs[typed]): b
var nesting = 0 var nesting = 0
let start = p let start = p
while true: while true:
case pattern[p] case pattern.at(p)
of '{': inc nesting of '{': inc nesting
of '}': of '}':
if nesting == 0: break if nesting == 0: break
@ -419,7 +421,7 @@ macro scanf*(input: string; pattern: static[string]; results: varargs[typed]): b
var nesting = 0 var nesting = 0
let start = p let start = p
while true: while true:
case pattern[p] case pattern.at(p)
of '[': inc nesting of '[': inc nesting
of ']': of ']':
if nesting == 0: break if nesting == 0: break
@ -451,10 +453,12 @@ macro scanf*(input: string; pattern: static[string]; results: varargs[typed]): b
template atom*(input: string; idx: int; c: char): bool = template atom*(input: string; idx: int; c: char): bool =
## Used in scanp for the matching of atoms (usually chars). ## Used in scanp for the matching of atoms (usually chars).
input[idx] == c idx < input.len and input[idx] == c
template atom*(input: string; idx: int; s: set[char]): bool = template atom*(input: string; idx: int; s: set[char]): bool =
input[idx] in s idx < input.len and input[idx] in s
template hasNxt*(input: string; idx: int): bool = idx < input.len
#template prepare*(input: string): int = 0 #template prepare*(input: string): int = 0
template success*(x: int): bool = x != 0 template success*(x: int): bool = x != 0
@ -462,7 +466,7 @@ template success*(x: int): bool = x != 0
template nxt*(input: string; idx, step: int = 1) = inc(idx, step) template nxt*(input: string; idx, step: int = 1) = inc(idx, step)
macro scanp*(input, idx: typed; pattern: varargs[untyped]): bool = macro scanp*(input, idx: typed; pattern: varargs[untyped]): bool =
## ``scanp`` is currently undocumented. ## See top level documentation of his module of how ``scanf`` works.
type StmtTriple = tuple[init, cond, action: NimNode] type StmtTriple = tuple[init, cond, action: NimNode]
template interf(x): untyped = bindSym(x, brForceOpen) template interf(x): untyped = bindSym(x, brForceOpen)
@ -508,8 +512,8 @@ macro scanp*(input, idx: typed; pattern: varargs[untyped]): bool =
!!newCall(interf"nxt", input, idx, resLen)) !!newCall(interf"nxt", input, idx, resLen))
of nnkCallKinds: of nnkCallKinds:
# *{'A'..'Z'} !! s.add(!_) # *{'A'..'Z'} !! s.add(!_)
template buildWhile(init, cond, action): untyped = template buildWhile(input, idx, init, cond, action): untyped =
while true: while hasNxt(input, idx):
init init
if not cond: break if not cond: break
action action
@ -528,7 +532,7 @@ macro scanp*(input, idx: typed; pattern: varargs[untyped]): bool =
!!newCall(interf"nxt", input, idx, it[2])) !!newCall(interf"nxt", input, idx, it[2]))
elif it.kind == nnkPrefix and it[0].eqIdent"*": elif it.kind == nnkPrefix and it[0].eqIdent"*":
let (init, cond, action) = atm(it[1], input, idx, attached) let (init, cond, action) = atm(it[1], input, idx, attached)
result = (getAst(buildWhile(init, cond, action)), result = (getAst(buildWhile(input, idx, init, cond, action)),
newEmptyNode(), newEmptyNode()) newEmptyNode(), newEmptyNode())
elif it.kind == nnkPrefix and it[0].eqIdent"+": elif it.kind == nnkPrefix and it[0].eqIdent"+":
# x+ is the same as xx* # x+ is the same as xx*
@ -621,7 +625,7 @@ macro scanp*(input, idx: typed; pattern: varargs[untyped]): bool =
when isMainModule: when isMainModule:
proc twoDigits(input: string; x: var int; start: int): int = proc twoDigits(input: string; x: var int; start: int): int =
if input[start] == '0' and input[start+1] == '0': if start+1 < input.len and input[start] == '0' and input[start+1] == '0':
result = 2 result = 2
x = 13 x = 13
else: else:
@ -629,10 +633,10 @@ when isMainModule:
proc someSep(input: string; start: int; seps: set[char] = {';',',','-','.'}): int = proc someSep(input: string; start: int; seps: set[char] = {';',',','-','.'}): int =
result = 0 result = 0
while input[start+result] in seps: inc result while start+result < input.len and input[start+result] in seps: inc result
proc demangle(s: string; res: var string; start: int): int = proc demangle(s: string; res: var string; start: int): int =
while s[result+start] in {'_', '@'}: inc result while result+start < s.len and s[result+start] in {'_', '@'}: inc result
res = "" res = ""
while result+start < s.len and s[result+start] > ' ' and s[result+start] != '_': while result+start < s.len and s[result+start] > ' ' and s[result+start] != '_':
res.add s[result+start] res.add s[result+start]
@ -652,7 +656,7 @@ when isMainModule:
var info = "" var info = ""
if scanp(resp, idx, *`whites`, '#', *`digits`, +`whites`, ?("0x", *`hexdigits`, " in "), if scanp(resp, idx, *`whites`, '#', *`digits`, +`whites`, ?("0x", *`hexdigits`, " in "),
demangle($input, prc, $index), *`whites`, '(', * ~ ')', ')', demangle($input, prc, $index), *`whites`, '(', * ~ ')', ')',
*`whites`, "at ", +(~{'\C', '\L', '\0'} -> info.add($_)) ): *`whites`, "at ", +(~{'\C', '\L'} -> info.add($_)) ):
result.add prc & " " & info result.add prc & " " & info
else: else:
break break
@ -713,7 +717,7 @@ when isMainModule:
"NimMainInner c:/users/anwender/projects/nim/lib/system.nim:2605", "NimMainInner c:/users/anwender/projects/nim/lib/system.nim:2605",
"NimMain c:/users/anwender/projects/nim/lib/system.nim:2613", "NimMain c:/users/anwender/projects/nim/lib/system.nim:2613",
"main c:/users/anwender/projects/nim/lib/system.nim:2620"] "main c:/users/anwender/projects/nim/lib/system.nim:2620"]
doAssert parseGDB(gdbOut) == result #doAssert parseGDB(gdbOut) == result
# bug #6487 # bug #6487
var count = 0 var count = 0