summaryrefslogtreecommitdiff
path: root/xmake/core/base/bytes.lua
diff options
context:
space:
mode:
authorruki <[email protected]>2019-10-31 21:04:32 +0800
committerruki <[email protected]>2019-10-31 00:27:17 +0800
commit7d47837062fba756f66e7bea313cb59f9a026477 (patch)
tree1faef02540808728046c67d23c874f6118a0c774 /xmake/core/base/bytes.lua
parent057e930e41972cc5ee1812d16792dc6f6945279d (diff)
impl bytes index and ipairs
Diffstat (limited to 'xmake/core/base/bytes.lua')
-rw-r--r--xmake/core/base/bytes.lua123
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