我正在尝试为Lua 5.1 / 5.2构建动态字节数组类。它是Flash游戏中非常有限的Lua服务器平台,它们允许我在执行单个源代码时不做任何其他事情。
每个字节在数字表内的数字内用8位表示。
我通过尝试写一个字符串('abc'
)暂时测试它,将其字节传递给字节数组,但是当检查这些字节的相应数量时,它的值是错误的。它应该是0x636261
(因为a
是0x61
),但实际上会产生6300000
。
local arr = bytearray:new('abc', 5);
print(arr[LK_Stack][1]);
我最多使用堆栈号(56位)的7个字节。我从this回答得到了一个自适应按位AND函数,用于检查32位。我尝试尽可能使用bit32
库。
这暂时是我如何实现字节读取和写入函数,这些函数对字节数组的堆栈中的特定数字进行操作。写入功能必须以更改状态返回堆栈编号。
local Opr_readByte;
local Opr_writeByte;
if _16 then
-- ...
else
function Opr_readByte(n, bit)
if bit == 48 then
local add = band(n, 4) > 0xB;
return floor(n / (add and 0x1000000000001 or 0x1000000000000));
end
if bit == 40 then return band(floor(n / 0x10000000000), 0xFF); end
if bit == 32 then return band(floor(n / 0x100000000), 0xFF); end
if bit == 24 then return band(floor(n / 0x100000000), 0xFF); end
if bit == 16 then return band(rshift(n, 16), 0xFF); end
if bit == 8 then return band(rshift(n, 8), 0xFF); end
return band(n, 0xFF);
end
function Opr_writeByte(n, bit, val)
if bit == 48 then return (val * 0x1000000000000) + Opr_band56(n, 0xFFFFFFFFFFFF); end
if bit == 40 then return (val * 0x10000000000) + Opr_band56(n, 0xFF00FFFFFFFFFF); end
if bit == 32 then return (val * 0x100000000) + Opr_band56(n, 0xFFFF00FFFFFFFF); end
if bit == 24 then return (val * 0x1000000) + Opr_band56(n, 0xFFFFFF00FFFFFF); end
if bit == 16 then return (val * 0x10000) + Opr_band56(n, 0xFFFFFFFF00FFFF); end
if bit == 8 then return (val * 0x100) + Opr_band56(n, 0xFFFFFFFFFF00FF); end
return val + Opr_band56(n, 0xFFFFFFFFFFFF00);
end
end
这是我目前的完整代码。
do
--[=[ pre-locals BEGIN ]=]
local band = bit32.band;
local lshift = bit32.lshift;
local rshift = bit32.rshift;
local floor = math.floor;
local min = math.min;
local byte = string.byte;
local getmetatable = getmetatable;
local setmetatable = setmetatable;
local tonumber = tonumber;
local type = type;
local BIT5 = (0x7FFFFFFF + 1) == 0x7FFFFFFF and 16 or 48;
local _16 = BIT5 == 16;
local BYTE5 = _16 and 4 or 7;
--[=[ pre-locals END ]=]
--[=[ Tracker BEGIN ]=]
--[=[
* *****
* Offset indices consist of [[number index]] and [[bit index]].
* *****]=]
local function Tracker_backward(x, y)
if y <= 0 then return x - 1, BIT5 end
return x, y - 8;
end
local function Tracker_forward(x, y)
if y >= BIT5 then return x + 1, 0 end
return x, y + 8;
end
local function Tracker_track(x, y, yx, yy)
while y < x do yx, yy = Tracker_forward(yx, yy); y = y + 1; end
while y > x do yx, yy = Tracker_backward(yx, yy); y = y - 1; end
return yx, yy;
end
local function Tracker_optimalIndexFor(target, x, xx, xy, y, yx, yy)
local zx = target > x and target - x or x - target;
local zy = target > y and target - y or y - target;
local optimal = min(zx, zy, target);
if optimal == zx then return xx, xy; end
if optimal == zy then return yx, yy; end
return 1, 0;
end
--[=[ Tracker END ]=]
--[=[ Opr BEGIN ]=]
local Opr_readByte
, Opr_writeByte;
if _16 then
function Opr_readByte(n, bit)
if bit == 16 then return rshift(n, 16); end
if bit == 8 then return band(rshift(n, 8), 0xFF); end
return band(n, 0xFF);
end
function Opr_writeByte(n, bit, val)
if bit == 16 then return lshift(val, 16) + band(n, 0xFFFF); end
if bit == 8 then return lshift(val, 8) + band(n, 0xFF00FF); end
return val + band(n, 0xFFFF00);
end
else
local function Opr_band56(x, y)
local xl = x % 0x10000000000;
local yl = y % 0x10000000000;
local xh = (x - xl) / 0x10000000000;
local yh = (y - yl) / 0x10000000000;
return band(xh, yh) * 0x10000000000 + band(xl, yl);
end
function Opr_readByte(n, bit)
if bit == 48 then
local add = band(n, 4) > 0xB;
return floor(n / (add and 0x1000000000001 or 0x1000000000000));
end
if bit == 40 then return band(floor(n / 0x10000000000), 0xFF); end
if bit == 32 then return band(floor(n / 0x100000000), 0xFF); end
if bit == 24 then return band(floor(n / 0x100000000), 0xFF); end
if bit == 16 then return band(rshift(n, 16), 0xFF); end
if bit == 8 then return band(rshift(n, 8), 0xFF); end
return band(n, 0xFF);
end
function Opr_writeByte(n, bit, val)
if bit == 48 then return (val * 0x1000000000000) + Opr_band56(n, 0xFFFFFFFFFFFF); end
if bit == 40 then return (val * 0x10000000000) + Opr_band56(n, 0xFF00FFFFFFFFFF); end
if bit == 32 then return (val * 0x100000000) + Opr_band56(n, 0xFFFF00FFFFFFFF); end
if bit == 24 then return (val * 0x1000000) + Opr_band56(n, 0xFFFFFF00FFFFFF); end
if bit == 16 then return (val * 0x10000) + Opr_band56(n, 0xFFFFFFFF00FFFF); end
if bit == 8 then return (val * 0x100) + Opr_band56(n, 0xFFFFFFFFFF00FF); end
return val + Opr_band56(n, 0xFFFFFFFFFFFF00);
end
end
--[=[ Opr END ]=]
local LK_Stack = false;
local LK_TrackX = true;
local LK_TrackXX = 0;
local LK_TrackXY = 1;
local LK_Length = 2;
local LK_Use_Le = 3;
local LK_OfsLength = 4;
local function resize(stack, x, y)
if x < y then
for i = x + 1, y do stack[i] = nil; end
return;
end
for i = y + 1, x do stack[i] = 0; end
end
local t = {};
do
local metatable = {};
local prototype = {};
local function bytearray(_, arg, n)
local stack = {};
local arr = setmetatable({
[ LK_Stack ] = stack,
[ LK_TrackX ] = 1,
[ LK_TrackXX] = 1,
[ LK_TrackXY ] = 0,
[ LK_Use_Le ] = true
}, metatable);
local _type = type(arg);
local isNum = _type == 'number';
local blen = not isNum and #arg;
local len = tonumber(isNum and arg or (n or blen)) or 0;
local ld = floor((len / BYTE5) + 1);
arr[LK_Length] = len;
resize(stack, ld, 0);
arr[LK_OfsLength] = ld;
if not isNum then
blen = blen % (len + 1);
if _type == 'string' then arg = { byte(arg, 1, blen) }; end
local n, x, y = 0, 1, 0;
for i = 1, blen do
n = Opr_writeByte(n, y, arg[i]);
local xsav = x;
x, y = Tracker_forward(x, y);
if x ~= xsav then stack[xsav] = n; n = 0; end
end
stack[x] = n;
end
return arr;
end
local prototype = {};
function prototype:getlength()
return self[LK_Length];
end
function prototype:setlength(len)
resize(self[LK_Stack], len, self[LK_Length]);
self[LK_Length] = len;
end
metatable.__index = prototype;
t.new = bytearray;
end
bytearray = t;
local arr = bytearray:new('abc', 5);
print(arr[LK_Stack][1]);
end