diff options
author | Araq <rumpf_a@web.de> | 2011-12-31 02:21:01 -0800 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2011-12-31 02:21:01 -0800 |
commit | 61ff32933789ea5d0c327d7a5c5d7b1f4dfc8499 (patch) | |
tree | 28ff00cbc675e9e1113637bf2d952d2ace616d00 /lib/system | |
parent | 9fdfda136c4d3ec0d8e72867345b427b30e88ef4 (diff) | |
parent | cf2078aed8c0b706f2e3576914558c9530fcb832 (diff) | |
download | Nim-61ff32933789ea5d0c327d7a5c5d7b1f4dfc8499.tar.gz |
Merge pull request #79 from Tass/master
readAll
Diffstat (limited to 'lib/system')
-rwxr-xr-x | lib/system/sysio.nim | 69 |
1 files changed, 50 insertions, 19 deletions
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.} |