mirror of
https://github.com/EngineerSmith/nativefs.git
synced 2025-11-08 23:15:02 +00:00
initial commit
This commit is contained in:
399
nativefs.lua
Normal file
399
nativefs.lua
Normal file
@@ -0,0 +1,399 @@
|
||||
local ffi, bit = require('ffi'), require('bit')
|
||||
local C = ffi.C
|
||||
|
||||
ffi.cdef([[
|
||||
typedef struct FILE FILE;
|
||||
|
||||
FILE* fopen(const char* pathname, const char* mode);
|
||||
size_t fread(void* ptr, size_t size, size_t nmemb, FILE* stream);
|
||||
size_t fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream);
|
||||
int fclose(FILE* stream);
|
||||
int fflush(FILE* stream);
|
||||
size_t fseek(FILE* stream, size_t offset, int whence);
|
||||
size_t ftell(FILE* stream);
|
||||
char* getcwd(char *buffer, int maxlen);
|
||||
int chdir(const char* path);
|
||||
int setvbuf(FILE* stream, char* buffer, int mode, size_t size);
|
||||
int feof(FILE* stream);
|
||||
int unlink(const char* path);
|
||||
]])
|
||||
|
||||
local fopen, fclose, ftell, fseek, fflush, feof = C.fopen, C.fclose, C.ftell, C.fseek, C.fflush
|
||||
local fread, fwrite, feof = C.fread, C.fwrite, C.feof
|
||||
local setvbuf, getcwd, chdir, unlink = C.setvbuf, C.getcwd, C.chdir, C.unlink
|
||||
|
||||
local BUFFERMODE = {
|
||||
full = 0,
|
||||
line = 1,
|
||||
none = 2,
|
||||
}
|
||||
|
||||
if ffi.os == 'Windows' then
|
||||
ffi.cdef([[
|
||||
typedef void* HANDLE;
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
struct WIN32_FIND_DATAW {
|
||||
uint32_t dwFileWttributes;
|
||||
uint64_t ftCreationTime;
|
||||
uint64_t ftLastAccessTime;
|
||||
uint64_t ftLastWriteTime;
|
||||
uint32_t dwReserved[4];
|
||||
char cFileName[520];
|
||||
char cAlternateFileName[28];
|
||||
};
|
||||
#pragma(pop)
|
||||
|
||||
int MultiByteToWideChar(unsigned int CodePage, uint32_t dwFlags, const char* lpMultiByteStr, int cbMultiByte, const char* lpWideCharStr, int cchWideChar);
|
||||
int WideCharToMultiByte(unsigned int CodePage, uint32_t dwFlags, const char* lpWideCharStr, int cchWideChar, const char* lpMultiByteStr, int cchMultiByte, const char* default, int* used);
|
||||
|
||||
int GetLogicalDrives(void);
|
||||
void* FindFirstFileW(const wchar_t* lpFileName, struct WIN32_FIND_DATAW* lpFindFileData);
|
||||
bool FindNextFileW(HANDLE hFindFile, struct WIN32_FIND_DATAW* fd);
|
||||
bool FindClose(HANDLE hFindFile);
|
||||
|
||||
int _wchdir(const wchar_t* path);
|
||||
wchar_t* _wgetcwd(wchar_t* buffer, int maxlen);
|
||||
FILE* _wfopen(const wchar_t* name, const wchar_t* mode);
|
||||
int _wunlink(const wchar_t* name);
|
||||
]])
|
||||
|
||||
local function towidestring(str)
|
||||
local size = C.MultiByteToWideChar(65001, 0, str, #str, nil, 0)
|
||||
local buf = ffi.new("char[?]", size * 2 + 2)
|
||||
C.MultiByteToWideChar(65001, 0, str, #str, buf, size * 2)
|
||||
return buf
|
||||
end
|
||||
|
||||
local function toutf8string(wstr)
|
||||
local size = C.WideCharToMultiByte(65001, 0, wstr, -1, nil, 0, nil, nil)
|
||||
local buf = ffi.new("char[?]", size + 1)
|
||||
size = C.WideCharToMultiByte(65001, 0, wstr, -1, buf, size, nil, nil)
|
||||
return ffi.string(buf, size)
|
||||
end
|
||||
|
||||
local MAX_PATH = 260
|
||||
local nameBuffer = ffi.new("char[?]", MAX_PATH * 2 + 2)
|
||||
|
||||
fopen = function(name, mode) return C._wfopen(towidestring(name), towidestring(mode)) end
|
||||
getcwd = function() return toutf8string(C._wgetcwd(nameBuffer, MAX_PATH)) end
|
||||
chdir = function(path) return C._wchdir(towidestring(path)) end
|
||||
unlink = function(name) return C._wunlink(towidestring(path)) end
|
||||
else
|
||||
local MAX_PATH = 4096
|
||||
local nameBuffer = ffi.new("char[?]", MAX_PATH)
|
||||
|
||||
getcwd = function()
|
||||
local cwd = C.getcwd(nameBuffer, MAX_PATH)
|
||||
if cwd == nil then
|
||||
return nil
|
||||
end
|
||||
return ffi.string(cwd)
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
-- NOTE: nil checks on file handles MUST be explicit (_handle == nil)
|
||||
-- due to ffi's NULL semantics!
|
||||
|
||||
local File = {}
|
||||
File.__index = File
|
||||
|
||||
function File:open(mode)
|
||||
if self._mode ~= 'c' then
|
||||
return false, "File is already open"
|
||||
end
|
||||
|
||||
mode = mode or 'r'
|
||||
local handle = fopen(self._name, mode)
|
||||
if handle == nil then
|
||||
-- TODO: get error message
|
||||
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
|
||||
return true
|
||||
end
|
||||
|
||||
function File:close()
|
||||
if self._handle == nil or self._mode == 'c' then
|
||||
return false, "File is not open"
|
||||
end
|
||||
|
||||
ffi.gc(self._handle, nil)
|
||||
fclose(self._handle)
|
||||
self._handle, self._mode = nil, 'c'
|
||||
return true
|
||||
end
|
||||
|
||||
function File:setBuffer(mode, size)
|
||||
bufferMode = BUFFERMODE[mode]
|
||||
if not bufferMode then
|
||||
return false, "Invalid buffer mode: " .. mode .. " (expected 'none', 'full', or 'line')"
|
||||
end
|
||||
|
||||
size = math.max(0, size or 0)
|
||||
self._bufferMode, self._bufferSize = mode, size
|
||||
if self._mode == 'c' then return true end
|
||||
|
||||
if C.setvbuf(self._handle, nil, bufferMode, size) ~= 0 then
|
||||
-- TODO: get error message
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function File:getBuffer()
|
||||
return self._bufferMode, self._bufferSize
|
||||
end
|
||||
|
||||
function File:getFilename()
|
||||
return self._name
|
||||
end
|
||||
|
||||
function File:getMode()
|
||||
return self._mode
|
||||
end
|
||||
|
||||
function File:getSize()
|
||||
-- NOTE: The correct way to do this would be a stat() call, which requires a
|
||||
-- lot more (system-specific) code. This is a shortcut that requires the file
|
||||
-- to be readable.
|
||||
local mustOpen = not self:isOpen()
|
||||
if mustOpen and not self:open('r') then
|
||||
return 0
|
||||
end
|
||||
|
||||
local pos = mustOpen and 0 or self:tell()
|
||||
fseek(self._handle, 0, 2)
|
||||
local size = tonumber(self:tell())
|
||||
if mustOpen then
|
||||
self:close()
|
||||
else
|
||||
self:seek(pos)
|
||||
end
|
||||
return size;
|
||||
end
|
||||
|
||||
function File:isEOF()
|
||||
return self:isOpen() and feof(self._handle) or false
|
||||
end
|
||||
|
||||
function File:isOpen()
|
||||
return self._mode ~= 'c' and self._handle ~= nil
|
||||
end
|
||||
|
||||
function File:read(containerOrBytes, bytes)
|
||||
if self._handle == nil or self._mode ~= 'r' then
|
||||
return nil, 0
|
||||
end
|
||||
|
||||
local container = bytes ~= nil and containerOrBytes or 'string'
|
||||
bytes = bytes == nil and containerOrBytes or 'all'
|
||||
if bytes == 'all' then
|
||||
bytes = self:getSize() - self:tell()
|
||||
else
|
||||
bytes = math.min(self:getSize() - self:tell(), bytes)
|
||||
end
|
||||
|
||||
if bytes <= 0 then
|
||||
local data = container == 'string' and '' or love.data.newByteData(0)
|
||||
return data, 0
|
||||
end
|
||||
|
||||
local data = love.data.newByteData(bytes)
|
||||
local r = tonumber(fread(data:getFFIPointer(), 1, bytes, self._handle))
|
||||
|
||||
if container == 'string' then
|
||||
local str = data:getString()
|
||||
data:release()
|
||||
data = str
|
||||
end
|
||||
return data, r
|
||||
end
|
||||
|
||||
function File:lines()
|
||||
end
|
||||
|
||||
function File:write(data, size)
|
||||
if self._mode ~= 'w' and self._mode ~= 'a' then
|
||||
return false, "File " .. self._name .. " not opened for writing"
|
||||
end
|
||||
if type(data) == 'string' then
|
||||
size = (size == nil or size == 'all') and #data or size
|
||||
local success = fwrite(data, 1, size, self._handle) == size
|
||||
if not success then
|
||||
return false, "Could not write data"
|
||||
end
|
||||
else
|
||||
size = (size == nil or size == 'all') and data:getSize() or size
|
||||
local success = fwrite(data:getFFIPointer(), 1, size, self._handle) == size
|
||||
if not success then
|
||||
return false, "Could not write data"
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function File:seek(pos)
|
||||
if self._handle == nil then return false end
|
||||
return fseek(self._handle, pos, 0) == 0
|
||||
end
|
||||
|
||||
function File:tell()
|
||||
if self._handle == nil then return -1 end
|
||||
return tonumber(ftell(self._handle))
|
||||
end
|
||||
|
||||
function File:flush()
|
||||
if self._handle == nil then return end
|
||||
return fflush(self._handle)
|
||||
end
|
||||
|
||||
function File:release()
|
||||
if self._mode ~= 'c' then
|
||||
self:close()
|
||||
end
|
||||
self._handle = nil
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
local nativefs = {}
|
||||
|
||||
function nativefs.newFile(name)
|
||||
return setmetatable({
|
||||
_name = name,
|
||||
_mode = 'c',
|
||||
_handle = nil,
|
||||
_bufferSize = 0,
|
||||
_bufferMode = 'none'
|
||||
}, File)
|
||||
end
|
||||
|
||||
function nativefs.newFileData(filepath)
|
||||
local f = nativefs.newFile(filepath)
|
||||
local ok, err = f:open('r')
|
||||
if not ok then return nil, err end
|
||||
|
||||
local data = f:read()
|
||||
f:close()
|
||||
return love.filesystem.newFileData(data, filepath)
|
||||
end
|
||||
|
||||
function nativefs.mount()
|
||||
end
|
||||
|
||||
function nativefs.unmount()
|
||||
end
|
||||
|
||||
function nativefs.read(containerOrName, nameOrSize, sizeOrNil)
|
||||
local container, name, size
|
||||
if sizeOrNil then
|
||||
container, name, size = containerOrName, nameOrSize, sizeOrNil
|
||||
elseif not nameOrSize then
|
||||
container, name, size = 'string', containerOrName, 'all'
|
||||
else
|
||||
if type(nameOrSize) == 'number' or nameOrSize == 'all' then
|
||||
container, name, size = 'string', containerOrName, nameOrSize
|
||||
else
|
||||
container, name, size = containerOrName, nameOrSize, 'all'
|
||||
end
|
||||
end
|
||||
|
||||
local file = nativefs.newFile(name)
|
||||
if not file:open('r') then
|
||||
return nil, "Could not open file for reading: " .. name
|
||||
end
|
||||
|
||||
local data, size = file:read(container, size)
|
||||
file:close()
|
||||
return data, size
|
||||
end
|
||||
|
||||
function nativefs.write(name, data, size)
|
||||
local file = nativefs.newFile(name)
|
||||
if not file:open('w') then
|
||||
return nil, "Could not open file for writing: " .. name
|
||||
end
|
||||
|
||||
local ok, err = file:write(data, size or 'all')
|
||||
file:close()
|
||||
return ok, err
|
||||
end
|
||||
|
||||
function nativefs.append(name, data, size)
|
||||
local file = nativefs.newFile(name)
|
||||
if not file:open('a') then
|
||||
return nil, "Could not open file for writing: " .. name
|
||||
end
|
||||
|
||||
local ok, err = file:write(data, size or 'all')
|
||||
file:close()
|
||||
return ok, err
|
||||
end
|
||||
|
||||
function nativefs.lines(name)
|
||||
local f = nativefs.newFile(name)
|
||||
local ok, err = f:open('r')
|
||||
if not ok then return nil, err end
|
||||
return f:lines()
|
||||
end
|
||||
|
||||
function nativefs.load(name)
|
||||
local chunk, err = nativefs.read(name)
|
||||
if not chunk then
|
||||
return nil, err
|
||||
end
|
||||
return loadstring(chunk, name)
|
||||
end
|
||||
|
||||
function nativefs.getDirectoryItems(dir, callback)
|
||||
end
|
||||
|
||||
function nativefs.getWorkingDirectory()
|
||||
return getcwd()
|
||||
end
|
||||
|
||||
function nativefs.setWorkingDirectory(path)
|
||||
if chdir(path) ~= 0 then
|
||||
return false, "Could not set working directory"
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function nativefs.getDriveList()
|
||||
if ffi.os ~= 'Windows' then
|
||||
return { '/' }
|
||||
end
|
||||
|
||||
local drives = {}
|
||||
local bits = C.GetLogicalDrives()
|
||||
for i = 0, 25 do
|
||||
if bit.band(bits, 2 ^ i) > 0 then
|
||||
table.insert(drives, string.char(65 + i) .. ':/')
|
||||
end
|
||||
end
|
||||
|
||||
return drives
|
||||
end
|
||||
|
||||
function nativefs.getInfo(name)
|
||||
end
|
||||
|
||||
function nativefs.createDirectory(path)
|
||||
end
|
||||
|
||||
function nativefs.remove(name)
|
||||
if unlink(name) ~= 0 then
|
||||
return false, "Could not remove file " .. name
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
return nativefs
|
||||
131
src/nativefs.moon
Normal file
131
src/nativefs.moon
Normal file
@@ -0,0 +1,131 @@
|
||||
ffi = require('ffi')
|
||||
bit = require('bit')
|
||||
|
||||
ffi.cdef([[
|
||||
typedef struct FILE FILE;
|
||||
]])
|
||||
|
||||
fopen = ffi.C.fopen
|
||||
fclose, ftell, fseek, fflush = ffi.C.fclose, ffi.C.ftell, ffi.C.fseek, ffi.C.fflush
|
||||
|
||||
if ffi.os == 'Windows'
|
||||
ffi.cdef([[
|
||||
typedef void* HANDLE;
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
struct WIN32_FIND_DATAW {
|
||||
uint32_t dwFileWttributes;
|
||||
uint64_t ftCreationTime;
|
||||
uint64_t ftLastAccessTime;
|
||||
uint64_t ftLastWriteTime;
|
||||
uint32_t dwReserved[4];
|
||||
char cFileName[520];
|
||||
char cAlternateFileName[28];
|
||||
};
|
||||
#pragma(pop)
|
||||
|
||||
int MultiByteToWideChar(unsigned int CodePage, uint32_t dwFlags, const char* lpMultiByteStr, int cbMultiByte, const char* lpWideCharStr, int cchWideChar);
|
||||
int WideCharToMultiByte(unsigned int CodePage, uint32_t dwFlags, const char* lpWideCharStr, int cchWideChar, const char* lpMultiByteStr, int cchMultiByte, const char* default, int* used);
|
||||
|
||||
int GetLogicalDrives(void);
|
||||
void* FindFirstFileW(const wchar_t* lpFileName, struct WIN32_FIND_DATAW* lpFindFileData);
|
||||
bool FindNextFileW(HANDLE hFindFile, struct WIN32_FIND_DATAW* fd);
|
||||
bool FindClose(HANDLE hFindFile);
|
||||
|
||||
int _wchdir(const wchar_t* path);
|
||||
wchar_t* _wgetcwd(wchar_t* buffer, int maxlen);
|
||||
FILE* _wfopen(const wchar_t* name, const wchar_t* mode);
|
||||
]])
|
||||
|
||||
towidestring = (str) ->
|
||||
size = ffi.C.MultiByteToWideChar(65001, 0, str, #str, nil, 0)
|
||||
buf = ffi.new("char[?]", size * 2 + 2)
|
||||
ffi.C.MultiByteToWideChar(65001, 0, str, #str, buf, size * 2)
|
||||
buf
|
||||
|
||||
toutf8string = (str) ->
|
||||
size = ffi.C.WideCharToMultiByte(65001, 0, wstr, -1, nil, 0, nil, nil)
|
||||
buf = ffi.new("char[?]", size + 1)
|
||||
size = ffi.C.WideCharToMultiByte(65001, 0, wstr, -1, buf, size, nil, nil)
|
||||
ffi.string(buf)
|
||||
|
||||
fopen = (name, mode) -> ffi.C._wfopen(towidestring(name), towidestring(mode))
|
||||
|
||||
class File
|
||||
new: (@_name) ->
|
||||
@_open = false
|
||||
@_handle = nil
|
||||
|
||||
open: (@_mode) ->
|
||||
@_handle = fopen(@_name, @_mode)
|
||||
return nil, "Could not open #{@_name} in mode #{@_mode}" unless @_handle
|
||||
ffi.gc(@_handle, fclose)
|
||||
true
|
||||
|
||||
close: ->
|
||||
ffi.gc(@_handle, nil)
|
||||
fclose(@_handle)
|
||||
@_handle = nil
|
||||
@_open = false
|
||||
|
||||
setBuffer: ->
|
||||
getBuffer: ->
|
||||
getFilename: -> @_name
|
||||
getMode: -> @_mode
|
||||
getSize: ->
|
||||
|
||||
isEOF: ->
|
||||
isOpen: -> @_open
|
||||
|
||||
read: ->
|
||||
lines: ->
|
||||
write: ->
|
||||
|
||||
seek: ->
|
||||
tell: -> ftell(@_handle)
|
||||
flush: -> fflush(@_handle)
|
||||
|
||||
nativefs = {}
|
||||
|
||||
nativefs.newFile = (name) -> File(name)
|
||||
|
||||
nativefs.newFileData = (filepath) ->
|
||||
f = File(filepath)
|
||||
ok, err = f\open('rb')
|
||||
return nil, err unless ok
|
||||
|
||||
data = f\read("all")
|
||||
f\close!
|
||||
love.filesystem.newFileData(data, filepath)
|
||||
|
||||
nativefs.mount = ->
|
||||
|
||||
nativefs.read = ->
|
||||
nativefs.write = ->
|
||||
nativefs.append = (name, data, size) ->
|
||||
nativefs.lines = (name) ->
|
||||
f = File(name)
|
||||
ok, err = f\open('r')
|
||||
return nil, err unless ok
|
||||
f\lines!
|
||||
|
||||
nativefs.load = ->
|
||||
|
||||
nativefs.exists = ->
|
||||
nativefs.isDirectory = ->
|
||||
nativefs.isFile = ->
|
||||
nativefs.isSymlink = ->
|
||||
|
||||
nativefs.getDirectoryItems = (dir, callback) ->
|
||||
nativefs.getWorkingDirectory = ->
|
||||
nativefs.setWorkingDirectory = (dir) ->
|
||||
nativefs.getDriveList = ->
|
||||
nativefs.getInfo = ->
|
||||
nativefs.getLastModified = ->
|
||||
nativefs.getSize = ->
|
||||
|
||||
nativefs.createDirectory = ->
|
||||
nativefs.remove = ->
|
||||
|
||||
nativefs
|
||||
26
test/conf.lua
Normal file
26
test/conf.lua
Normal file
@@ -0,0 +1,26 @@
|
||||
function love.conf(t)
|
||||
t.identity = nil
|
||||
t.appendidentity = false
|
||||
t.version = "11.3"
|
||||
t.console = true
|
||||
t.accelerometerjoystick = false
|
||||
t.externalstorage = false
|
||||
t.modules.audio = false
|
||||
t.modules.data = true
|
||||
t.modules.event = true
|
||||
t.modules.font = false
|
||||
t.modules.graphics = false
|
||||
t.modules.image = false
|
||||
t.modules.joystick = false
|
||||
t.modules.keyboard = false
|
||||
t.modules.math = true
|
||||
t.modules.mouse = false
|
||||
t.modules.physics = false
|
||||
t.modules.sound = false
|
||||
t.modules.system = true
|
||||
t.modules.thread = false
|
||||
t.modules.timer = true
|
||||
t.modules.touch = false
|
||||
t.modules.video = false
|
||||
t.modules.window = false
|
||||
end
|
||||
1
test/data/test.lua
Normal file
1
test/data/test.lua
Normal file
@@ -0,0 +1 @@
|
||||
return "hello"
|
||||
4
test/data/ümläüt.txt
Normal file
4
test/data/ümläüt.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
|
||||
Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
|
||||
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
|
||||
Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
|
||||
2779
test/luaunit.lua
Normal file
2779
test/luaunit.lua
Normal file
File diff suppressed because it is too large
Load Diff
195
test/main.lua
Normal file
195
test/main.lua
Normal file
@@ -0,0 +1,195 @@
|
||||
io.stdout:setvbuf('no')
|
||||
package.path = package.path .. ';../?.lua'
|
||||
|
||||
local ffi = require('ffi')
|
||||
local lu = require('luaunit')
|
||||
local fs = require('nativefs')
|
||||
local lfs = love.filesystem
|
||||
|
||||
local equals, notEquals = lu.assertEquals, lu.assertNotEquals
|
||||
local isError, containsError = lu.assertErrorMsgEquals, lu.assertErrorMsgContains
|
||||
local contains = lu.assertStrContains
|
||||
|
||||
local function notFailed(ok, err)
|
||||
equals(ok, true)
|
||||
equals(err, nil)
|
||||
end
|
||||
|
||||
local function hasFailed(expected, ok, err)
|
||||
equals(ok, false)
|
||||
if expected then
|
||||
equals(err, expected)
|
||||
end
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function test_fs_newFile()
|
||||
local file = fs.newFile('test.file')
|
||||
notEquals(file, nil)
|
||||
equals(file:getFilename(), 'test.file')
|
||||
end
|
||||
|
||||
function test_fs_newFileData()
|
||||
local fd = fs.newFileData('data/ümläüt.txt')
|
||||
local filesize = love.filesystem.newFile('data/ümläüt.txt'):getSize()
|
||||
equals(fd:getSize(), filesize)
|
||||
|
||||
local d = love.filesystem.read('data/ümläüt.txt')
|
||||
equals(fd:getString(), d)
|
||||
end
|
||||
|
||||
function test_fs_mount()
|
||||
end
|
||||
|
||||
function test_fs_read()
|
||||
local text, textSize = love.filesystem.read('data/ümläüt.txt')
|
||||
local data, size = fs.read('data/ümläüt.txt')
|
||||
equals(size, textSize)
|
||||
equals(data, text)
|
||||
|
||||
local data, size = fs.read('data/ümläüt.txt', 'all')
|
||||
equals(size, textSize)
|
||||
equals(data, text)
|
||||
|
||||
local data, size = fs.read('string', 'data/ümläüt.txt')
|
||||
equals(size, textSize)
|
||||
equals(data, text)
|
||||
|
||||
local data, size = fs.read('data', 'data/ümläüt.txt', 'all')
|
||||
equals(size, textSize)
|
||||
equals(data:getString(), text)
|
||||
|
||||
local foo, bar = fs.read('does_not_exist')
|
||||
equals(foo, nil)
|
||||
contains(bar, "Could not open")
|
||||
end
|
||||
|
||||
function test_fs_write()
|
||||
local data, size = fs.read('data/ümläüt.txt')
|
||||
notFailed(fs.write('data/write.test', data))
|
||||
|
||||
local data2, size2 = love.filesystem.read('data', 'data/write.test')
|
||||
notFailed(fs.write('data/write.test', data2, 100))
|
||||
local file = fs.newFile('data/write.test')
|
||||
equals(file:getSize(), 100)
|
||||
|
||||
fs.remove('data/write.test')
|
||||
end
|
||||
|
||||
function test_fs_append()
|
||||
local text, textSize = love.filesystem.read('data/ümläüt.txt')
|
||||
fs.write('data/append.test', text)
|
||||
fs.append('data/append.test', text)
|
||||
|
||||
local text2, textSize2 = love.filesystem.read('data/append.test')
|
||||
equals(textSize2, textSize * 2)
|
||||
equals(text2, text .. text)
|
||||
|
||||
fs.remove('data/append.test')
|
||||
end
|
||||
|
||||
function test_fs_lines()
|
||||
end
|
||||
|
||||
function test_fs_load()
|
||||
local chunk, err = fs.load('data/test.lua')
|
||||
notEquals(chunk, nil)
|
||||
local result = chunk()
|
||||
equals(result, 'hello')
|
||||
end
|
||||
|
||||
function test_fs_getDirectoryItems()
|
||||
end
|
||||
|
||||
function test_fs_setWorkingDirectory()
|
||||
local wd = fs.getWorkingDirectory()
|
||||
|
||||
notFailed(fs.setWorkingDirectory('data'))
|
||||
|
||||
local cwd = fs.getWorkingDirectory()
|
||||
notEquals(cwd, nil)
|
||||
equals(cwd:sub(#cwd - 3, #cwd), 'data')
|
||||
|
||||
hasFailed('Could not set working directory', fs.setWorkingDirectory('does_not_exist'))
|
||||
|
||||
notFailed(fs.setWorkingDirectory('..'))
|
||||
equals(fs.getWorkingDirectory(), wd)
|
||||
end
|
||||
|
||||
function test_fs_getDriveList()
|
||||
local dl = fs.getDriveList()
|
||||
notEquals(dl, nil)
|
||||
notEquals(#dl, 0)
|
||||
if ffi.os ~= 'Windows' then
|
||||
equals(dl[1], '/')
|
||||
end
|
||||
end
|
||||
|
||||
function test_fs_getInfo()
|
||||
end
|
||||
|
||||
function test_fs_createDirectory()
|
||||
end
|
||||
|
||||
function test_fs_remove()
|
||||
local text = love.filesystem.read('data/ümläüt.txt')
|
||||
fs.write('data/remove.test', text)
|
||||
notFailed(fs.remove('data/remove.test'))
|
||||
equals(love.filesystem.getInfo('data/remove.test'), nil)
|
||||
end
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
function test_File()
|
||||
end
|
||||
|
||||
function test_File_open()
|
||||
local f = fs.newFile('data/ümläüt.txt')
|
||||
notEquals(f, nil)
|
||||
equals(f:isOpen(), false)
|
||||
equals(f:getMode(), 'c')
|
||||
|
||||
notFailed(f:open())
|
||||
equals(f:isOpen(), true)
|
||||
equals(f:getMode(), 'r')
|
||||
|
||||
hasFailed('File is already open', f:open())
|
||||
equals(f:getMode(), 'r')
|
||||
|
||||
notFailed(f:close())
|
||||
equals(f:isOpen(), false)
|
||||
equals(f:getMode(), 'c')
|
||||
|
||||
hasFailed('File is not open', f:close())
|
||||
equals(f:getMode(), 'c')
|
||||
|
||||
f:release()
|
||||
end
|
||||
|
||||
function test_File_setBuffer()
|
||||
end
|
||||
|
||||
function test_File_isEOF()
|
||||
end
|
||||
|
||||
function test_File_read()
|
||||
end
|
||||
|
||||
function test_File_lines()
|
||||
end
|
||||
|
||||
function test_File_write()
|
||||
end
|
||||
|
||||
function test_File_seek()
|
||||
end
|
||||
|
||||
function test_File_tell()
|
||||
end
|
||||
|
||||
function test_File_flush()
|
||||
end
|
||||
|
||||
lu.LuaUnit.new():runSuite('--verbose')
|
||||
love.event.quit()
|
||||
Reference in New Issue
Block a user