implemented readAll()
This commit is contained in:
parent
4f08946f64
commit
5ede29cd05
4 changed files with 77 additions and 22 deletions
|
|
@ -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.}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue