summary refs log tree commit diff stats
path: root/lib/system/sysio.nim
diff options
context:
space:
mode:
authorSimon Hafner <hafnersimon@gmail.com>2011-11-03 17:05:32 +0100
committerSimon Hafner <hafnersimon@gmail.com>2011-12-22 17:17:06 +0100
commit5ede29cd051b818c7c2fc926c4acba86ddb76a0e (patch)
tree8e0f21121ffd9f44884e2354a63ede3313c0e05b /lib/system/sysio.nim
parent4f08946f64f04ef85a53c686fb89b8d84fbc6d65 (diff)
downloadNim-5ede29cd051b818c7c2fc926c4acba86ddb76a0e.tar.gz
implemented readAll()
Diffstat (limited to 'lib/system/sysio.nim')
-rwxr-xr-xlib/system/sysio.nim64
1 files changed, 45 insertions, 19 deletions
diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim
index 890f526ea..6641d7218 100755
--- a/lib/system/sysio.nim
+++ b/lib/system/sysio.nim
@@ -24,6 +24,13 @@ proc putc(c: Char, stream: TFile) {.importc: "putc", nodecl.}
 proc fprintf(f: TFile, frmt: CString) {.importc: "fprintf", nodecl, varargs.}
 proc strlen(c: cstring): int {.importc: "strlen", nodecl.}
 
+
+# C routine that is used here:
+proc fread(buf: Pointer, size, n: int, f: TFile): int {.
+  importc: "fread", noDecl.}
+proc fseek(f: TFile, offset: clong, whence: int): int {.
+  importc: "fseek", noDecl.}
+proc ftell(f: TFile): int {.importc: "ftell", noDecl.}
 proc setvbuf(stream: TFile, buf: pointer, typ, size: cint): cint {.
   importc, nodecl.}
 
@@ -36,6 +43,9 @@ var
   IOFBF {.importc: "_IOFBF", nodecl.}: cint
   IONBF {.importc: "_IONBF", nodecl.}: cint
 
+const
+  BUF_SIZE = 4000
+
 proc raiseEIO(msg: string) {.noinline, noreturn.} =
   raise newException(EIO, msg)
 
@@ -82,21 +92,44 @@ proc write(f: TFile, c: Char) = putc(c, f)
 proc write(f: TFile, a: openArray[string]) =
   for x in items(a): write(f, x)
 
+proc readAllBuffer(file: TFile): string = 
+  # This proc is for TFile we want to read but don't know how many
+  # bytes we need to read before the buffer is empty.
+  result = ""
+  var buffer = newString(BUF_SIZE)
+  var bytesRead = BUF_SIZE
+  while bytesRead == BUF_SIZE:
+    bytesRead = readBuffer(file, addr(buffer[0]), BUF_SIZE)
+    result.add(buffer)
+  
+proc readAllFile(file: TFile): string =
+  # We aquire the filesize beforehand and hope it doesn't change.
+  # Speeds things up.
+  var len = getFileSize(file)
+  if len >= high(int):
+    raiseEIO("file too big to fit in memory")
+  result = newString(int(len))
+  if readBuffer(file, addr(result[0]), int(len)) != len:
+    raiseEIO("error while reading from file")
+
+proc hasDefinedLength(file: TFile): bool = 
+  var oldPos = getFilePos(file)
+  discard fseek(file, 0, 2) # seek the end of the file
+  result = ftell(file) >= 0
+  setFilePos(file, oldPos)
+
+proc readAll(file: TFile): TaintedString = 
+  # Separate handling needed because we need to buffer when we
+  # don't know the overall length of the TFile.
+  if hasDefinedLength(file):
+    result = readAllBuffer(file).TaintedSTring
+  else:
+    result = readAllFile(file).TaintedString
+  
 proc readFile(filename: string): TaintedString =
   var f = open(filename)
   try:
-    var len = getFileSize(f)
-    if len < high(int):
-      when taintMode:
-        result = newString(int(len)).TaintedString
-        if readBuffer(f, addr(string(result)[0]), int(len)) != len:
-          raiseEIO("error while reading from file")
-      else:
-        result = newString(int(len))
-        if readBuffer(f, addr(result[0]), int(len)) != len:
-          raiseEIO("error while reading from file")
-    else:
-      raiseEIO("file too big to fit in memory")
+    result = readAllFile(f)
   finally:
     close(f)
 
@@ -157,13 +190,6 @@ proc open(f: var TFile, filehandle: TFileHandle, mode: TFileMode): bool =
   f = fdopen(filehandle, FormatOpen[mode])
   result = f != nil
 
-# C routine that is used here:
-proc fread(buf: Pointer, size, n: int, f: TFile): int {.
-  importc: "fread", noDecl.}
-proc fseek(f: TFile, offset: clong, whence: int): int {.
-  importc: "fseek", noDecl.}
-proc ftell(f: TFile): int {.importc: "ftell", noDecl.}
-
 proc fwrite(buf: Pointer, size, n: int, f: TFile): int {.
   importc: "fwrite", noDecl.}