summary refs log tree commit diff stats
path: root/rod/llstream.nim
diff options
context:
space:
mode:
Diffstat (limited to 'rod/llstream.nim')
-rwxr-xr-xrod/llstream.nim195
1 files changed, 195 insertions, 0 deletions
diff --git a/rod/llstream.nim b/rod/llstream.nim
new file mode 100755
index 000000000..6fcd278a0
--- /dev/null
+++ b/rod/llstream.nim
@@ -0,0 +1,195 @@
+#
+#
+#           The Nimrod Compiler
+#        (c) Copyright 2009 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+# Low-level streams for high performance.
+
+import 
+  strutils
+
+type 
+  TLLStreamKind* = enum       # stream encapsulates stdin
+    llsNone,                  # null stream: reading and writing has no effect
+    llsString,                # stream encapsulates a string
+    llsFile,                  # stream encapsulates a file
+    llsStdIn
+  TLLStream* = object of TObject
+    kind*: TLLStreamKind      # accessible for low-level access (lexbase uses this)
+    f*: tfile
+    s*: string
+    rd*, wr*: int             # for string streams
+  
+  PLLStream* = ref TLLStream
+
+proc LLStreamOpen*(data: string): PLLStream
+proc LLStreamOpen*(f: var tfile): PLLStream
+proc LLStreamOpen*(filename: string, mode: TFileMode): PLLStream
+proc LLStreamOpen*(): PLLStream
+proc LLStreamOpenStdIn*(): PLLStream
+proc LLStreamClose*(s: PLLStream)
+proc LLStreamRead*(s: PLLStream, buf: pointer, bufLen: int): int
+proc LLStreamReadLine*(s: PLLStream): string
+proc LLStreamReadAll*(s: PLLStream): string
+proc LLStreamWrite*(s: PLLStream, data: string)
+proc LLStreamWrite*(s: PLLStream, data: Char)
+proc LLStreamWrite*(s: PLLStream, buf: pointer, buflen: int)
+proc LLStreamWriteln*(s: PLLStream, data: string)
+proc LLStreamAtEnd*(s: PLLStream): bool
+# implementation
+
+proc LLStreamOpen(data: string): PLLStream = 
+  new(result)
+  result.s = data
+  result.kind = llsString
+
+proc LLStreamOpen(f: var tfile): PLLStream = 
+  new(result)
+  result.f = f
+  result.kind = llsFile
+
+proc LLStreamOpen(filename: string, mode: TFileMode): PLLStream = 
+  new(result)
+  result.kind = llsFile
+  if not open(result.f, filename, mode): result = nil
+  
+proc LLStreamOpen(): PLLStream = 
+  new(result)
+  result.kind = llsNone
+
+proc LLStreamOpenStdIn(): PLLStream = 
+  new(result)
+  result.kind = llsStdIn
+  result.s = ""
+
+proc LLStreamClose(s: PLLStream) = 
+  case s.kind
+  of llsNone, llsString, llsStdIn: 
+    nil
+  of llsFile: 
+    close(s.f)
+  
+proc LLreadFromStdin(s: PLLStream, buf: pointer, bufLen: int): int = 
+  var 
+    line: string
+    L: int
+  s.s = ""
+  s.rd = 0
+  while true: 
+    write(stdout, "Nimrod> ")
+    line = readLine(stdin)
+    L = len(line)
+    add(s.s, line)
+    add(s.s, "\n")
+    if (L > 0) and (line[L - 1 + 0] == '#'): break 
+  result = min(bufLen, len(s.s) - s.rd)
+  if result > 0: 
+    copyMem(buf, addr(s.s[0 + s.rd]), result)
+    inc(s.rd, result)
+
+proc LLStreamRead(s: PLLStream, buf: pointer, bufLen: int): int = 
+  case s.kind
+  of llsNone: 
+    result = 0
+  of llsString: 
+    result = min(bufLen, len(s.s) - s.rd)
+    if result > 0: 
+      copyMem(buf, addr(s.s[0 + s.rd]), result)
+      inc(s.rd, result)
+  of llsFile: 
+    result = readBuffer(s.f, buf, bufLen)
+  of llsStdIn: 
+    result = LLreadFromStdin(s, buf, bufLen)
+  
+proc LLStreamReadLine(s: PLLStream): string = 
+  case s.kind
+  of llsNone: 
+    result = ""
+  of llsString: 
+    result = ""
+    while s.rd < len(s.s): 
+      case s.s[s.rd + 0]
+      of '\x0D': 
+        inc(s.rd)
+        if s.s[s.rd + 0] == '\x0A': inc(s.rd)
+        break 
+      of '\x0A': 
+        inc(s.rd)
+        break 
+      else: 
+        add(result, s.s[s.rd + 0])
+        inc(s.rd)
+  of llsFile: 
+    result = readLine(s.f)
+  of llsStdIn: 
+    result = readLine(stdin)
+  
+proc LLStreamAtEnd(s: PLLStream): bool = 
+  case s.kind
+  of llsNone: result = true
+  of llsString: result = s.rd >= len(s.s)
+  of llsFile: result = endOfFile(s.f)
+  of llsStdIn: result = false
+  
+proc LLStreamWrite(s: PLLStream, data: string) = 
+  case s.kind
+  of llsNone, llsStdIn: 
+    nil
+  of llsString: 
+    add(s.s, data)
+    inc(s.wr, len(data))
+  of llsFile: 
+    write(s.f, data)
+  
+proc LLStreamWriteln(s: PLLStream, data: string) = 
+  LLStreamWrite(s, data)
+  LLStreamWrite(s, "\n")
+
+proc LLStreamWrite(s: PLLStream, data: Char) = 
+  var c: char
+  case s.kind
+  of llsNone, llsStdIn: 
+    nil
+  of llsString: 
+    add(s.s, data)
+    inc(s.wr)
+  of llsFile: 
+    c = data
+    discard writeBuffer(s.f, addr(c), sizeof(c))
+
+proc LLStreamWrite(s: PLLStream, buf: pointer, buflen: int) = 
+  case s.kind
+  of llsNone, llsStdIn: 
+    nil
+  of llsString: 
+    if bufLen > 0: 
+      setlen(s.s, len(s.s) + bufLen)
+      copyMem(addr(s.s[0 + s.wr]), buf, bufLen)
+      inc(s.wr, bufLen)
+  of llsFile: 
+    discard writeBuffer(s.f, buf, bufLen)
+  
+proc LLStreamReadAll(s: PLLStream): string = 
+  const 
+    bufSize = 2048
+  var bytes, i: int
+  case s.kind
+  of llsNone, llsStdIn: 
+    result = ""
+  of llsString: 
+    if s.rd == 0: result = s.s
+    else: result = copy(s.s, s.rd + 0)
+    s.rd = len(s.s)
+  of llsFile: 
+    result = newString(bufSize)
+    bytes = readBuffer(s.f, addr(result[0]), bufSize)
+    i = bytes
+    while bytes == bufSize: 
+      setlen(result, i + bufSize)
+      bytes = readBuffer(s.f, addr(result[i + 0]), bufSize)
+      inc(i, bytes)
+    setlen(result, i)