Read Write Format |
|
This function fails for negative singed values i.e. -86000 !
-- This format function packs a list of integers into a binary string. -- The sizes of the integers can be specified, both little and big endian -- ordering are supported. The format parameter is a string composed of -- ASCII digit numbers, the size in bytes of the corresponding value. -- Example: -- write_format(true, "421", 0x12345678, 0x432931, 0x61) returns "xV41)a", -- a 7 bytes string whose characters are in hex: 78 56 34 12 31 29 61 function write_format(little_endian, format, ...) local res = '' local values = {...} for i=1,#format do local size = tonumber(format:sub(i,i)) local value = values[i] local str = "" for j=1,size do str = str .. string.char(value % 256) value = math.floor(value / 256) end if not little_endian then str = string.reverse(str) end res = res .. str end return res end -- This format function does the inverse of write_format. It unpacks a binary -- string into a list of integers of specified size, supporting big and little -- endian ordering. Example: -- read_format(true, "421", "xV4.1)a") returns 0x12345678, 0x2931 and 0x61. function read_format(little_endian, format, str) local idx = 0 local res = {} for i=1,#format do local size = tonumber(format:sub(i,i)) local val = str:sub(idx+1,idx+size) local value = 0 idx = idx + size if little_endian then val = string.reverse(val) end for j=1,size do value = value * 256 + val:byte(j) end res[i] = value end return unpack(res) end
This functions fail for negative singed values i.e. -86000 !
Another way to read and write integers, written by Tom N Harris.
-- Read an integer in LSB order. function stringtonumber(str) local function _b2n(exp, num, digit, ...) if not digit then return num end return _b2n(exp*256, num + digit*exp, ...) end return _b2n(256, string.byte(str, 1, -1)) end -- Read an integer in MSB order. function stringtonumber(str) local function _b2n(num, digit, ...) if not digit then return num end return _b2n(num*256 + digit, ...) end return _b2n(0, string.byte(str, 1, -1)) end -- Write an integer in LSB order using width bytes. function numbertobytes(num, width) local function _n2b(width, num, rem) rem = rem * 256 if width == 0 then return rem end return rem, _n2b(width-1, math.modf(num/256)) end return string.char(_n2b(width-1, math.modf(num/256))) end -- Write an integer in MSB order using width bytes. function numbertobytes(num, width) local function _n2b(t, width, num, rem) if width == 0 then return table.concat(t) end table.insert(t, 1, string.char(rem * 256)) return _n2b(t, width-1, math.modf(num/256)) end return _n2b({}, width, math.modf(num/256)) end
function unpackbits(bits, width) local fl = {} local num,rem = flags for i = 1,width do num,rem = math.modf(num/2) fl[#fl+1] = rem>=0.5 end return unpack(fl) end
function convertfloat(str) -- Change to b4,b3,b2,b1 to unpack an LSB float local b1,b2,b3,b4 = string.byte(str, 1, 4) local exponent = (b1 % 128) * 2 + math.floor(b2 / 128) if exponent == 0 then return 0 end local sign = (b1 > 127) and -1 or 1 local mantissa = ((b2 % 128) * 256 + b3) * 256 + b4 mantissa = (math.ldexp(mantissa, -23) + 1) * sign return math.ldexp(mantissa, exponent - 127) end
Original citation, Sirmabus: September 13, 2009