Unexpected values from bit manipulations
I am trying to create a dynamic byte array class for Lua 5.1 / 5.2. They are a very limited server-side Lua platform in a Flash game, they allow me to do nothing else while executing one source code.
Each byte is denoted by 8 bits inside a number that is inside a table of numbers.
I am temporarily testing it by trying to write a string ( 'abc'
), pass my bytes to a byte array, but when checking for the appropriate number of those bytes, its value is incorrect. It should be 0x636261
(because it a
is 0x61
), but as a result it is actually 6300000
.
local arr = bytearray:new('abc', 5);
print(arr[LK_Stack][1]);
I am using a maximum of 7 bytes from the stack number (56 bits). I got an adaptive bitwise AND function from this answer for testing over 32 bits. I am trying to use the library bit32
where possible.
This is temporary as I implement my byte read and write functions that work on a specific number from the byte array stack. The write function should return the stack number back to the changed state.
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
And this is my complete current code.
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
source to share
No one has answered this question yet
See similar questions:
or similar: