This commit is contained in:
Grump
2020-06-18 13:01:39 +02:00
parent 30d36b97e1
commit 3d4a838105
2 changed files with 52 additions and 36 deletions

View File

@@ -11,7 +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[?]') local ByteArray = ffi.typeof('unsigned char[?]')
local function _ptr(p) return p ~= nil and p or nil end local function _ptr(p) return p ~= nil and p or nil end -- NULL pointer to nil
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
@@ -20,11 +20,9 @@ function File:open(mode)
local handle = _ptr(fopen(self._name, MODEMAP[mode])) local handle = _ptr(fopen(self._name, MODEMAP[mode]))
if not handle then return false, "Could not open " .. self._name .. " in mode " .. mode end if not handle then return false, "Could not open " .. self._name .. " in mode " .. mode end
if C.setvbuf(handle, nil, BUFFERMODE[self._bufferMode], self._bufferSize) ~= 0 then
self._bufferMode, self._bufferSize = 'none', 0
end
self._handle, self._mode = ffi.gc(handle, C.fclose), mode self._handle, self._mode = ffi.gc(handle, C.fclose), mode
self:setBuffer(self._bufferMode, self._bufferSize)
return true return true
end end
@@ -48,12 +46,13 @@ function File:setBuffer(mode, size)
end end
local success = self._mode == 'c' or C.setvbuf(self._handle, nil, bufferMode, size) == 0 local success = self._mode == 'c' or C.setvbuf(self._handle, nil, bufferMode, size) == 0
if success then if not success then
self._bufferMode, self._bufferSize = mode, size self._bufferMode, self._bufferSize = 'none', 0
return true return false, "Could not set buffer mode"
end end
return false, "Could not set buffer mode" self._bufferMode, self._bufferSize = mode, size
return true
end end
function File:getSize() function File:getSize()
@@ -311,28 +310,25 @@ function nativefs.remove(name)
return true return true
end end
local function withTempMount(dir, fn) local function withTempMount(dir, fn, ...)
local mountPoint = _ptr(loveC.PHYSFS_getMountPoint(dir)) local mountPoint = _ptr(loveC.PHYSFS_getMountPoint(dir))
if mountPoint then return fn(ffi.string(mountPoint)) end if mountPoint then return fn(ffi.string(mountPoint), ...) end
if not nativefs.mount(dir, '__nativefs__temp__') then return false, "Could not mount " .. dir end if not nativefs.mount(dir, '__nativefs__temp__') then return false, "Could not mount " .. dir end
local a, b = fn('__nativefs__temp__') local a, b = fn('__nativefs__temp__', ...)
nativefs.unmount(dir) nativefs.unmount(dir)
return a, b return a, b
end end
function nativefs.getDirectoryItems(dir) function nativefs.getDirectoryItems(dir)
local result, err = withTempMount(dir, function(mount) local result, err = withTempMount(dir, love.filesystem.getDirectoryItems)
return love.filesystem.getDirectoryItems(mount)
end)
return result or {} return result or {}
end end
function nativefs.getDirectoryItemsInfo(path, filtertype) local function getDirectoryItemsInfo(path, filtertype)
local result, err = withTempMount(path, function(mount)
local items = {} local items = {}
local files = love.filesystem.getDirectoryItems(mount) local files = love.filesystem.getDirectoryItems(path)
for i = 1, #files do for i = 1, #files do
local filepath = string.format('%s/%s', mount, files[i]) local filepath = string.format('%s/%s', path, files[i])
local info = love.filesystem.getInfo(filepath, filtertype) local info = love.filesystem.getInfo(filepath, filtertype)
if info then if info then
info.name = files[i] info.name = files[i]
@@ -340,23 +336,29 @@ function nativefs.getDirectoryItemsInfo(path, filtertype)
end end
end end
return items return items
end) end
function nativefs.getDirectoryItemsInfo(path, filtertype)
local result, err = withTempMount(path, getDirectoryItemsInfo, filtertype)
return result or {} return result or {}
end end
local function getInfo(path, file, filtertype)
local filepath = string.format('%s/%s', path, file)
return love.filesystem.getInfo(filepath, filtertype)
end
function nativefs.getInfo(path, filtertype) function nativefs.getInfo(path, filtertype)
local dir = path:match("(.*[\\/]).*$") or './' local dir = path:match("(.*[\\/]).*$") or './'
local file = love.path.leaf(path) local file = love.path.leaf(path)
local result, err = withTempMount(dir, function(mount) local result, err = withTempMount(dir, getInfo, file, filtertype)
local filepath = string.format('%s/%s', mount, file)
return love.filesystem.getInfo(filepath, filtertype)
end)
return result or nil return result or nil
end end
----------------------------------------------------------------------------- -----------------------------------------------------------------------------
MODEMAP = { r = 'rb', w = 'wb', a = 'ab' } MODEMAP = { r = 'rb', w = 'wb', a = 'ab' }
local MAX_PATH = 4096
ffi.cdef([[ ffi.cdef([[
int PHYSFS_mount(const char* dir, const char* mountPoint, int appendToPath); int PHYSFS_mount(const char* dir, const char* mountPoint, int appendToPath);
@@ -406,7 +408,6 @@ if ffi.os == 'Windows' then
return ffi.string(buf) return ffi.string(buf)
end end
local MAX_PATH = 260
local nameBuffer = ffi.new('wchar_t[?]', MAX_PATH + 1) local nameBuffer = ffi.new('wchar_t[?]', MAX_PATH + 1)
fopen = function(path, mode) return C._wfopen(towidestring(path), towidestring(mode)) end fopen = function(path, mode) return C._wfopen(towidestring(path), towidestring(mode)) end
@@ -426,7 +427,6 @@ else
int rmdir(const char* path); int rmdir(const char* path);
]]) ]])
local MAX_PATH = 4096
local nameBuffer = ByteArray(MAX_PATH) local nameBuffer = ByteArray(MAX_PATH)
fopen = C.fopen fopen = C.fopen

View File

@@ -137,14 +137,24 @@ function test_fs_getDirectoryItems()
for i = 1, #items2 do for i = 1, #items2 do
equals(map[items2[i]], map2[items2[i]]) equals(map[items2[i]], map2[items2[i]])
equals(fs.getInfo('data/' .. items2[i]), love.filesystem.getInfo('data/' .. items2[i]))
end end
equals(#fs.getDirectoryItems('does_not_exist'), 0) equals(#fs.getDirectoryItems('does_not_exist'), 0)
end end
function test_fs_getDirectoryItemsInfo() function test_fs_getDirectoryItemsInfo()
local items, map = fs.getDirectoryItems('data'), {} local files = fs.getDirectoryItems('data')
for i = 1, #items do map[items[i]] = true end local items, map = {}, {}
for i = 1, #files do
local info = fs.getInfo('data/' .. files[i])
if info then
info.name = files[i]
table.insert(items, info)
end
end
for i = 1, #items do map[items[i].name] = true end
local itemsEx, mapEx = fs.getDirectoryItemsInfo('data'), {} local itemsEx, mapEx = fs.getDirectoryItemsInfo('data'), {}
for i = 1, #itemsEx do mapEx[itemsEx[i].name] = itemsEx[i] end for i = 1, #itemsEx do mapEx[itemsEx[i].name] = itemsEx[i] end
@@ -203,6 +213,12 @@ function test_fs_getInfo()
equals(info.type, 'file') equals(info.type, 'file')
equals(info.size, testSize1) equals(info.size, testSize1)
notEquals(info.modtime, nil) notEquals(info.modtime, nil)
local info = fs.getInfo(testFile2)
notEquals(info, nil)
equals(info.type, 'file')
equals(info.size, testSize2)
notEquals(info.modtime, nil)
end end
function test_fs_createDirectory() function test_fs_createDirectory()