@markebbert, yes you are right! That should be
if data[last] == '\l':
buffer.add data[pos+1 ..< pos+bufSize]
else:
buffer.add data[pos ..< pos+bufSize]
pos += bufSize
Run
Which will account for the buffer increase. So the code now for the `lines`
iterator is (I also changed the buffer size to avoid reallocations):
iterator lines*(s: GzFileStream, cap = 100000000): TaintedString {.tags:
[ReadIOEffect].} =
## An iterator across GzFileStream that takes a buffer capacity
var
bufSize = 24576
data = TaintedString(newStringOfCap(cap))
buffer = TaintedString(newStringOfCap(bufSize))
var
pos = 0
last = 0
while not s.atEnd():
var success = readStr(s, cap, data)
if not success: break
pos = 0
last = 0
while pos < data.len:
let m = c_memchr(addr data.string[pos], '\L'.ord, bufSize)
if m != nil:
# \l found: Could be our own or the one by fgets, in any case,
we're done
last = cast[ByteAddress](m) - cast[ByteAddress](addr data.string[0])
if last > 0 or data.string[last] == '\l':
if buffer.len > 0:
yield buffer & data[pos ..< last]
buffer.setLen(0)
else:
yield data[pos ..< last]
pos = last + 1
else:
break
else:
if data[last] == '\l':
buffer.add data[pos+1 ..< pos+bufSize]
else:
buffer.add data[pos ..< pos+bufSize]
pos += bufSize
if last < data.len:
# there is still data left over and we
# need to keep it for the next iteration
if data[last] == '\l':
buffer.add data[last+1 ..< data.len]
else:
buffer.add data[last ..< data.len]
Run
I do recommend you go with one of @cblakes memslice solutions, though. They
will be much faster.