summaryrefslogtreecommitdiff
path: root/xmake/core/base/bytes.lua
diff options
context:
space:
mode:
authorruki <[email protected]>2019-11-01 00:50:39 +0800
committerruki <[email protected]>2019-10-31 23:03:54 +0800
commit56178606d872629cb3553bf912a742c84cf244e4 (patch)
treefd11ec3abab4cca7dc093f6d55b5c7c3ee40386f /xmake/core/base/bytes.lua
parent7d47837062fba756f66e7bea313cb59f9a026477 (diff)
export ffi/malloc for windows
Diffstat (limited to 'xmake/core/base/bytes.lua')
-rw-r--r--xmake/core/base/bytes.lua133
1 files changed, 113 insertions, 20 deletions
diff --git a/xmake/core/base/bytes.lua b/xmake/core/base/bytes.lua
index 9f5a9ead2..c92bb065f 100644
--- a/xmake/core/base/bytes.lua
+++ b/xmake/core/base/bytes.lua
@@ -29,46 +29,91 @@ local os = require("base/os")
-- define ffi interfaces
ffi.cdef[[
- void* malloc(size_t __size);
- void free(void *__ptr);
+ void* xm_ffi_malloc(unsigned long size);
+ void xm_ffi_free(void* data);
]]
-- new a bytes instance
--
--- new(size): allocates a buffer of given size
--- new(size, ptr [, manage]) : mounts buffer on existing storage (manage memory or not)
--- new(str): allocates a buffer from the given string
+-- bytes(size): allocates a buffer of given size
+-- bytes(size, ptr [, manage]): mounts buffer on existing storage (manage memory or not)
+-- bytes(str): mounts a buffer from the given string
+-- bytes(bytes, start, last): mounts a buffer from another one, with start/last limits
+-- bytes(bytes1, bytes2, bytes3, ...): allocates and concat buffer from list of byte buffers
+-- bytes(bytes): allocates a buffer from another one (strict replica, sharing memory)
--
-function _instance.new(arg1, arg2, arg3)
+function _instance.new(...)
+ local args = {...}
+ local arg1, arg2, arg3 = unpack(args)
local instance = table.inherit(_instance)
if type(arg1) == "number" then
local size = arg1
local ptr = arg2
if ptr then
- -- new(size, ptr [, manage]) : mounts buffer on existing storage (manage memory or not)
+ -- bytes(size, ptr [, manage]): mounts buffer on existing storage (manage memory or not)
local manage = arg3
if manage then
- instance._CDATA = ffi.gc(ffi.cast("unsigned char*", ptr), ffi.C.free)
+ instance._CDATA = ffi.gc(ffi.cast("unsigned char*", ptr), ffi.C.xm_ffi_free)
instance._MANAGED = true
else
instance._CDATA = ffi.cast("unsigned char*", ptr)
instance._MANAGED = false
end
else
- -- new(size): allocates a buffer of given size
- ptr = ffi.C.malloc(size)
- instance._CDATA = ffi.gc(ffi.cast("unsigned char*", ptr), ffi.C.free)
+ -- bytes(size): allocates a buffer of given size
+ ptr = ffi.C.xm_ffi_malloc(size)
+ instance._CDATA = ffi.gc(ffi.cast("unsigned char*", ptr), ffi.C.xm_ffi_free)
instance._MANAGED = true
end
instance._SIZE = size
elseif type(arg1) == "string" then
- -- new(str): allocates a buffer from the given string
+ -- bytes(str): mounts a buffer from the given string
local str = arg1
instance._SIZE = #str
instance._CDATA = ffi.cast("unsigned char*", str)
instance._REF = str -- keep ref for GC
instance._MANAGED = false
- else
+ elseif type(arg1) == "table" then
+ if type(arg2) == 'number' then
+ -- bytes(bytes, start, last): mounts a buffer from another one, with start/last limits:
+ local b = arg1
+ local start = arg2 or 1
+ local last = arg3 or b:size()
+ if start < 1 or last > b:size() then
+ os.raise("incorrect bounds(%d-%d) for bytes(...)!", start, last)
+ end
+ instance._SIZE = last - start + 1
+ instance._CDATA = b:cdata() - 1 + start
+ instance._REF = b -- keep lua ref for GC
+ instance._MANAGED = false
+ elseif type(arg2) == "table" then
+ -- bytes(bytes1, bytes2, bytes3, ...): allocates and concat buffer from list of byte buffers
+ instance._SIZE = 0
+ for _, b in ipairs(args) do
+ instance._SIZE = instance._SIZE + b:size()
+ end
+ instance._CDATA = ffi.gc(ffi.cast("unsigned char*", ffi.C.xm_ffi_malloc(instance._SIZE)), ffi.C.xm_ffi_free)
+ local offset = 0
+ for _, b in ipairs(args) do
+ ffi.copy(instance._CDATA + offset, b:cdata(), b:size())
+ offset = offset + b:size()
+ end
+ instance._MANAGED = true
+ elseif not arg2 and arg1:size() then
+ -- bytes(bytes): allocates a buffer from another one (strict replica, sharing memory)
+ local b = arg1
+ local start = 1
+ local last = arg3 or b:size()
+ if start < 1 or last > b:size() then
+ os.raise("incorrect bounds(%d-%d)!", start, last)
+ end
+ instance._SIZE = last - start + 1
+ instance._CDATA = b:cdata() - 1 + start
+ instance._REF = b -- keep lua ref for GC
+ instance._MANAGED = false
+ end
+ end
+ if instance:cdata() == nil then
os.raise("invalid arguments for bytes(...)!")
end
setmetatable(instance, _instance)
@@ -80,6 +125,11 @@ function _instance:size()
return self._SIZE
end
+-- get bytes data
+function _instance:cdata()
+ return self._CDATA
+end
+
-- bytes:ipairs()
function _instance:ipairs()
local index = 0
@@ -91,23 +141,59 @@ function _instance:ipairs()
end
end
--- bytes[key]
+-- get a slice of bytes
+function _instance:slice(start, last)
+ return bytes(self, start, last)
+end
+
+-- copy bytes
+function _instance:copy(src)
+ if type(src) == 'string' then
+ src = bytes(src)
+ end
+ if src:size() ~= self:size() then
+ os.raise("cannot copy bytes, src and dst must have same size(%d->%d)!", src:size(), self:size())
+ end
+ ffi.copy(self:cdata(), src:cdata(), self:size())
+ return self
+end
+
+-- clone a new bytes buffer
+function _instance:clone()
+ local new = bytes(self:size())
+ new:copy(self)
+ return new
+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)
+end
+
+-- get byte or bytes slice at the given index position
+--
+-- bytes[1]
+-- bytes[{1, 2}]
+--
function _instance:__index(key)
if type(key) == "number" then
if key < 1 or key > self:size() then
os.raise("bytes index(%d/%d) out of bounds!", key, self:size())
end
return self._CDATA[key - 1]
- --[[
elseif type(key) == "table" then
local start, last = key[1], key[2]
return self:slice(start, last)
- --]]
end
return rawget(self, key)
end
--- bytes[key] = value
+-- get byte or bytes slice at the given index position
+--
+-- bytes[1] = 0x1
+-- bytes[{1, 2}] = bytes(2)
+--
function _instance:__newindex(key, value)
if type(key) == "number" then
if key < 1 or key > self:size() then
@@ -115,15 +201,22 @@ function _instance:__newindex(key, value)
end
self._CDATA[key - 1] = value
return
- --[[
elseif type(key) == "table" then
- local start,last = key[1],key[2]
+ local start, last = key[1], key[2]
self:slice(start,last):copy(value)
- return]]
+ return
end
rawset(self, key, value)
end
+-- concat two bytes buffer
+function _instance:__concat(other)
+ local new = bytes(self:size() + other:size())
+ new:slice(1, self:size()):copy(self)
+ new:slice(self:size() + 1, new:size()):copy(other)
+ return new
+end
+
-- tostring(bytes)
function _instance:__tostring()
local parts = {}