diff options
author | Clyybber <darkmine956@gmail.com> | 2019-09-29 22:20:00 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2019-09-29 22:20:00 +0200 |
commit | 16c39f9b2edc963655889cfd33e165bfae91c96d (patch) | |
tree | 9da74d03a757de874d9f01a8a055875643bbfbb2 | |
parent | 85db42ad8c1a19ea47bd5826d8639e8974cc9042 (diff) | |
download | Nim-16c39f9b2edc963655889cfd33e165bfae91c96d.tar.gz |
More of StringStream now works at compile time (#12284)
* readLine of StringStream now works at compile time * Work for js backend only at compile time * readAll now works at CT * readAll works in js ct now * Add test
-rw-r--r-- | lib/pure/streams.nim | 131 | ||||
-rw-r--r-- | tests/stdlib/tstreams3.nim | 11 |
2 files changed, 114 insertions, 28 deletions
diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim index 0a187cea2..61aa520d1 100644 --- a/lib/pure/streams.nim +++ b/lib/pure/streams.nim @@ -251,16 +251,29 @@ when not defined(js): strm.close() const bufferSize = 1024 - var buffer {.noinit.}: array[bufferSize, char] - while true: - let readBytes = readData(s, addr(buffer[0]), bufferSize) - if readBytes == 0: - break - let prevLen = result.len - result.setLen(prevLen + readBytes) - copyMem(addr(result[prevLen]), addr(buffer[0]), readBytes) - if readBytes < bufferSize: - break + when nimvm: + var buffer2: string + buffer2.setLen(bufferSize) + while true: + let readBytes = readDataStr(s, buffer2, 0..<bufferSize) + if readBytes == 0: + break + let prevLen = result.len + result.setLen(prevLen + readBytes) + result[prevLen..<prevLen+readBytes] = buffer2[0..<readBytes] + if readBytes < bufferSize: + break + else: + var buffer {.noinit.}: array[bufferSize, char] + while true: + let readBytes = readData(s, addr(buffer[0]), bufferSize) + if readBytes == 0: + break + let prevLen = result.len + result.setLen(prevLen + readBytes) + copyMem(addr(result[prevLen]), addr(buffer[0]), readBytes) + if readBytes < bufferSize: + break proc peekData*(s: Stream, buffer: pointer, bufLen: int): int = ## Low level proc that reads data into an untyped `buffer` of `bufLen` size @@ -399,7 +412,12 @@ proc readChar*(s: Stream): char = doAssert strm.readChar() == '\x00' strm.close() - if readData(s, addr(result), sizeof(result)) != 1: result = '\0' + when nimvm: + var str = " " + if readDataStr(s, str, 0..<sizeof(result)) != 1: result = '\0' + else: result = str[0] + else: + if readData(s, addr(result), sizeof(result)) != 1: result = '\0' proc peekChar*(s: Stream): char = ## Peeks a char from the stream `s`. Raises `IOError` if an error occurred. @@ -884,7 +902,10 @@ proc readLine*(s: Stream, line: var TaintedString): bool = result = s.readLineImpl(s, line) else: # fallback - line.string.setLen(0) + when nimvm: #Bug #12282 + line.setLen(0) + else: + line.string.setLen(0) while true: var c = readChar(s) if c == '\c': @@ -894,7 +915,10 @@ proc readLine*(s: Stream, line: var TaintedString): bool = elif c == '\0': if line.len > 0: break else: return false - line.string.add(c) + when nimvm: #Bug #12282 + line.add(c) + else: + line.string.add(c) result = true proc peekLine*(s: Stream, line: var TaintedString): bool = @@ -999,21 +1023,73 @@ iterator lines*(s: Stream): TaintedString = while s.readLine(line): yield line -when not defined(js): +type + StringStream* = ref StringStreamObj + ## A stream that encapsulates a string. + ## + ## **Note:** Not available for JS backend. + StringStreamObj* = object of StreamObj + ## A string stream object. + ## + ## **Note:** Not available for JS backend. + data*: string ## A string data. + ## This is updated when called `writeLine` etc. + pos: int - type - StringStream* = ref StringStreamObj - ## A stream that encapsulates a string. - ## - ## **Note:** Not available for JS backend. - StringStreamObj* = object of StreamObj - ## A string stream object. - ## - ## **Note:** Not available for JS backend. - data*: string ## A string data. - ## This is updated when called `writeLine` etc. - pos: int +when defined(js): #This section exists so that string streams work at compile time for the js backend + proc ssAtEnd(s: Stream): bool {.compileTime.} = + var s = StringStream(s) + return s.pos >= s.data.len + + proc ssSetPosition(s: Stream, pos: int) {.compileTime.} = + var s = StringStream(s) + s.pos = clamp(pos, 0, s.data.len) + + proc ssGetPosition(s: Stream): int {.compileTime.} = + var s = StringStream(s) + return s.pos + + proc ssReadDataStr(s: Stream, buffer: var string, slice: Slice[int]): int {.compileTime.} = + var s = StringStream(s) + result = min(slice.b + 1 - slice.a, s.data.len - s.pos) + if result > 0: + buffer[slice.a..<slice.a+result] = s.data[s.pos..<s.pos+result] + inc(s.pos, result) + else: + result = 0 + + proc ssClose(s: Stream) {.compileTime.} = + var s = StringStream(s) + when defined(nimNoNilSeqs): + s.data = "" + else: + s.data = nil + + proc newStringStream*(s: string = ""): owned StringStream {.compileTime.} = + new(result) + result.data = s + result.pos = 0 + result.closeImpl = ssClose + result.atEndImpl = ssAtEnd + result.setPositionImpl = ssSetPosition + result.getPositionImpl = ssGetPosition + result.readDataStrImpl = ssReadDataStr + + proc readAll*(s: Stream): string {.compileTime.} = + const bufferSize = 1024 + var bufferr: string + bufferr.setLen(bufferSize) + while true: + let readBytes = readDataStr(s, bufferr, 0..<bufferSize) + if readBytes == 0: + break + let prevLen = result.len + result.setLen(prevLen + readBytes) + result[prevLen..<prevLen+readBytes] = bufferr[0..<readBytes] + if readBytes < bufferSize: + break +else: proc ssAtEnd(s: Stream): bool = var s = StringStream(s) return s.pos >= s.data.len @@ -1031,8 +1107,7 @@ when not defined(js): result = min(slice.b + 1 - slice.a, s.data.len - s.pos) if result > 0: when nimvm: - for i in 0 ..< result: # sorry, but no fast string splicing on the vm. - buffer[slice.a + i] = s.data[s.pos + i] + buffer[slice.a..<slice.a+result] = s.data[s.pos..<s.pos+result] else: copyMem(unsafeAddr buffer[slice.a], addr s.data[s.pos], result) inc(s.pos, result) diff --git a/tests/stdlib/tstreams3.nim b/tests/stdlib/tstreams3.nim index e3b395e05..89f45f275 100644 --- a/tests/stdlib/tstreams3.nim +++ b/tests/stdlib/tstreams3.nim @@ -1,5 +1,10 @@ discard """ output: "threw exception" + nimout: ''' +I +AM +GROOT +''' """ import streams @@ -7,3 +12,9 @@ try: var fs = openFileStream("shouldneverexist.txt") except IoError: echo "threw exception" + +static: + var s = newStringStream("I\nAM\nGROOT") + for line in s.lines: + echo line + s.close |