需要编码&解码字节流(可能包含非ascii字符),来自/进入uint16,uint32,uint64(它们的典型C / C ++含义),处理字节序。什么是有效的&希望跨平台的方式在Lua做这样的事情?
我的目标arch是64位x86_64,但是想保持它的可移植性(如果它在性能方面没有花费我的成本)。
e.g。
解码(比如当前在Lua字符串中) - 0x00,0x1d,0xff,0x23,0x44,0x32(小端) 作为 - uint16:(0x1d00)= 7424 uint32:(0x324423ff)= 843326463
如果有人可以用一个例子来解释,那会很棒。
答案 0 :(得分:6)
用于从bytes转换为int(处理字节级别的endianness和signedness):
function bytes_to_int(str,endian,signed) -- use length of string to determine 8,16,32,64 bits
local t={str:byte(1,-1)}
if endian=="big" then --reverse bytes
local tt={}
for k=1,#t do
tt[#t-k+1]=t[k]
end
t=tt
end
local n=0
for k=1,#t do
n=n+t[k]*2^((k-1)*8)
end
if signed then
n = (n > 2^(#t*8-1) -1) and (n - 2^(#t*8)) or n -- if last bit set, negative.
end
return n
end
虽然我们也在另一个方向:
function int_to_bytes(num,endian,signed)
if num<0 and not signed then num=-num print"warning, dropping sign from number converting to unsigned" end
local res={}
local n = math.ceil(select(2,math.frexp(num))/8) -- number of bytes to be used.
if signed and num < 0 then
num = num + 2^n
end
for k=n,1,-1 do -- 256 = 2^8 bits per char.
local mul=2^(8*(k-1))
res[k]=math.floor(num/mul)
num=num-res[k]*mul
end
assert(num==0)
if endian == "big" then
local t={}
for k=1,n do
t[k]=res[n-k+1]
end
res=t
end
return string.char(unpack(res))
end
欢迎任何评论,经过测试,但不是太彻底......
答案 1 :(得分:4)
在这个例子中,我使用struct.unpack
将Lua字符串解码为带有强制little-endian编码的两个整数:
require 'struct'
-- convert character codes to a Lua string - this may come from your source
local str = string.char(0x00, 0x1d, 0xff, 0x23, 0x44, 0x32)
-- format string: < = little endian, In = unsigned int (n bytes)
local u16, u32 = struct.unpack('<I2I4', str)
print(u16, u32) --> 7424 843326463
答案 2 :(得分:0)
我对&#34; Int16ToByte&#34; -function的建议没有检查参数:
function Int16ToBytes(num, endian)
if num < 0 then
num = num & 0xFFFF
end
highByte = (num & 0xFF00) >> 8
lowByte = num & 0xFF
if endian == "little" then
lowByte, highByte = highByte, lowByte
end
return string.char(highByte,lowByte)
end