diff options
| author | ruki <[email protected]> | 2019-10-12 23:06:48 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2019-10-12 23:06:48 +0800 |
| commit | 938be7f39197d2f202fe3342e82d9d31c3264b53 (patch) | |
| tree | 088215082dc0a89902ba7ff7c97eecaf4f945278 /xmake/core/base/io.lua | |
| parent | 3dcbba4360d7a7ab7082117711566a5bfc6857dc (diff) | |
seperate io submodules
Diffstat (limited to 'xmake/core/base/io.lua')
| -rw-r--r-- | xmake/core/base/io.lua | 682 |
1 files changed, 5 insertions, 677 deletions
diff --git a/xmake/core/base/io.lua b/xmake/core/base/io.lua index 5aaebc1af..4a515c202 100644 --- a/xmake/core/base/io.lua +++ b/xmake/core/base/io.lua @@ -19,684 +19,12 @@ -- -- define module -local io = io or {} -local _file = _file or {} -local _filelock = _filelock or {} -local _socket = _socket or {} +local io = io or {} --- load modules -local path = require("base/path") -local table = require("base/table") -local string = require("base/string") - --- save metatable and builtin functions -io._file = _file -io._filelock = _filelock -io._socket = _socket -io._stdfile = io._stdfile or io.stdfile - --- new an file -function _file.new(filepath, fileref) - local file = table.inherit(_file) - file._NAME = path.filename(filepath) - file._PATH = path.absolute(filepath) - file._FILE = fileref - 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 rawfd -function _file:rawfd() - if not self._FILE then - return false, string.format("file(%s) has been closed!", self:name()) - end - local result, errors = io.file_rawfd(self._FILE) - if not result and errors then - errors = string.format("file(%s): %s", self:name(), errors) - end - return result, errors -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 {} - local result, errors = io.file_read(self._FILE, fmt, opt.continuation) - if errors 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 ok == nil and errors then - errors = string.format("file(%s): %s", self:name(), errors) - end - return ok, errors -end - --- iterator of lines -function _file._lines_iter(data) - local l = data.file:read("l", data.opt) - if not l and data.opt.close_on_finished then - data.file:close() - end - return l -end - --- read all lines from a file -function _file:lines(opt) - return _file._lines_iter, { file = assert(self), opt = opt or {} } -end - --- print file -function _file:print(...) - return self:write(string.format(...), "\n") -end - --- printf file -function _file:printf(...) - return self:write(string.format(...)) -end - --- save object -function _file:save(object, opt) - local str, errors = string.serialize(object, opt) - if errors then - return false, errors - else - return self:write(str) - end -end - --- load object -function _file:load() - local data, err = self:read("*all") - if err then - return nil, err - end - if data and type(data) == "string" then - return data:deserialize() - end -end - --- new a filelock -function _filelock.new(lockpath, lock) - local filelock = table.inherit(_filelock) - filelock._NAME = path.filename(lockpath) - filelock._PATH = path.absolute(lockpath) - filelock._LOCK = lock - filelock._LOCKED_NUM = 0 - setmetatable(filelock, _filelock) - return filelock -end - --- get the filelock name -function _filelock:name() - return self._NAME -end - --- get the filelock path -function _filelock:path() - return self._PATH -end - --- is locked? -function _filelock:islocked() - return self._LOCKED_NUM > 0 -end - --- lock file --- --- @param opt the argument option, {shared = true} --- --- @return ok, errors --- -function _filelock:lock(opt) - if not self._LOCK then - return false, string.format("filelock(%s) has been closed!", self:name()) - end - if self._LOCKED_NUM > 0 or io.filelock_lock(self._LOCK, opt) then - self._LOCKED_NUM = self._LOCKED_NUM + 1 - return true - else - return false, string.format("filelock(%s): lock %s failed!", self:name(), self:path()) - end -end - --- try to lock file --- --- @param opt the argument option, {shared = true} --- --- @return ok, errors --- -function _filelock:trylock(opt) - if not self._LOCK then - return false, string.format("filelock(%s) has been closed!", self:name()) - end - if self._LOCKED_NUM > 0 or io.filelock_trylock(self._LOCK, opt) then - self._LOCKED_NUM = self._LOCKED_NUM + 1 - return true - else - return false, string.format("filelock(%s): trylock %s failed!", self:name(), self:path()) - end -end - --- unlock file -function _filelock:unlock(opt) - if not self._LOCK then - return false, string.format("filelock(%s) has been closed!", self:name()) - end - if self._LOCKED_NUM > 1 or (self._LOCKED_NUM > 0 and io.filelock_unlock(self._LOCK)) then - if self._LOCKED_NUM > 0 then - self._LOCKED_NUM = self._LOCKED_NUM - 1 - else - self._LOCKED_NUM = 0 - end - return true - else - return false, string.format("filelock(%s): unlock %s failed!", self:name(), self:path()) - end -end - --- close filelock -function _filelock:close() - if not self._LOCK then - return false, string.format("filelock(%s) has been closed!", self:name()) - end - local ok = io.filelock_close(self._LOCK) - if ok then - self._LOCK = nil - self._LOCKED_NUM = 0 - end - return ok -end - --- tostring(filelock) -function _filelock:__tostring() - return "filelock: " .. self:name() -end - --- gc(filelock) -function _filelock:__gc() - if self._LOCK and io.filelock_close(self._LOCK) then - self._LOCK = nil - self._LOCKED_NUM = 0 - end -end - --- new a socket -function _socket.new(sock) - local socket = table.inherit(_socket) - socket._SOCK = sock - socket._NAME = "" - setmetatable(socket, _socket) - return socket -end - --- get the socket name -function _socket:name() - return self._NAME -end - --- close socket -function _socket:close() - if not self._SOCK then - return false, string.format("socket(%s) has been closed!", self:name()) - end - local ok = io.socket_close(self._SOCK) - if ok then - self._SOCK = nil - end - return ok -end - --- tostring(socket) -function _socket:__tostring() - return "socket: " .. self:name() -end - --- gc(socket) -function _socket:__gc() - if self._SOCK and io.socket_close(self._SOCK) then - self._SOCK = nil - end -end - --- read all lines from file -function io.lines(filepath, opt) - - -- close on finished - opt = opt or {} - if opt.close_on_finished == nil then - opt.close_on_finished = true - end - - -- open file - local file = io.open(filepath, "r", opt) - if not file then - return function() return nil end - end - - return file:lines(opt) -end - --- read all data from file -function io.readfile(filepath, opt) - - opt = opt or {} - - -- open file - local file = io.open(filepath, "r", opt) - if not file then - -- error - return nil, string.format("open %s failed!", filepath) - end - - -- read all - local data, err = file:read("*all", opt) - - -- exit file - file:close() - - -- ok? - return data, err -end - -function io.read(fmt, opt) - return io.stdin:read(fmt, opt) -end - -function io.write(...) - return io.stdout:write(...) -end - -function io.print(...) - return io.stdout:print(...) -end - -function io.printf(...) - return io.stdout:printf(...) -end - -function io.flush() - return io.stdout:flush() -end - --- write data to file -function io.writefile(filepath, data, opt) - - -- init option - opt = opt or {} - - -- open file - local file = io.open(filepath, "w", opt) - if not file then - return false, string.format("open %s failed!", filepath) - end - - -- write all - file:write(data) - - -- exit file - file:close() - - -- ok? - return true -end - --- isatty -function io.isatty(file) - file = file or io.stdout - return file:isatty() -end - --- get std file, /dev/stdin, /dev/stdout, /dev/stderr -function io.stdfile(filepath) - local file = nil - if filepath == "/dev/stdin" then - file = io._stdfile(1) - elseif filepath == "/dev/stdout" then - file = io._stdfile(2) - elseif filepath == "/dev/stderr" then - file = io._stdfile(3) - end - if file then - return _file.new(filepath, file) - else - return nil, string.format("failed to get std file: %s", filepath) - end -end - --- open file -function io.open(filepath, mode, opt) - - -- check - assert(filepath) - - -- init option and mode - opt = opt or {} - mode = mode or "r" - - -- open it - 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 -end - --- open a filelock -function io.openlock(filepath) - - -- check - assert(filepath) - - -- open it - local lock = io.filelock_open(filepath) - if lock then - return _filelock.new(filepath, lock) - else - return nil, string.format("failed to open lock: %s", filepath) - end -end - --- open a socket -function io.opensock() - - -- open it - local sock = io.socket_open() - if sock then - return _socket.new(filepath, sock) - else - return nil, string.format("failed to open socket!") - end -end - --- close file -function io.close(file) - return (file or io.stdout):close() -end - --- save object the the given filepath -function io.save(filepath, object, opt) - - -- check - assert(filepath and object) - - -- init option - opt = opt or {} - - -- open the file - local file, err = io.open(filepath, "wb", opt) - if err then - -- error - return false, err - end - - -- save object to file - local ok, errors = file:save(object, opt) - -- close file - file:close() - if not ok then - -- error - return false, string.format("save %s failed, %s!", filepath, errors) - end - - -- ok - return true -end - --- load object from the given file -function io.load(filepath, opt) - - -- check - assert(filepath) - - -- init option - opt = opt or {} - - -- open the file - local file, err = io.open(filepath, "rb", opt) - if err then - -- error - return nil, err - end - - -- load object - local result, errors = file:load() - - -- close file - file:close() - - -- ok? - return result, errors -end - --- gsub the given file and return replaced data -function io.gsub(filepath, pattern, replace, opt) - - -- init option - opt = opt or {} - - -- read all data from file - local data, errors = io.readfile(filepath, opt) - if not data then return nil, 0, errors end - - -- replace it - local count = 0 - if type(data) == "string" then - data, count = data:gsub(pattern, replace) - else - return nil, 0, string.format("data is not string!") - end - - -- replace ok? - if count ~= 0 then - -- write all data to file - local ok, errors = io.writefile(filepath, data, opt) - if not ok then return nil, 0, errors end - end - - -- ok - return data, count -end - --- cat the given file -function io.cat(filepath, linecount, opt) - - -- init option - opt = opt or {} - - -- open file - local file = io.open(filepath, "r", opt) - if file then - - -- show file - local count = 1 - for line in file:lines(opt) do - - -- show line - io.print(line) - - -- end? - if linecount and count >= linecount then - break - end - - -- update the line count - count = count + 1 - end - - -- exit file - file:close() - end -end - --- tail the given file -function io.tail(filepath, linecount, opt) - - -- init option - opt = opt or {} - - -- all? - if linecount < 0 then - return io.cat(filepath, opt) - end - - -- open file - local file = io.open(filepath, "r", opt) - if file then - - -- read lines - local lines = {} - for line in file:lines(opt) do - table.insert(lines, line) - end - - -- tail lines - local tails = {} - if #lines ~= 0 then - local count = 1 - for index = #lines, 1, -1 do - - -- show line - table.insert(tails, lines[index]) - - -- end? - if linecount and count >= linecount then - break - end - - -- update the line count - count = count + 1 - end - end - - -- show tails - if #tails ~= 0 then - for index = #tails, 1, -1 do - - -- show tail - io.print(tails[index]) - - end - end - - -- exit file - file:close() - end -end - --- lazy loading stdfile -io.stdin = nil -io.stdout = nil -io.stderr = nil -setmetatable(io, { __index = function (tbl, key) - local val = rawget(tbl, key) - if val == nil and (key == "stdin" or key == "stdout" or key == "stderr") then - val = io.stdfile("/dev/" .. key) - if val ~= nil then - rawset(tbl, key, val) - end - end - return val - end}) +-- load io submodules +require("base/io/file") +require("base/io/socket") +require("base/io/filelock") -- return module return io |
