implemented readAll()

This commit is contained in:
Simon Hafner 2011-11-03 17:05:32 +01:00
commit 5ede29cd05
4 changed files with 77 additions and 22 deletions

View file

@ -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.}