diff options
author | Simon Hafner <hafnersimon@gmail.com> | 2011-11-03 17:05:32 +0100 |
---|---|---|
committer | Simon Hafner <hafnersimon@gmail.com> | 2011-12-22 17:17:06 +0100 |
commit | 5ede29cd051b818c7c2fc926c4acba86ddb76a0e (patch) | |
tree | 8e0f21121ffd9f44884e2354a63ede3313c0e05b /lib/system/sysio.nim | |
parent | 4f08946f64f04ef85a53c686fb89b8d84fbc6d65 (diff) | |
download | Nim-5ede29cd051b818c7c2fc926c4acba86ddb76a0e.tar.gz |
implemented readAll()
Diffstat (limited to 'lib/system/sysio.nim')
-rwxr-xr-x | lib/system/sysio.nim | 64 |
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.} |