Lua, work with byte streams without ascii, byte change

It is necessary to encode and decode a byte stream (possibly containing characters without ascii), from / to uint16, uint32, uint64 (their typical C / C ++ value), taking care of the content. What is an efficient and hopefully cross-platform way to do this in Lua?

My target arch is 64-bit x86_64, but I would like to keep it portable (if it doesn't cost me performance).

eg.

decode (say, currently in the Lua line) - 0x00, 0x1d, 0xff, 0x23, 0x44, 0x32 (small number) in the form - uint16: (0x1d00) = 7424 uint32: (0x324423ff) = 843326463

It would be great if someone could explain an example.

+4
source share
3 answers

Take a look at struct and lpack .

In this example, I use struct.unpack to decode a Lua string into two integers with a little-endian forced encoding:

 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 
+4
source

for converting from bytes to int (care at the byte and signature level):

 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 

And while we are in this other direction:

 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 

Any comments are welcome, they are checked, but not too carefully ...

+6
source

my suggestion for the "Int16ToByte" function without checking the parameters:

 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 
0
source

Source: https://habr.com/ru/post/1342942/


All Articles