diff options
| author | ruki <[email protected]> | 2019-08-18 23:29:31 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2019-08-18 23:29:31 +0800 |
| commit | 236988050bfe9f51ebe6b72c6e3d760bb2e349ef (patch) | |
| tree | a024e29828dd0954705f276bd257cd77cafad1c5 /xmake/core | |
| parent | 35e6c625a2279a9c6adfdba1027b27d088b3c8b6 (diff) | |
rewrite io
Diffstat (limited to 'xmake/core')
| -rw-r--r-- | xmake/core/base/io.lua | 151 | ||||
| -rw-r--r-- | xmake/core/base/process.lua | 3 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/io.lua | 153 |
3 files changed, 240 insertions, 67 deletions
diff --git a/xmake/core/base/io.lua b/xmake/core/base/io.lua index cbb2a409b..b86d4dd1a 100644 --- a/xmake/core/base/io.lua +++ b/xmake/core/base/io.lua @@ -20,7 +20,7 @@ -- define module local io = io or {} -local _file = _file or io._file or {} +local _file = _file or {} local _filelock = _filelock or {} -- load modules @@ -28,15 +28,130 @@ local path = require("base/path") local table = require("base/table") local string = require("base/string") --- save original apis -io._open = io._open or io.open +-- save metatable +io._file = _file io._filelock = _filelock -_file._read = _file._read or _file.read + +-- new an file +function _file.new(filepath, file) + local file = table.inherit(_file) + file._NAME = path.filename(filepath) + file._PATH = filepath + file._FILE = file + setmetatable(file, _file) + return file +end + +-- get the file name +function _file:name() + return self._NAME +end + +-- get the file path +function _file:path() + return self._PATH +end + +-- close file +function _file:close() + if not self._FILE then + return false, string.format("file(%s) has been closed!", self:name()) + end + local ok, errors = io.file_close(self._FILE) + if ok then + self._FILE = nil + end + return ok, errors +end + +-- tostring(file) +function _file:__tostring() + return "file: " .. self:name() +end + +-- gc(file) +function _file:__gc() + if self._FILE and io.file_close(self._FILE) then + self._FILE = nil + end +end + +-- get file length +function _file:__len() + return self:size() +end + +-- get file size +function _file:size() + if not self._FILE then + return false, string.format("file(%s) has been closed!", self:name()) + end + local result, errors = io.file_size(self._FILE) + if not result and errors then + errors = string.format("file(%s): %s", self:name(), errors) + end + return result, errors +end -- read data from file function _file:read(fmt, opt) + if not self._FILE then + return false, string.format("file(%s) has been closed!", self:name()) + end opt = opt or {} - return self:_read(fmt, opt.continuation) + local result, errors = io.file_read(self._FILE, fmt, opt.continuation) + if not result then + errors = string.format("file(%s): %s", self:name(), errors) + end + return result, errors +end + +-- write data to file +function _file:write(...) + if not self._FILE then + return false, string.format("file(%s) has been closed!", self:name()) + end + local ok, errors = io.file_write(self._FILE, ...) + if not ok and errors then + errors = string.format("file(%s): %s", self:name(), errors) + end + return ok, errors +end + +-- seek offset at file +function _file:seek(whence, offset) + if not self._FILE then + return false, string.format("file(%s) has been closed!", self:name()) + end + local result, errors = io.file_seek(self._FILE, whence, offset) + if not result and errors then + errors = string.format("file(%s): %s", self:name(), errors) + end + return result, errors +end + +-- flush data to file +function _file:flush() + if not self._FILE then + return false, string.format("file(%s) has been closed!", self:name()) + end + local ok, errors = io.file_flush(self._FILE) + if not ok and errors then + errors = string.format("file(%s): %s", self:name(), errors) + end + return ok, errors +end + +-- this file is a tty? +function _file:isatty() + if not self._FILE then + return false, string.format("file(%s) has been closed!", self:name()) + end + local ok, errors = io.file_isatty(self._FILE) + if not ok and errors then + errors = string.format("file(%s): %s", self:name(), errors) + end + return ok, errors end -- iterator of lines @@ -66,11 +181,11 @@ end -- save object function _file:save(object, opt) local str, errors = string.serialize(object, opt) - if not errors then - self:write(str) - return str + if errors then + return false, errors + else + return self:write(str) end - return str, errors end -- load object @@ -183,8 +298,7 @@ end -- gc(filelock) function _filelock:__gc() - local ok = self._LOCK and io.filelock_close(self._LOCK) or false - if ok then + if self._LOCK and io.filelock_close(self._LOCK) then self._LOCK = nil self._LOCKED_NUM = 0 end @@ -236,7 +350,7 @@ function io.read(fmt, opt) end function io.write(...) - io.stdout:write(...) + return io.stdout:write(...) end function io.print(...) @@ -274,9 +388,9 @@ function io.writefile(filepath, data, opt) end -- isatty -function io.isatty(fd) - fd = fd or io.stdout - return fd:isatty() +function io.isatty(file) + file = file or io.stdout + return file:isatty() end -- replace the original open interface @@ -290,11 +404,12 @@ function io.open(filepath, mode, opt) mode = mode or "r" -- open it - local file = io._open(filepath, mode .. (opt.encoding or "")) - if not file then + local file = io.file_open(filepath, mode .. (opt.encoding or "")) + if file then + return _file.new(filepath, file) + else return nil, string.format("failed to open file: %s", filepath) end - return file end -- open a filelock diff --git a/xmake/core/base/process.lua b/xmake/core/base/process.lua index cf5f3744e..1e4fe5434 100644 --- a/xmake/core/base/process.lua +++ b/xmake/core/base/process.lua @@ -84,8 +84,7 @@ end -- gc(subprocess) function _subprocess:__gc() - local ok = self._PROC and process._close(self._PROC) or false - if ok then + if self._PROC and process._close(self._PROC) then self._PROC = nil end end diff --git a/xmake/core/sandbox/modules/io.lua b/xmake/core/sandbox/modules/io.lua index ca6f29ee4..752026e78 100644 --- a/xmake/core/sandbox/modules/io.lua +++ b/xmake/core/sandbox/modules/io.lua @@ -27,57 +27,105 @@ local vformat = require("sandbox/modules/vformat") -- define module local sandbox_io = sandbox_io or {} -local sandbox_io_file = sandbox_io._file or {} +local sandbox_io_file = sandbox_io_file or {} local sandbox_io_filelock = sandbox_io_filelock or {} -sandbox_io._file = sandbox_io_file +sandbox_io._file = sandbox_io._file or io._file sandbox_io._filelock = sandbox_io._filelock or io._filelock --- inherit some builtin interfaces -sandbox_io.lines = io.lines -sandbox_io.read = io.read -sandbox_io.isatty = io.isatty +-- get file size +function sandbox_io_file.size(file) + local result, errors = file:_size() + if not result then + raise(errors) + end + return result +end --- inherit matatable of file -if sandbox_io_file.__index ~= sandbox_io_file then - sandbox_io_file.__index = sandbox_io_file - for k, v in pairs(io._file) do - if type(v) == "function" then - sandbox_io_file[k] = function(s, ...) - local result, err = v(s._FILE, ...) - if result == nil and err ~= nil then - raise(err) - end - -- wrap to sandbox_file again - if result == s._FILE then - result = s - end - return result - end - end +-- close file +function sandbox_io_file.close(file) + local ok, errors = file:_close() + if not ok then + raise(errors) end - -- file:lines does not use its second return value for error - sandbox_io_file.lines = io._file.lines + return ok end --- get file size -function sandbox_io_file:size() - -- __len on tables is scheduled to be supported in 5.2. - return sandbox_io_file.__len(self) +-- flush file +function sandbox_io_file.flush(file) + local ok, errors = file:_flush() + if not ok then + raise(errors) + end + return ok +end + +-- this file is a tty? +function sandbox_io_file.isatty(file) + local ok, errors = file:_isatty() + if not ok then + raise(errors) + end + return ok +end + +-- seek offset at file +function sandbox_io_file.seek(file, whence, offset) + local result, errors = file:_seek(whence, offset) + if not result then + raise(errors) + end + return result +end + +-- read data from file +function sandbox_io_file.read(file, fmt, opt) + local result, errors = file:_read(fmt, opt) + if not result then + raise(errors) + end + return result +end + +-- write data to file +function sandbox_io_file.write(file, ...) + local ok, errors = file:_write(...) + if not ok then + raise(errors) + end + return ok end -- print file -function sandbox_io_file:print(...) - return self:write(vformat(...), "\n") +function sandbox_io_file.print(file, ...) + return sandbox_io_file.write(file, vformat(...), "\n") end -- printf file -function sandbox_io_file:printf(...) - return self:write(vformat(...)) +function sandbox_io_file.printf(file, ...) + return sandbox_io_file.write(file, vformat(...)) +end + +-- writef file (without value filter) +function sandbox_io_file.writef(file, ...) + return sandbox_io_file.write(file, string.format(...)) end --- writef file -function sandbox_io_file:writef(...) - return self:write(string.format(...)) +-- load object from file +function sandbox_io_file.load(file) + local result, errors = file:_load() + if errors then + raise(errors) + end + return result +end + +-- save object to file +function sandbox_io_file.save(file, object, opt) + local ok, errors = file:_save(object, opt) + if not ok then + raise(errors) + end + return ok end -- lock filelock @@ -146,9 +194,17 @@ function sandbox_io.open(filepath, mode, opt) raise(errors) end - -- bind metatable - file = { _FILE = file } - setmetatable(file, sandbox_io_file); + -- hook file interfaces + local hooked = {} + for name, func in pairs(sandbox_io_file) do + if not name:startswith("_") and type(func) == "function" then + hooked["_" .. name] = file["_" .. name] or file[name] + hooked[name] = func + end + end + for name, func in pairs(hooked) do + file[name] = func + end return file end @@ -235,6 +291,11 @@ function sandbox_io.readfile(filepath, opt) return result end +--- direct read from stdin +function sandbox_io.read(fmt, opt) + return sandbox_io.stdin:read(fmt, opt) +end + --- direct write to stdout function sandbox_io.write(...) sandbox_io.stdout:write(...) @@ -245,6 +306,12 @@ function sandbox_io.flush(file) return (file or sandbox_io.stdout):flush() end +-- isatty +function sandbox_io.isatty(file) + file = file or sandbox_io.stdout + return file:isatty() +end + -- write all data to file function sandbox_io.writefile(filepath, data, opt) @@ -297,14 +364,6 @@ function sandbox_io.tail(filepath, linecount, opt) io.tail(filepath, linecount, opt) end --- wrap std files -sandbox_io.stdin = { _FILE = io.stdin } -sandbox_io.stderr = { _FILE = io.stderr } -sandbox_io.stdout = { _FILE = io.stdout } -setmetatable(sandbox_io.stdin, sandbox_io_file); -setmetatable(sandbox_io.stderr, sandbox_io_file); -setmetatable(sandbox_io.stdout, sandbox_io_file); - -- return module return sandbox_io |
