summary refs log tree commit diff stats
path: root/tests/arc
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2020-03-09 15:32:38 +0100
committerGitHub <noreply@github.com>2020-03-09 15:32:38 +0100
commit63af8ae53ca8e1ffd61a2c2d55d09c5fe30310e1 (patch)
tree64f73cf00505159f9720aa6113e07ad1dcdf6857 /tests/arc
parent4aecc6b3465411d99dbd94e89c1bb3eb371d6fa6 (diff)
downloadNim-63af8ae53ca8e1ffd61a2c2d55d09c5fe30310e1.tar.gz
fixes #13596 (#13612)
Diffstat (limited to 'tests/arc')
-rw-r--r--tests/arc/tamemfiles.nim110
-rw-r--r--tests/arc/testfile.txt2
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