diff options
| author | ruki <[email protected]> | 2019-10-31 21:04:32 +0800 |
|---|---|---|
| committer | ruki <[email protected]> | 2019-10-31 00:27:17 +0800 |
| commit | 7d47837062fba756f66e7bea313cb59f9a026477 (patch) | |
| tree | 1faef02540808728046c67d23c874f6118a0c774 /xmake/core/base/bytes.lua | |
| parent | 057e930e41972cc5ee1812d16792dc6f6945279d (diff) | |
impl bytes index and ipairs
Diffstat (limited to 'xmake/core/base/bytes.lua')
| -rw-r--r-- | xmake/core/base/bytes.lua | 123 |
1 files changed, 116 insertions, 7 deletions
diff --git a/xmake/core/base/bytes.lua b/xmake/core/base/bytes.lua index 38f79c324..9f5a9ead2 100644 --- a/xmake/core/base/bytes.lua +++ b/xmake/core/base/bytes.lua @@ -23,21 +23,130 @@ local bytes = bytes or {} local _instance = _instance or {} -- load modules -local bit = require('bit') -local ffi = require('ffi') -local string = require("base/string") +local bit = require('bit') +local ffi = require('ffi') +local os = require("base/os") + +-- define ffi interfaces +ffi.cdef[[ + void* malloc(size_t __size); + void free(void *__ptr); +]] -- new a bytes instance -function _instance.new(size) - local instance = table.inherit(_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 +-- +function _instance.new(arg1, arg2, arg3) + 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) + local manage = arg3 + if manage then + instance._CDATA = ffi.gc(ffi.cast("unsigned char*", ptr), ffi.C.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) + instance._MANAGED = true + end + instance._SIZE = size + elseif type(arg1) == "string" then + -- new(str): allocates 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 + os.raise("invalid arguments for bytes(...)!") + end setmetatable(instance, _instance) return instance end --- new an instance -function bytes.new(str_or_size) +-- get bytes size +function _instance:size() + return self._SIZE +end +-- bytes:ipairs() +function _instance:ipairs() + local index = 0 + return function (...) + if index < self:size() then + index = index + 1 + return index, self[index] + end + end end +-- bytes[key] +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 +function _instance:__newindex(key, value) + 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 + self._CDATA[key - 1] = value + return + --[[ + elseif type(key) == "table" then + local start,last = key[1],key[2] + self:slice(start,last):copy(value) + return]] + end + rawset(self, key, value) +end + +-- tostring(bytes) +function _instance:__tostring() + local parts = {} + for i = 1, tonumber(self:size()) do + parts[i] = bit.tohex(self[i], 2) + end + return "<bytes: " .. table.concat(parts, " ") .. ">" +end + +-- new an bytes instance +function bytes.new(...) + return _instance.new(...) +end + +-- register call function +setmetatable(bytes, { + __call = function (_, ...) + return bytes.new(...) + end, + __tostring = function() + return "<bytes>" + end +}) + -- return module: bytes return bytes |
