diff --git a/dev/tests/bytearray.lua b/dev/tests/bytearray.lua index cbd537100..71e895d37 100644 --- a/dev/tests/bytearray.lua +++ b/dev/tests/bytearray.lua @@ -18,55 +18,55 @@ Bytearray.insert(arr, {5, 3, 6}) assert(#arr == 12) Bytearray.insert(arr, 2, 8) -assert(#arr == 13) +asserts.equals(13, #arr) for i=1,10 do assert(arr[i] == 10 - i) end print(#arr, arr:get_capacity()) arr:trim() -assert(#arr == arr:get_capacity()) +asserts.equals(#arr, arr:get_capacity()) arr = Bytearray({0, 2, 7, 1, 16, 75, 25}) assert(arr[6] == 75) arr:insert(2, {5, 6}) -assert(arr[#arr] == 25) -assert(arr[2] == 5) -assert(arr[3] == 6) +asserts.equals(25, arr[#arr]) +asserts.equals(5, arr[2]) +asserts.equals(6, arr[3]) -- ============================= arr = Bytearray({254, 255, 255, 255, 255, 255, 255, 255}) ---assert(U64view(arr)[1] == 2 ^ 64 - 2) -assert(I64view(arr)[1] == -2) -assert(U32view(arr)[1] == 2 ^ 32 - 2) -assert(I32view(arr)[1] == -2) -assert(U16view(arr)[1] == 2 ^ 16 - 2) -assert(I16view(arr)[1] == -2) -assert(I8view(arr)[1] == -2) +asserts.equals(U64view(arr)[1], ctypes.uint64(2) ^ 64 - 2) +asserts.equals(I64view(arr)[1], -2) +asserts.equals(U32view(arr)[1], 2 ^ 32 - 2) +asserts.equals(I32view(arr)[1], -2) +asserts.equals(U16view(arr)[1], 2 ^ 16 - 2) +asserts.equals(I16view(arr)[1], -2) +asserts.equals(I8view(arr)[1], -2) -assert(I8view(arr)[2] == -1) -assert(I32view(arr)[2] == -1) +asserts.equals(I8view(arr)[2], -1) +asserts.equals(I32view(arr)[2], -1) arr = Bytearray({0xFF, 0x7F}) local arri16 = I16view(arr) local arru16 = U16view(arr) -assert(arri16[1] == 32767) +asserts.equals(arri16[1], 32767) arru16[1] = arru16[1] + 1 -assert(arri16[1] == -32768) -assert(arru16[1] == 32768) +asserts.equals(arri16[1], -32768) +asserts.equals(arru16[1], 32768) arr = Bytearray({0x9A, 0x99, 0x59, 0x40}) -- approx. equal 3.4 in hexadecimal representation of single-precision float number. local arrflt = FLTview(arr) local arru32 = U32view(arr) -assert(arrflt[1] == 3.4000000953674316) -assert(arru32[1] == 0x4059999A) +asserts.equals(arrflt[1], 3.4000000953674316) +asserts.equals(arru32[1], 0x4059999A) arrflt[1] = arrflt[1] + 0.1 -assert(arrflt[1] == 3.5) -assert(arru32[1] == 0x40600000) -- hexadecimal representation of 3.5 single-precision float number. +asserts.equals(arrflt[1], 3.5) +asserts.equals(arru32[1], 0x40600000) -- hexadecimal representation of 3.5 single-precision float number. arr = Bytearray({0x18, 0x2D, 0x44, 0x54, 0xFB, 0x21, 9, 64}) -- hexadecimal representation of 3.141592653589793 double-precision float number. assert(DBLview(arr)[1] == 3.141592653589793) @@ -84,20 +84,20 @@ function barrtostr(barr) end arr = Bytearray({0, 5, 34, 87, 21, 0, 210}) -assert(barrtostr(arr) == "0|5|34|87|21|0|210") +asserts.equals(barrtostr(arr), "0|5|34|87|21|0|210") arr:move(2, 3, 4) -assert(barrtostr(arr) == "0|5|5|34|87|21|210") +asserts.equals(barrtostr(arr), "0|5|5|34|87|21|210") local arr2 = Bytearray({1, 2, 3, 4, 6, 7, 8}) -assert(barrtostr(arr2) == "1|2|3|4|6|7|8") +asserts.equals(barrtostr(arr2), "1|2|3|4|6|7|8") arr:copy(4, arr2, 2, 3) -assert(barrtostr(arr2) == "1|34|87|21|6|7|8") +asserts.equals(barrtostr(arr2), "1|34|87|21|6|7|8") arr:fill(nil, nil, 192) -assert(barrtostr(arr) == "192|192|192|192|192|192|192") +asserts.equals(barrtostr(arr), "192|192|192|192|192|192|192") arr:fill(nil, 3, 233) -assert(barrtostr(arr) == "233|233|233|233|233|233|233") +asserts.equals(barrtostr(arr), "233|233|233|233|233|233|233") arr:fill(2, nil, 254) -assert(barrtostr(arr) == "254|254|254|254|254|254|254") +asserts.equals(barrtostr(arr), "254|254|254|254|254|254|254") arr:fill(2, 2, 66) -assert(barrtostr(arr) == "254|66|66|254|254|254|254") \ No newline at end of file +asserts.equals(barrtostr(arr), "254|66|66|254|254|254|254") diff --git a/doc/en/scripting.md b/doc/en/scripting.md index 09cf40ef4..2072d4353 100644 --- a/doc/en/scripting.md +++ b/doc/en/scripting.md @@ -16,6 +16,7 @@ Subsections: - [block](scripting/builtins/libblock.md) - [byteutil](scripting/builtins/libbyteutil.md) - [cameras](scripting/builtins/libcameras.md) + - [ctypes](scripting/builtins/libctypes.md) - [entities](scripting/builtins/libentities.md) - [file](scripting/builtins/libfile.md) - [gfx.blockwraps](scripting/builtins/libgfx-blockwraps.md) diff --git a/doc/en/scripting/builtins/libctypes.md b/doc/en/scripting/builtins/libctypes.md new file mode 100644 index 000000000..5517af0fa --- /dev/null +++ b/doc/en/scripting/builtins/libctypes.md @@ -0,0 +1,28 @@ +# *ctypes* Library + +A library for safe work with C types. + +| ctypes.\ | C-Type | Minimum | Maximum | +| --------------- | -------- | -------------------- | -------------------- | +| uint8 | uint8_t | 0 | 255 | +| uint16 | uint16_t | 0 | 65535 | +| uint32 | uint32_t | 0 | 4294967295 | +| uint64 | uint64_t | 0 | 18446744073709551615 | +| int8 | int8_t | -128 | 127 | +| int16 | int16_t | -32768 | 32767 | +| int32 | int32_t | -2147483648 | 2147483647 | +| int64 | int64_t | -9223372036854775808 | 9223372036854775807 | + + +Usage examples: + +```lua +local x = ctypes.uint64(1234) +print(x) --> 1234ULL (cdata) +local y = ctypes.uint64("18446744073709551615") +print(y) --> 18446744073709551615ULL (cdata) +print(x + y) --> 1233ULL + +local z = tonumber(x) +print(z) --> 1234 (number) +``` diff --git a/doc/ru/scripting.md b/doc/ru/scripting.md index db3fcd921..1e6d73098 100644 --- a/doc/ru/scripting.md +++ b/doc/ru/scripting.md @@ -16,6 +16,7 @@ - [block](scripting/builtins/libblock.md) - [byteutil](scripting/builtins/libbyteutil.md) - [cameras](scripting/builtins/libcameras.md) + - [ctypes](scripting/builtins/libctypes.md) - [entities](scripting/builtins/libentities.md) - [file](scripting/builtins/libfile.md) - [gfx.blockwraps](scripting/builtins/libgfx-blockwraps.md) diff --git a/doc/ru/scripting/builtins/libctypes.md b/doc/ru/scripting/builtins/libctypes.md new file mode 100644 index 000000000..d6c985b44 --- /dev/null +++ b/doc/ru/scripting/builtins/libctypes.md @@ -0,0 +1,28 @@ +# Библиотека *ctypes* + +Библиотека для безопасной работы с типами языка С. + +| ctypes.\ | С-тип | Минимум | Максимум | +| ------------- | -------- | -------------------- | -------------------- | +| uint8 | uint8_t | 0 | 255 | +| uint16 | uint16_t | 0 | 65535 | +| uint32 | uint32_t | 0 | 4294967295 | +| uint64 | uint64_t | 0 | 18446744073709551615 | +| int8 | int8_t | -128 | 127 | +| int16 | int16_t | -32768 | 32767 | +| int32 | int32_t | -2147483648 | 2147483647 | +| int64 | int64_t | -9223372036854775808 | 9223372036854775807 | + + +Примеры использования: + +```lua +local x = ctypes.uint64(1234) +print(x) --> 1234ULL (cdata) +local y = ctypes.uint64("18446744073709551615") +print(y) --> 18446744073709551615ULL (cdata) +print(x + y) --> 1233ULL + +local z = tonumber(x) +print(z) --> 1234 (number) +``` diff --git a/res/modules/internal/bytearray.lua b/res/modules/internal/bytearray.lua index 0908b8c9a..896f43188 100644 --- a/res/modules/internal/bytearray.lua +++ b/res/modules/internal/bytearray.lua @@ -340,16 +340,20 @@ local function create_FFIview_class(name, typename) end end end, - typesize = function() - return typesize - 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 FFII8view = create_FFIview_class("FFII8view", "int8_t") diff --git a/res/modules/internal/ctypes.lua b/res/modules/internal/ctypes.lua new file mode 100644 index 000000000..032ea34b5 --- /dev/null +++ b/res/modules/internal/ctypes.lua @@ -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 diff --git a/res/scripts/stdmin.lua b/res/scripts/stdmin.lua index 196bf8942..03de8cbaa 100644 --- a/res/scripts/stdmin.lua +++ b/res/scripts/stdmin.lua @@ -322,6 +322,8 @@ FLTview = bytearray.FFIFLTview DBLview = bytearray.FFIDBLview Bytearray_construct = function(...) return Bytearray(...) end +ctypes = require "core:internal/ctypes" + bit.compile = require "core:bitwise/compiler" bit.execute = require "core:bitwise/executor"