diff options
| author | ruki <[email protected]> | 2021-09-21 00:25:24 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2021-09-21 00:25:24 +0800 |
| commit | 1e14751dcb53640e9592be678e3ebf6a46d611e1 (patch) | |
| tree | 864f09358840610ac892790fa1e09f7d945b38f8 | |
| parent | 07a9a02dbd44f4d58cdb704c6db23f5e62fd2ccf (diff) | |
improve bytes for lua
| -rw-r--r-- | core/src/xmake/engine.c | 2 | ||||
| -rw-r--r-- | core/src/xmake/libc/strndup.c | 58 | ||||
| -rw-r--r-- | core/src/xmake/makefile | 3 | ||||
| -rw-r--r-- | xmake/core/base/bytes.lua | 15 | ||||
| -rw-r--r-- | xmake/core/base/libc.lua | 33 |
5 files changed, 91 insertions, 20 deletions
diff --git a/core/src/xmake/engine.c b/core/src/xmake/engine.c index 5ca1d90f0..e8f774327 100644 --- a/core/src/xmake/engine.c +++ b/core/src/xmake/engine.c @@ -226,6 +226,7 @@ tb_int_t xm_libc_malloc(lua_State* lua); tb_int_t xm_libc_free(lua_State* lua); tb_int_t xm_libc_memcpy(lua_State* lua); tb_int_t xm_libc_memset(lua_State* lua); +tb_int_t xm_libc_strndup(lua_State* lua); tb_int_t xm_libc_dataptr(lua_State* lua); tb_int_t xm_libc_ptraddr(lua_State* lua); @@ -427,6 +428,7 @@ static luaL_Reg const g_libc_functions[] = , { "free", xm_libc_free } , { "memcpy", xm_libc_memcpy } , { "memset", xm_libc_memset } +, { "strndup", xm_libc_strndup } , { "dataptr", xm_libc_dataptr } , { "ptraddr", xm_libc_ptraddr } , { tb_null, tb_null } diff --git a/core/src/xmake/libc/strndup.c b/core/src/xmake/libc/strndup.c new file mode 100644 index 000000000..e0e1a1e02 --- /dev/null +++ b/core/src/xmake/libc/strndup.c @@ -0,0 +1,58 @@ +/*!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-present, TBOOX Open Source Group. + * + * @author ruki + * @file strndup.c + * + */ + +/* ////////////////////////////////////////////////////////////////////////////////////// + * trace + */ +#define TB_TRACE_MODULE_NAME "strndup" +#define TB_TRACE_MODULE_DEBUG (0) + +/* ////////////////////////////////////////////////////////////////////////////////////// + * includes + */ +#include "prefix.h" + +/* ////////////////////////////////////////////////////////////////////////////////////// + * implementation + */ +tb_int_t xm_libc_strndup(lua_State* lua) +{ + // check + tb_assert_and_check_return_val(lua, 0); + + // check arguments? + if (!xm_lua_ispointer(lua, 1) || !xm_lua_ispointer(lua, 2) || !lua_isnumber(lua, 3)) + xm_libc_return_error(lua, "strndup(invalid args)!"); + + // do strndup + tb_char_t const* s = tb_null; + if (xm_lua_ispointer(lua, 1)) + s = (tb_char_t const*)xm_lua_topointer(lua, 1); + else if (lua_isstring(lua, 2)) + s = lua_tostring(lua, 2); + else xm_libc_return_error(lua, "strndup(invalid args)!"); + tb_int_t n = (tb_int_t)lua_tointeger(lua, 2); + if (s && n >= 0) + lua_pushlstring(lua, s, n); + else lua_pushliteral(lua, ""); + return 1; +} + diff --git a/core/src/xmake/makefile b/core/src/xmake/makefile index 94df3a3e8..ae623c979 100644 --- a/core/src/xmake/makefile +++ b/core/src/xmake/makefile @@ -121,7 +121,8 @@ xmake_C_FILES += \ libc/memset \ libc/memcpy \ libc/dataptr \ - libc/ptraddr + libc/ptraddr \ + libc/strndup iswin = ifeq ($(PLAT),windows) diff --git a/xmake/core/base/bytes.lua b/xmake/core/base/bytes.lua index 8b2fa08cc..55c08e774 100644 --- a/xmake/core/base/bytes.lua +++ b/xmake/core/base/bytes.lua @@ -24,7 +24,6 @@ local _instance = _instance or {} -- load modules local bit = require("base/bit") -local ffi = xmake._LUAJIT and require("ffi") or nil local os = require("base/os") local utils = require("base/utils") local todisplay = require("base/todisplay") @@ -52,7 +51,7 @@ function _instance.new(...) local ptr = arg2 local manage = arg3 if manage then - instance._CDATA = ffi.gc(libc.dataptr(ptr), ffi.C.free) + instance._CDATA = libc.dataptr(ptr, {gc = true}) instance._MANAGED = true else instance._CDATA = libc.dataptr(ptr) @@ -70,7 +69,7 @@ function _instance.new(...) os.raise("invalid arguments #2 for bytes(size, ...), cdata, string, number or nil expected!") end end - local ptr = libc.gcmalloc(size) + local ptr = libc.malloc(size, {gc = true}) if init then libc.memset(ptr, init, size) end @@ -107,7 +106,7 @@ function _instance.new(...) for _, b in ipairs(args) do instance._SIZE = instance._SIZE + b:size() end - instance._CDATA = libc.gcmalloc(instance._SIZE) + instance._CDATA = libc.malloc(instance._SIZE, {gc = true}) local offset = 0 for _, b in ipairs(args) do libc.memcpy(instance._CDATA + offset, b:cdata(), b:size()) @@ -122,7 +121,7 @@ function _instance.new(...) for _, b in ipairs(args) do instance._SIZE = instance._SIZE + b:size() end - instance._CDATA = libc.gcmalloc(instance._SIZE) + instance._CDATA = libc.malloc(instance._SIZE, {gc = true}) local offset = 0 for _, b in ipairs(args) do libc.memcpy(instance._CDATA + offset, b._CDATA, b:size()) @@ -325,7 +324,7 @@ end -- convert bytes to string function _instance:str(i, j) local offset = i and i - 1 or 0 - return ffi.string(self:cdata() + offset, (j or self:size()) - offset) + return libc.strndup(self:cdata() + offset, (j or self:size()) - offset) end -- get uint8 value @@ -451,6 +450,10 @@ end -- it's only called for lua runtime, because bytes is not userdata function _instance:__gc() print("gc") + if self._MANAGED and self._CDATA then + libc.free(self._CDATA) + self._CDATA = nil + end end -- new an bytes instance diff --git a/xmake/core/base/libc.lua b/xmake/core/base/libc.lua index 20caff02b..1954f0fb1 100644 --- a/xmake/core/base/libc.lua +++ b/xmake/core/base/libc.lua @@ -40,23 +40,18 @@ if ffi then ]] end -function libc.malloc(size) +function libc.malloc(size, opt) if ffi then - return ffi.cast("unsigned char*", ffi.C.malloc(size)) + if opt and opt.gc then + return ffi.gc(ffi.cast("unsigned char*", ffi.C.malloc(size)), ffi.C.free) + else + return ffi.cast("unsigned char*", ffi.C.malloc(size)) + end else return libc._malloc(size) end end -function libc.gcmalloc(size) - if ffi then - return ffi.gc(ffi.cast("unsigned char*", ffi.C.malloc(size)), ffi.C.free) - else - -- @note we need free it in lua/__gc manually - return libc._malloc(size) - end -end - function libc.free(data) if ffi then return ffi.C.free(data) @@ -81,9 +76,21 @@ function libc.memset(data, ch, size) end end -function libc.dataptr(data) +function libc.strndup(s, n) + if ffi then + return ffi.string(s, n) + else + return libc._strndup(s, n) + end +end + +function libc.dataptr(data, opt) if ffi then - return ffi.cast("unsigned char*", data) + if opt and opt.gc then + return ffi.gc(ffi.cast("unsigned char*", data), ffi.C.free) + else + return ffi.cast("unsigned char*", data) + end else return libc._dataptr(data) end |
