diff options
Diffstat (limited to 'lib')
-rwxr-xr-x | lib/system.nim | 9 | ||||
-rwxr-xr-x | lib/system/sysio.nim | 69 |
2 files changed, 56 insertions, 22 deletions
diff --git a/lib/system.nim b/lib/system.nim index f8bfe3e77..ab38fbb21 100755 --- a/lib/system.nim +++ b/lib/system.nim @@ -1677,10 +1677,13 @@ when not defined(EcmaScript) and not defined(NimrodVM): proc FlushFile*(f: TFile) {.importc: "fflush", noDecl.} ## Flushes `f`'s buffer. + proc readAll*(file: TFile): TaintedString + ## Reads all data from the stream `file`. Raises an IO exception + ## in case of an error + proc readFile*(filename: string): TaintedString - ## Opens a file named `filename` for reading. Then reads the - ## file's content completely into a string and - ## closes the file afterwards. Returns the string. + ## Opens a file named `filename` for reading. Then calls `readAll` + ## and closes the file afterwards. Returns the string. ## Raises an IO exception in case of an error. proc writeFile*(filename, content: string) diff --git a/lib/system/sysio.nim b/lib/system/sysio.nim index 890f526ea..d012110f1 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,49 @@ 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 rawFileSize(file: TFile): int = + # this does not raise an error opposed to `getFileSize` + var oldPos = ftell(file) + discard fseek(file, 0, 2) # seek the end of the file + result = ftell(file) + discard fseek(file, clong(oldPos), 0) + +proc readAllFile(file: TFile, len: int): string = + # We aquire the filesize beforehand and hope it doesn't change. + # Speeds things up. + 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 readAllFile(file: TFile): string = + var len = rawFileSize(file) + result = readAllFile(file, len) + +proc readAll(file: TFile): TaintedString = + # Separate handling needed because we need to buffer when we + # don't know the overall length of the TFile. + var len = rawFileSize(file) + if len >= 0: + result = readAllFile(file, len).TaintedSTring + else: + result = readAllBuffer(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).TaintedString finally: close(f) @@ -157,13 +195,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.} |