summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorxyz <xyz@queeq.com>2015-08-22 10:59:20 -0400
committerxyz <xyz@queeq.com>2015-08-22 10:59:20 -0400
commitdc6c0559e962a0df40be2258bf920827dbe9e304 (patch)
tree37d614d2e52ef2c7b50d6ce83b8cb175c04856c4
parentdd2a0ec431c17f165c18b976d01195b93b69b5e8 (diff)
downloadNim-dc6c0559e962a0df40be2258bf920827dbe9e304.tar.gz
When reading files, check if the eof flag is set before throwing.
-rw-r--r--lib/system.nim5
-rw-r--r--lib/system/sysio.nim23
2 files changed, 23 insertions, 5 deletions
diff --git a/lib/system.nim b/lib/system.nim
index 2a3f72f3b..ee94f85d2 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -2594,7 +2594,10 @@ when not defined(JS): #and not defined(nimscript):
       ## Closes the file.
 
     proc endOfFile*(f: File): bool {.tags: [], benign.}
-      ## Returns true iff `f` is at the end.
+      ## Returns true if `f` is at the end.
+
+    proc fileError*(f: File): bool {.tags: [], benign.}
+      ## Returns true if the error indicator of `f` is set.
 
     proc readChar*(f: File): char {.
       importc: "fgetc", header: "<stdio.h>", tags: [ReadIOEffect].}
diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim
index 58ad8ace0..7918569e1 100644
--- a/lib/system/sysio.nim
+++ b/lib/system/sysio.nim
@@ -37,6 +37,8 @@ proc fread(buf: pointer, size, n: int, f: File): int {.
 proc fseek(f: File, offset: clong, whence: int): int {.
   importc: "fseek", header: "<stdio.h>", tags: [].}
 proc ftell(f: File): int {.importc: "ftell", header: "<stdio.h>", tags: [].}
+proc ferror(f: File): int {.importc: "ferror", header: "<stdio.h>", tags: [].}
+proc feof(f: File): int {.importc: "feof", header: "<stdio.h>", tags: [].}
 proc setvbuf(stream: File, buf: pointer, typ, size: cint): cint {.
   importc, header: "<stdio.h>", tags: [].}
 proc memchr(s: pointer, c: cint, n: csize): pointer {.
@@ -147,9 +149,17 @@ proc rawFileSize(file: File): int =
 proc readAllFile(file: File, len: int): string =
   # We acquire the filesize beforehand and hope it doesn't change.
   # Speeds things up.
-  result = newString(int(len))
-  if readBuffer(file, addr(result[0]), int(len)) != len:
+  result = newString(len)
+  let bytes = readBuffer(file, addr(result[0]), len)
+  if endOfFile(file):
+    if bytes < len:
+      result = substr(result, 0 , bytes - 1)
+  elif fileError(file):
     raiseEIO("error while reading from file")
+  else:
+    # We red all the bytes but did not reach the EOF
+    # Try to read it as a buffer
+    result = readAllBuffer(file)
 
 proc readAllFile(file: File): string =
   var len = rawFileSize(file)
@@ -187,12 +197,17 @@ proc endOfFile(f: File): bool =
   ungetc(c, f)
   return c < 0'i32
 
+proc fileError(f: File): bool =
+  result = (ferror(f) != 0)
+
 proc writeLn[Ty](f: File, x: varargs[Ty, `$`]) =
-  for i in items(x): write(f, i)
+  for i in items(x):
+    write(f, i)
   write(f, "\n")
 
 proc writeLine[Ty](f: File, x: varargs[Ty, `$`]) =
-  for i in items(x): write(f, i)
+  for i in items(x):
+    write(f, i)
   write(f, "\n")
 
 when declared(stdout):