diff options
| author | ruki <[email protected]> | 2019-10-13 22:40:54 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2019-10-13 22:40:54 +0800 |
| commit | 2eeba59f19090ee8108f13f8883d739739a4967d (patch) | |
| tree | 435b829bc2079d9d5a5c221be3fe96221e62ba1a | |
| parent | 3d88cf25bc977b9c5b01e5841d1175fc40bef6bd (diff) | |
add socket module
| -rw-r--r-- | xmake/core/base/io.lua | 630 | ||||
| -rw-r--r-- | xmake/core/base/io/file.lua | 577 | ||||
| -rw-r--r-- | xmake/core/base/io/filelock.lua | 181 | ||||
| -rw-r--r-- | xmake/core/base/socket.lua (renamed from xmake/core/base/io/socket.lua) | 34 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/import/core/base/socket.lua | 102 | ||||
| -rw-r--r-- | xmake/core/sandbox/modules/io.lua | 50 |
6 files changed, 746 insertions, 828 deletions
diff --git a/xmake/core/base/io.lua b/xmake/core/base/io.lua index 4a515c202..f6c931970 100644 --- a/xmake/core/base/io.lua +++ b/xmake/core/base/io.lua @@ -19,12 +19,632 @@ -- -- define module -local io = io or {} +local io = io or {} +local _file = _file or {} +local _filelock = _filelock or {} --- load io submodules -require("base/io/file") -require("base/io/socket") -require("base/io/filelock") +-- 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._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 an 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 + +-- 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 + +-- 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}) -- return module return io diff --git a/xmake/core/base/io/file.lua b/xmake/core/base/io/file.lua deleted file mode 100644 index 1e1c777c1..000000000 --- a/xmake/core/base/io/file.lua +++ /dev/null @@ -1,577 +0,0 @@ ---!A cross-platform build utility based on Lua --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. --- --- Copyright (C) 2015 - 2019, TBOOX Open Source Group. --- --- @author ruki --- @file file.lua --- - --- define module -local io = io or {} -local _file = _file or {} - --- load modules -local path = require("base/path") -local table = require("base/table") -local string = require("base/string") - --- save the builtin functions -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() - - -- ensure opened - local ok, errors = self:_ensure_opened() - if not ok then - return false, errors - end - - -- close it - ok, errors = io.file_close(self._FILE) - if ok then - self._FILE = nil - end - return ok, errors -end - --- ensure the file is opened -function _file:_ensure_opened() - if not self._FILE then - return false, string.format("%s: has been closed!", self) - end - return true -end - --- tostring(file) -function _file:__tostring() - local name = self:path() - if not name or #name > 16 then - name = self:name() - end - return "<file: " .. 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() - - -- ensure opened - local ok, errors = self:_ensure_opened() - if not ok then - return nil, errors - end - - -- get rawfd - local result, errors = io.file_rawfd(self._FILE) - if not result and errors then - errors = string.format("%s: %s", self, errors) - end - return result, errors -end - --- get file size -function _file:size() - - -- ensure opened - local ok, errors = self:_ensure_opened() - if not ok then - return nil, errors - end - - -- get file size - local result, errors = io.file_size(self._FILE) - if not result and errors then - errors = string.format("%s: %s", self, errors) - end - return result, errors -end - --- read data from file -function _file:read(fmt, opt) - - -- ensure opened - local ok, errors = self:_ensure_opened() - if not ok then - return nil, errors - end - - -- read it - opt = opt or {} - local result, errors = io.file_read(self._FILE, fmt, opt.continuation) - if errors then - errors = string.format("%s: %s", self, errors) - end - return result, errors -end - --- write data to file -function _file:write(...) - - -- ensure opened - local ok, errors = self:_ensure_opened() - if not ok then - return false, errors - end - - -- write it - ok, errors = io.file_write(self._FILE, ...) - if not ok and errors then - errors = string.format("%s: %s", self, errors) - end - return ok, errors -end - --- seek offset at file -function _file:seek(whence, offset) - - -- ensure opened - local ok, errors = self:_ensure_opened() - if not ok then - return nil, errors - end - - -- seek it - local result, errors = io.file_seek(self._FILE, whence, offset) - if not result and errors then - errors = string.format("%s: %s", self, errors) - end - return result, errors -end - --- flush data to file -function _file:flush() - - -- ensure opened - local ok, errors = self:_ensure_opened() - if not ok then - return false, errors - end - - -- flush it - ok, errors = io.file_flush(self._FILE) - if not ok and errors then - errors = string.format("%s: %s", self, errors) - end - return ok, errors -end - --- this file is a tty? -function _file:isatty() - - -- ensure opened - local ok, errors = self:_ensure_opened() - if not ok then - return false, errors - end - - -- is a tty? - ok, errors = io.file_isatty(self._FILE) - if ok == nil and errors then - errors = string.format("%s: %s", self, 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 - --- 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 - --- 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}) - diff --git a/xmake/core/base/io/filelock.lua b/xmake/core/base/io/filelock.lua deleted file mode 100644 index b4e66c7bb..000000000 --- a/xmake/core/base/io/filelock.lua +++ /dev/null @@ -1,181 +0,0 @@ ---!A cross-platform build utility based on Lua --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. --- --- Copyright (C) 2015 - 2019, TBOOX Open Source Group. --- --- @author ruki --- @file filelock.lua --- - --- define module -local io = io or {} -local _filelock = _filelock or {} - --- load modules -local path = require("base/path") -local table = require("base/table") -local string = require("base/string") - --- 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) - - -- ensure opened - local ok, errors = self:_ensure_opened() - if not ok then - return false, errors - end - - -- lock it - 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("%s: lock failed!", self) - end -end - --- try to lock file --- --- @param opt the argument option, {shared = true} --- --- @return ok, errors --- -function _filelock:trylock(opt) - - -- ensure opened - local ok, errors = self:_ensure_opened() - if not ok then - return false, errors - end - - -- unlock it - 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("%s: trylock failed!", self) - end -end - --- unlock file -function _filelock:unlock(opt) - - -- ensure opened - local ok, errors = self:_ensure_opened() - if not ok then - return false, errors - end - - -- unlock it - 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("%s: unlock failed!", self) - end -end - --- close filelock -function _filelock:close() - - -- ensure opened - local ok, errors = self:_ensure_opened() - if not ok then - return false, errors - end - - -- close filelock - ok = io.filelock_close(self._LOCK) - if ok then - self._LOCK = nil - self._LOCKED_NUM = 0 - end - return ok -end - --- ensure the filelock is opened -function _filelock:_ensure_opened() - if not self._LOCK then - return false, string.format("%s: has been closed!", self) - end - return true -end - --- tostring(filelock) -function _filelock:__tostring() - local name = self:path() - if not name or #name > 16 then - name = self:name() - end - return "<filelock: " .. 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 - --- 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 - diff --git a/xmake/core/base/io/socket.lua b/xmake/core/base/socket.lua index 13b56ecb0..97a04bb8b 100644 --- a/xmake/core/base/io/socket.lua +++ b/xmake/core/base/socket.lua @@ -19,35 +19,36 @@ -- -- define module -local io = io or {} -local _socket = _socket or {} +local io = io or {} +local socket = socket or {} +local _instance = _instance or {} -- load modules local table = require("base/table") local string = require("base/string") -- new a socket -function _socket.new(socktype, family, sock) - local socket = table.inherit(_socket) +function _instance.new(socktype, family, sock) + local socket = table.inherit(_instance) socket._SOCK = sock socket._TYPE = socktype or "tcp" socket._FAMILY = family or "ipv4" - setmetatable(socket, _socket) + setmetatable(socket, _instance) return socket end -- get socket type -function _socket:type() +function _instance:type() return self._TYPE end -- get socket family -function _socket:family() +function _instance:family() return self._FAMILY end -- get socket rawfd -function _socket:rawfd() +function _instance:rawfd() -- ensure opened local ok, errors = self:_ensure_opened() @@ -64,7 +65,7 @@ function _socket:rawfd() end -- connect socket -function _socket:connect(addr, port) +function _instance:connect(addr, port) -- ensure opened local ok, errors = self:_ensure_opened() @@ -81,7 +82,7 @@ function _socket:connect(addr, port) end -- close socket -function _socket:close() +function _instance:close() -- ensure opened local ok, errors = self:_ensure_opened() @@ -98,7 +99,7 @@ function _socket:close() end -- ensure the socket is opened -function _socket:_ensure_opened() +function _instance:_ensure_opened() if not self._SOCK then return false, string.format("%s: has been closed!", self) end @@ -106,13 +107,13 @@ function _socket:_ensure_opened() end -- tostring(socket) -function _socket:__tostring() +function _instance:__tostring() local rawfd = self:rawfd() or "closed" return string.format("<socket: %s%s/%s>", self:type(), self:family() == "ipv6" and "6" or "4", rawfd) end -- gc(socket) -function _socket:__gc() +function _instance:__gc() if self._SOCK and io.socket_close(self._SOCK) then self._SOCK = nil end @@ -125,11 +126,14 @@ end -- -- @return the socket instance -- -function io.opensock(socktype, family) +function socket.open(socktype, family) local sock, errors = io.socket_open(socktype, family) if sock then - return _socket.new(socktype, family, sock) + return _instance.new(socktype, family, sock) else return nil, errors or string.format("failed to open socket(%s/%s)!", socktype, family) end end + +-- return module +return socket diff --git a/xmake/core/sandbox/modules/import/core/base/socket.lua b/xmake/core/sandbox/modules/import/core/base/socket.lua new file mode 100644 index 000000000..3522d34d5 --- /dev/null +++ b/xmake/core/sandbox/modules/import/core/base/socket.lua @@ -0,0 +1,102 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015 - 2019, TBOOX Open Source Group. +-- +-- @author ruki +-- @file socket.lua +-- + +-- load modules +local utils = require("base/utils") +local socket = require("base/socket") +local string = require("base/string") +local raise = require("sandbox/modules/raise") + +-- define module +local sandbox_core_base_socket = sandbox_core_base_socket or {} +local sandbox_core_base_socket_instance = sandbox_core_base_socket_instance or {} + +-- connect socket +function sandbox_core_base_socket_instance.connect(sock, addr, port) + local result, errors = sock:_connect(addr, port) + if result < 0 and errors then + raise(errors) + end + return result +end + +-- get socket rawfd +function sandbox_core_base_socket_instance.rawfd(sock) + local result, errors = sock:_rawfd() + if not result then + raise(errors) + end + return result +end + +-- close socket +function sandbox_core_base_socket_instance.close(sock) + local ok, errors = sock:_close() + if not ok then + raise(errors) + end +end + +-- open socket +function sandbox_core_base_socket.open(socktype, family) + + -- open sock + local sock, errors = socket.open(socktype, family) + if not sock then + raise(errors) + end + + -- hook socket interfaces + local hooked = {} + for name, func in pairs(sandbox_core_base_socket_instance) do + if not name:startswith("_") and type(func) == "function" then + hooked["_" .. name] = sock["_" .. name] or sock[name] + hooked[name] = func + end + end + for name, func in pairs(hooked) do + sock[name] = func + end + return sock +end + +-- open tcp/ipv4 socket +function sandbox_core_base_socket.open_tcp4() + return sandbox_core_base_socket.open("tcp", "ipv4") +end + +-- open tcp/ipv6 socket +function sandbox_core_base_socket.open_tcp6() + return sandbox_core_base_socket.open("tcp", "ipv6") +end + +-- open udp/ipv4 socket +function sandbox_core_base_socket.open_udp4() + return sandbox_core_base_socket.open("udp", "ipv4") +end + +-- open udp/ipv6 socket +function sandbox_core_base_socket.open_udp6() + return sandbox_core_base_socket.open("udp", "ipv6") +end + +-- return module +return sandbox_core_base_socket + diff --git a/xmake/core/sandbox/modules/io.lua b/xmake/core/sandbox/modules/io.lua index e58b43a98..53ba52cc1 100644 --- a/xmake/core/sandbox/modules/io.lua +++ b/xmake/core/sandbox/modules/io.lua @@ -29,7 +29,6 @@ local vformat = require("sandbox/modules/vformat") local sandbox_io = sandbox_io or {} local sandbox_io_file = sandbox_io_file or {} local sandbox_io_filelock = sandbox_io_filelock or {} -local sandbox_io_socket = sandbox_io_socket or {} sandbox_io.lines = io.lines -- get file size @@ -168,32 +167,6 @@ function sandbox_io_filelock.close(lock) end end --- connect socket -function sandbox_io_socket.connect(sock, addr, port) - local result, errors = sock:_connect(addr, port) - if result < 0 and errors then - raise(errors) - end - return result -end - --- get socket rawfd -function sandbox_io_socket.rawfd(sock) - local result, errors = sock:_rawfd() - if not result then - raise(errors) - end - return result -end - --- close socket -function sandbox_io_socket.close(sock) - local ok, errors = sock:_close() - if not ok then - raise(errors) - end -end - -- gsub the given file and return replaced data function sandbox_io.gsub(filepath, pattern, replace, opt) @@ -297,29 +270,6 @@ function sandbox_io.openlock(filepath) return lock end --- open socket -function sandbox_io.opensock(socktype, family) - - -- open sock - local sock, errors = io.opensock(socktype, family) - if not sock then - raise(errors) - end - - -- hook socket interfaces - local hooked = {} - for name, func in pairs(sandbox_io_socket) do - if not name:startswith("_") and type(func) == "function" then - hooked["_" .. name] = sock["_" .. name] or sock[name] - hooked[name] = func - end - end - for name, func in pairs(hooked) do - sock[name] = func - end - return sock -end - -- load object from the given file function sandbox_io.load(filepath, opt) |
