diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2020-03-09 15:32:38 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-09 15:32:38 +0100 |
commit | 63af8ae53ca8e1ffd61a2c2d55d09c5fe30310e1 (patch) | |
tree | 64f73cf00505159f9720aa6113e07ad1dcdf6857 /tests/arc | |
parent | 4aecc6b3465411d99dbd94e89c1bb3eb371d6fa6 (diff) | |
download | Nim-63af8ae53ca8e1ffd61a2c2d55d09c5fe30310e1.tar.gz |
fixes #13596 (#13612)
Diffstat (limited to 'tests/arc')
-rw-r--r-- | tests/arc/tamemfiles.nim | 110 | ||||
-rw-r--r-- | tests/arc/testfile.txt | 2 |
2 files changed, 112 insertions, 0 deletions
diff --git a/tests/arc/tamemfiles.nim b/tests/arc/tamemfiles.nim new file mode 100644 index 000000000..97deb489f --- /dev/null +++ b/tests/arc/tamemfiles.nim @@ -0,0 +1,110 @@ +discard """ + output: ''' +loop 1a +loop 1b; cols: @[1, x] +loop 1c +loop 1d +loop 1a +loop 1b; cols: @[2, y] +loop 1c +loop 1d +''' + cmd: "nim c --gc:arc $file" +""" + +# bug #13596 + +import tables, memfiles, strutils, os + +type Splitr* = tuple[ repeat: bool, chrDlm: char, setDlm: set[char], n: int ] + +type csize = uint +proc cmemchr*(s: pointer, c: char, n: csize): pointer {. + importc: "memchr", header: "<string.h>" .} +proc `-!`*(p, q: pointer): int {.inline.} = + (cast[int](p) -% cast[int](q)).int +proc `+!`*(p: pointer, i: int): pointer {.inline.} = + cast[pointer](cast[int](p) +% i) +proc `+!`*(p: pointer, i: uint64): pointer {.inline.} = + cast[pointer](cast[uint64](p) + i) + +proc charEq(x, c: char): bool {.inline.} = x == c + +proc initSplitr*(delim: string): Splitr = + if delim == "white": #User can use any other permutation if needed + result.repeat = true + result.chrDlm = ' ' + result.setDlm = { ' ', '\t', '\n' } + result.n = result.setDlm.card + return + for c in delim: + if c in result.setDlm: + result.repeat = true + continue + result.setDlm.incl(c) + inc(result.n) + if result.n == 1: #support n==1 test to allow memchr optimization + result.chrDlm = delim[0] + +proc hash(x: MemSlice): int = 55542 + +template defSplit[T](slc: T, fs: var seq[MemSlice], n: int, repeat: bool, + sep: untyped, nextSep: untyped, isSep: untyped) {.dirty.} = + fs.setLen(if n < 1: 16 else: n) + var b = slc.data + var eob = b +! slc.size + while repeat and eob -! b > 0 and isSep((cast[cstring](b))[0], sep): + b = b +! 1 + if b == eob: fs.setLen(0); return + var e = nextSep(b, sep, (eob -! b).csize) + while e != nil: + if n < 1: #Unbounded msplit + if result == fs.len - 1: #Expand capacity + fs.setLen(if fs.len < 512: 2*fs.len else: fs.len + 512) + elif result == n - 1: #Need 1 more slot for final field + break + fs[result].data = b + fs[result].size = e -! b + result += 1 + while repeat and eob -! e > 0 and isSep((cast[cstring](e))[1], sep): + e = e +! 1 + b = e +! 1 + if eob -! b <= 0: + b = eob + break + e = nextSep(b, sep, (eob -! b).csize) + if not repeat or eob -! b > 0: + fs[result].data = b + fs[result].size = eob -! b + result += 1 + fs.setLen(result) + +proc msplit*(s: MemSlice, fs: var seq[MemSlice], sep=' ', n=0, + repeat=false): int = + defSplit(s, fs, n, repeat, sep, cmemchr, charEq) + +proc split*(s: Splitr, line: MemSlice, cols: var seq[MemSlice], + n=0) {.inline.} = + discard msplit(line, cols, s.chrDlm, n, s.repeat) + +######################################################################## +# Using lines instead of memSlices & split instead of splitr.split seems +# to mask the arc problem, as does simplifying `Table` to `seq[char]`. + +proc load(path: string, delim=" "): Table[MemSlice, seq[char]] = + let f = memfiles.open(path) + let splitr = initSplitr(delim) + var cols: seq[MemSlice] = @[ ] # re-used seq buffer + var nwSq = newSeqOfCap[char](1) # re-used seq value + nwSq.setLen 1 + for line in memSlices(f, eat='\0'): + stderr.write "loop 1a\n" + splitr.split(line, cols, 2) + stderr.write "loop 1b; cols: ", cols, "\n" + let cs = cast[cstring](cols[0].data) + stderr.write "loop 1c\n" #..reports exception here, but + nwSq[0] = cs[0] #..actually doing out of bounds here + stderr.write "loop 1d\n" + result[cols[1]] = nwSq + +discard load(getAppDir() / "testfile.txt") diff --git a/tests/arc/testfile.txt b/tests/arc/testfile.txt new file mode 100644 index 000000000..5169490be --- /dev/null +++ b/tests/arc/testfile.txt @@ -0,0 +1,2 @@ +1 x +2 y |