diff options
| author | ruki <[email protected]> | 2019-11-01 00:50:39 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2019-10-31 23:03:54 +0800 |
| commit | 56178606d872629cb3553bf912a742c84cf244e4 (patch) | |
| tree | fd11ec3abab4cca7dc093f6d55b5c7c3ee40386f /xmake/core/base/bytes.lua | |
| parent | 7d47837062fba756f66e7bea313cb59f9a026477 (diff) | |
export ffi/malloc for windows
Diffstat (limited to 'xmake/core/base/bytes.lua')
| -rw-r--r-- | xmake/core/base/bytes.lua | 133 |
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 = {} |
