Merge branch 'main' into animation

This commit is contained in:
MihailRis 2026-08-04 23:39:49 +03:00
commit 282c9b3de2
68 changed files with 1419 additions and 488 deletions

View file

@ -4,12 +4,14 @@ local FFI = ffi
FFI.cdef[[
void* malloc(size_t);
void* realloc(void*, size_t);
void free(void*);
typedef struct {
unsigned char* bytes;
int size;
int capacity;
} bytearray_t;
void* memmove(void*, const void*, size_t);
]]
local free = FFI.C.free
@ -22,12 +24,33 @@ local GC_THRESHOLD = 50 * 1024 * 1024
local function malloc(size)
local raw = FFI.C.malloc(size)
if raw == nil then
return nil
if not raw then
error("failed memory allocation of " .. size .. " bytes")
end
allocated_bytes = allocated_bytes + size
if allocated_bytes >= GC_THRESHOLD then
collectgarbage("step", 200)
allocated_bytes = 0
end
return raw
end
local function realloc(buff, size, throwerror)
if throwerror == nil then throwerror = true end
if size <= 0 then
free(buff)
return
end
local raw = FFI.C.realloc(buff, size)
if not raw and throwerror then
error("failed memory reallocation of block " .. buff .. " to new size " .. size)
end
allocated_bytes = allocated_bytes + size
if allocated_bytes >= GC_THRESHOLD then
collectgarbage("step", 200)
allocated_bytes = 0
@ -38,23 +61,17 @@ end
local function grow_buffer(self, elems)
local new_capacity = math.ceil(self.capacity / 0.75 + elems)
local prev = self.bytes
self.bytes = malloc(new_capacity)
FFI.copy(self.bytes, prev, self.size)
self.bytes = realloc(self.bytes, new_capacity)
self.capacity = new_capacity
free(prev)
end
local function trim_buffer(self)
if self.size == self.capacity then
return
if self.size == self.capacity then return end
local new_bytes = realloc(self.bytes, self.size, false)
if new_bytes then
self.bytes = new_bytes
self.capacity = self.size
end
local size = self.size
local prev = self.bytes
self.bytes = malloc(size)
FFI.copy(self.bytes, prev, self.size)
self.capacity = size
free(prev)
end
local function count_elements(b)
@ -125,15 +142,21 @@ local function clear(self)
self.size = 0
end
local function reserve(self, new_capacity)
if new_capacity <= self.capacity then
return
local function fill(self, index, size, byte)
if index ~= nil and size ~= nil and size > 0 then
if index < 1 or index + size - 1 > self.size then
error("selected fill range is out of array bounds")
end
FFI.fill(self.bytes + index - 1, size, byte)
else
FFI.fill(self.bytes, self.size, byte)
end
local prev = self.bytes
self.bytes = malloc(new_capacity)
FFI.copy(self.bytes, prev, self.size)
end
local function reserve(self, new_capacity)
if new_capacity <= self.capacity then return end
self.bytes = realloc(self.bytes, new_capacity)
self.capacity = new_capacity
free(prev)
end
local function get_capacity(self)
@ -150,22 +173,46 @@ local function slice(self, offset, length)
length = self.size - offset + 1
end
local buffer = malloc(length)
if not buffer then
error("malloc(" .. length .. ") returned NULL")
end
FFI.copy(buffer, self.bytes + (offset - 1), length)
return bytearray_type(buffer, length, length)
end
local function copy(self, srcindex, dst, dstindex, size)
if size <= 0 then error("size of byte range must be positive non-zero integer") end
if srcindex < 1 or srcindex + size - 1 > self.size then
error("specified source byte range is out of source array bounds")
end
if dstindex < 1 or dstindex + size - 1 > dst.size then
error("specified destination byte range is out of destination array bounds")
end
FFI.copy(dst.bytes + dstindex - 1, self.bytes + srcindex - 1, size)
end
local function move(self, fromindex, toindex, size)
if size <= 0 then error("size of byte range must be positive non-zero integer") end
if fromindex < 1 or fromindex + size - 1 > self.size then
error("specified source byte range is out of array bounds")
end
if toindex < 1 or toindex + size - 1 > self.size then
error("specified destination byte range is out of array bounds")
end
FFI.C.memmove(self.bytes + toindex - 1, self.bytes + fromindex - 1, size)
end
local bytearray_methods = {
append=append,
insert=insert,
remove=remove,
trim=trim_buffer,
clear=clear,
reserve=reserve,
get_capacity=get_capacity,
slice=slice,
append = append,
insert = insert,
remove = remove,
trim = trim_buffer,
clear = clear,
reserve = reserve,
get_capacity = get_capacity,
slice = slice,
fill = fill,
copy = copy,
move = move
}
local bytearray_mt = {
@ -256,7 +303,8 @@ local function FFIBytearray_as_string(bytes)
end
end
local function create_FFIview_class(name, typename, typesize)
local function create_FFIview_class(name, typename)
local typesize = FFI.sizeof(typename)
local ptrtype = typename .. "*"
local FFIview_mt = {
__index = function(self, key)
@ -291,27 +339,44 @@ local function create_FFIview_class(name, typename, typesize)
return i, ptr[i - 1]
end
end
end
end,
}
return function (bytes)
local x = setmetatable({
bytes=bytes,
}, FFIview_mt)
return x
end
return setmetatable({}, {
__call = function (self, bytes)
local x = setmetatable({
bytes=bytes,
}, FFIview_mt)
return x
end,
__index = {
typesize = function()
return typesize
end
}
})
end
local FFII16view = create_FFIview_class("FFII16view", "int16_t", 2)
local FFIU16view = create_FFIview_class("FFIU16view", "uint16_t", 2)
local FFII32view = create_FFIview_class("FFII32view", "int32_t", 4)
local FFIU32view = create_FFIview_class("FFIU32view", "uint32_t", 4)
local FFII8view = create_FFIview_class("FFII8view", "int8_t")
local FFII16view = create_FFIview_class("FFII16view", "int16_t")
local FFIU16view = create_FFIview_class("FFIU16view", "uint16_t")
local FFII32view = create_FFIview_class("FFII32view", "int32_t")
local FFIU32view = create_FFIview_class("FFIU32view", "uint32_t")
local FFII64view = create_FFIview_class("FFII64view", "int64_t")
local FFIU64view = create_FFIview_class("FFIU64view", "uint64_t")
local FFIFLTview = create_FFIview_class("FFIFLTview", "float")
local FFIDBLview = create_FFIview_class("FFIDBLview", "double")
return {
FFIBytearray = setmetatable(FFIBytearray, FFIBytearray),
FFIBytearray_as_string = FFIBytearray_as_string,
FFIBytearray_as_ptr = FFIBytearray_as_ptr,
FFII8view = FFII8view,
FFIU16view = FFIU16view,
FFII16view = FFII16view,
FFIU32view = FFIU32view,
FFII32view = FFII32view,
FFIU64view = FFIU64view,
FFII64view = FFII64view,
FFIFLTview = FFIFLTview,
FFIDBLview = FFIDBLview,
}

View file

@ -0,0 +1,38 @@
local FFI = ffi
FFI.cdef[[
unsigned long long strtoull(const char* nptr, char** endptr, int base);
long long strtoll(const char* nptr, char** endptr, int base);
]]
local this = {}
local function create_integral_type(ctype_name, signed)
local parse_func = signed and FFI.C.strtoll or FFI.C.strtoull
return function(value, base)
value = value or 0
local typename = type(value)
if typename == "number" then
return FFI.cast(ctype_name, value)
elseif typename == "string" then
if type(base) ~= "number" then
base = 10
end
return parse_func(value, nil, base)
end
error(string.format("invalid value type: %s", typename))
end
end
this.uint8 = create_integral_type("uint8_t", false)
this.uint16 = create_integral_type("uint16_t", false)
this.uint32 = create_integral_type("uint32_t", false)
this.uint64 = create_integral_type("uint64_t", false)
this.int8 = create_integral_type("int8_t", true)
this.int16 = create_integral_type("int16_t", true)
this.int32 = create_integral_type("int32_t", true)
this.int64 = create_integral_type("int64_t", true)
return this

View file

@ -1,4 +1,4 @@
local rules = {nexid = 1, rules = {}}
local rules = {nextid = 1, rules = {}}
function rules.get_rule(name)
local rule = rules.rules[name]
@ -27,13 +27,13 @@ end
function rules.reset(name)
local rule = rules.get_rule(name)
rules.set(rule.default)
rules.set(name, rule.default)
end
function rules.listen(name, handler)
local rule = rules.get_rule(name)
local id = rules.nexid
rules.nextid = rules.nexid + 1
local id = rules.nextid
rules.nextid = rules.nextid + 1
rule.listeners[utf8.encode(id)] = handler
return id
end