summaryrefslogtreecommitdiff
path: root/xmake/core
diff options
context:
space:
mode:
authorruki <[email protected]>2019-08-18 23:29:31 +0800
committerruki <[email protected]>2019-08-18 23:29:31 +0800
commit236988050bfe9f51ebe6b72c6e3d760bb2e349ef (patch)
treea024e29828dd0954705f276bd257cd77cafad1c5 /xmake/core
parent35e6c625a2279a9c6adfdba1027b27d088b3c8b6 (diff)
rewrite io
Diffstat (limited to 'xmake/core')
-rw-r--r--xmake/core/base/io.lua151
-rw-r--r--xmake/core/base/process.lua3
-rw-r--r--xmake/core/sandbox/modules/io.lua153
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