some refactoring, better error reporting in File:tell

This commit is contained in:
Grump
2020-05-28 14:57:37 +02:00
parent 81c8d8d3bf
commit ebf98b4494
2 changed files with 18 additions and 10 deletions

View File

@@ -11,6 +11,7 @@ local File = {
local fopen, getcwd, chdir, unlink, mkdir, rmdir local fopen, getcwd, chdir, unlink, mkdir, rmdir
local BUFFERMODE, MODEMAP local BUFFERMODE, MODEMAP
local ByteArray = ffi.typeof('unsigned char[?]')
function File:open(mode) function File:open(mode)
if self._mode ~= 'c' then return false, "File " .. self._name .. " is already open" end if self._mode ~= 'c' then return false, "File " .. self._name .. " is already open" end
@@ -106,27 +107,31 @@ function File:lines()
if self._mode ~= 'r' then error("File is not opened for reading") end if self._mode ~= 'r' then error("File is not opened for reading") end
local BUFFERSIZE = 4096 local BUFFERSIZE = 4096
local buffer = ffi.new('unsigned char[?]', BUFFERSIZE) local buffer = ByteArray(BUFFERSIZE)
local bytesRead = tonumber(C.fread(buffer, 1, BUFFERSIZE, self._handle)) local bytesRead = tonumber(C.fread(buffer, 1, BUFFERSIZE, self._handle))
local bufferPos = 0 local bufferPos = 0
local offset = self:tell() local offset = self:tell()
return function() return function()
self:seek(offset)
local line = {} local line = {}
self:seek(offset)
while bytesRead > 0 do while bytesRead > 0 do
for i = bufferPos, bytesRead - 1 do for i = bufferPos, bytesRead - 1 do
if buffer[i] ~= 10 and buffer[i] ~= 13 then if buffer[i] == 10 then -- end of line
table.insert(line, string.char(buffer[i]))
elseif buffer[i] == 10 then
bufferPos = i + 1 bufferPos = i + 1
return table.concat(line) return table.concat(line)
end end
if buffer[i] ~= 13 then -- ignore CR
table.insert(line, string.char(buffer[i]))
end
end end
bytesRead = tonumber(C.fread(buffer, 1, BUFFERSIZE, self._handle)) bytesRead = tonumber(C.fread(buffer, 1, BUFFERSIZE, self._handle))
offset, bufferPos = offset + bytesRead, 0 offset, bufferPos = offset + bytesRead, 0
end end
return line[1] and table.concat(line) or nil return line[1] and table.concat(line) or nil
end end
end end
@@ -135,6 +140,7 @@ function File:write(data, size)
if self._mode ~= 'w' and self._mode ~= 'a' then if self._mode ~= 'w' and self._mode ~= 'a' then
return false, "File " .. self._name .. " not opened for writing" return false, "File " .. self._name .. " not opened for writing"
end end
local toWrite, writeSize local toWrite, writeSize
if type(data) == 'string' then if type(data) == 'string' then
writeSize = (size == nil or size == 'all') and #data or size writeSize = (size == nil or size == 'all') and #data or size
@@ -143,6 +149,7 @@ function File:write(data, size)
writeSize = (size == nil or size == 'all') and data:getSize() or size writeSize = (size == nil or size == 'all') and data:getSize() or size
toWrite = data:getFFIPointer() toWrite = data:getFFIPointer()
end end
if tonumber(C.fwrite(toWrite, 1, writeSize, self._handle)) ~= writeSize then if tonumber(C.fwrite(toWrite, 1, writeSize, self._handle)) ~= writeSize then
return false, "Could not write data" return false, "Could not write data"
end end
@@ -150,13 +157,12 @@ function File:write(data, size)
end end
function File:seek(pos) function File:seek(pos)
if self._handle == nil then return false end return self._handle and C.fseek(self._handle, pos, 0) == 0
return C.fseek(self._handle, pos, 0) == 0
end end
function File:tell() function File:tell()
if self._handle == nil then return -1 end if self._handle == nil then return nil, "Invalid position" end
return tonumber(C.ftell(self._handle)) return self._handle and tonumber(C.ftell(self._handle)) or -1
end end
function File:flush() function File:flush()
@@ -417,7 +423,7 @@ else
]]) ]])
local MAX_PATH = 4096 local MAX_PATH = 4096
local nameBuffer = ffi.new('char[?]', MAX_PATH) local nameBuffer = ByteArray(MAX_PATH)
fopen = C.fopen fopen = C.fopen
unlink = function(path) return ffi.C.unlink(path) == 0 end unlink = function(path) return ffi.C.unlink(path) == 0 end

View File

@@ -334,6 +334,8 @@ end
function test_File_tell() function test_File_tell()
local f = fs.newFile(testFile1) local f = fs.newFile(testFile1)
local ok, err = f:tell()
equals(ok, nil)
f:open('r') f:open('r')
f:read(172) f:read(172)
equals(f:tell(), 172) equals(f:tell(), 172)