Add float and double support for struct
@edubart suggested it would be still better to have it done within C as extra module (just like lbitlib). "f" a float (4 bytes). "d" a double (8 bytes). http://en.wikipedia.org/wiki/IEEE_floating_point
This commit is contained in:
		
							parent
							
								
									7ea6c46b2c
								
							
						
					
					
						commit
						48fefb03cb
					
				|  | @ -1,7 +1,7 @@ | |||
| Struct = {} | ||||
| 
 | ||||
| function Struct.pack(format, ...) | ||||
|   local stream = '' | ||||
|   local stream = {} | ||||
|   local vars = {...} | ||||
|   local endianness = true | ||||
| 
 | ||||
|  | @ -11,35 +11,78 @@ function Struct.pack(format, ...) | |||
|     if opt == '<' or opt == '>' then | ||||
|       endianness = opt == '<' and true or false | ||||
|     elseif opt == 'b' or opt == 'B' or opt == 'h' or opt == 'H' or opt == 'i' or opt == 'I' or opt == 'l' or opt == 'L' then | ||||
|       local val = tonumber(table.remove(vars, 1)) | ||||
|       local n = ((opt == 'h' or opt == 'H') and 2) or ((opt == 'i' or opt == 'I') and 4) or ((opt == 'l' or opt == 'L') and 8) or 1 | ||||
|       local val = tonumber(table.remove(vars, 1)) | ||||
| 
 | ||||
|       if val < 0 then | ||||
|         val = val + 2 ^ (n * 8 - 1) | ||||
|       end | ||||
| 
 | ||||
|       local binary = '' | ||||
|       local bytes = {} | ||||
|       for j = 1, n do | ||||
|         binary = binary .. string.char(val % (2 ^ 8)) | ||||
|         table.insert(bytes, string.char(val % (2 ^ 8))) | ||||
|         val = math.floor(val / (2 ^ 8)) | ||||
|       end | ||||
| 
 | ||||
|       if not endianness then | ||||
|         binary = string.reverse(binary) | ||||
|         table.insert(stream, string.reverse(table.concat(bytes))) | ||||
|       else | ||||
|         table.insert(stream, table.concat(bytes)) | ||||
|       end | ||||
|     elseif opt == 'f' or opt == 'd' then | ||||
|       local val = tonumber(table.remove(vars, 1)) | ||||
|       local sign = 0 | ||||
| 
 | ||||
|       if val < 0 then | ||||
|         sign = 1  | ||||
|         val = -val  | ||||
|       end | ||||
| 
 | ||||
|       stream = stream .. binary | ||||
|       local mantissa, exponent = math.frexp(val) | ||||
|       if val == 0 then | ||||
|         mantissa = 0 | ||||
|         exponent = 0 | ||||
|       else | ||||
|         mantissa = (mantissa * 2 - 1) * math.ldexp(0.5, (opt == 'd') and 53 or 24) | ||||
|         exponent = exponent + ((opt == 'd') and 1022 or 126) | ||||
|       end | ||||
| 
 | ||||
|       local bytes = {} | ||||
|       if opt == 'd' then | ||||
|         val = mantissa | ||||
|         for i = 1, 6 do | ||||
|           table.insert(bytes, string.char(math.floor(val) % (2 ^ 8))) | ||||
|           val = math.floor(val / (2 ^ 8)) | ||||
|         end | ||||
|       else | ||||
|         table.insert(bytes, string.char(math.floor(mantissa) % (2 ^ 8))) | ||||
|         val = math.floor(mantissa / (2 ^ 8)) | ||||
|         table.insert(bytes, string.char(math.floor(val) % (2 ^ 8))) | ||||
|         val = math.floor(val / (2 ^ 8)) | ||||
|       end | ||||
| 
 | ||||
|       table.insert(bytes, string.char(math.floor(exponent * ((opt == 'd') and 16 or 128) + val) % (2 ^ 8))) | ||||
|       val = math.floor((exponent * ((opt == 'd') and 16 or 128) + val) / (2 ^ 8)) | ||||
|       table.insert(bytes, string.char(math.floor(sign * 128 + val) % (2 ^ 8))) | ||||
|       val = math.floor((sign * 128 + val) / (2 ^ 8)) | ||||
| 
 | ||||
|       if not endianness then | ||||
|         table.insert(stream, string.reverse(table.concat(bytes))) | ||||
|       else | ||||
|         table.insert(stream, table.concat(bytes)) | ||||
|       end | ||||
|     elseif opt == 's' then | ||||
|       stream = stream .. tostring(table.remove(vars, 1)) | ||||
|       stream = stream .. string.char(0) | ||||
|       table.insert(stream, tostring(table.remove(vars, 1))) | ||||
|       table.insert(stream, string.char(0)) | ||||
|     end | ||||
|   end | ||||
| 
 | ||||
|   return stream | ||||
|   return table.concat(stream) | ||||
| end | ||||
| 
 | ||||
| function Struct.unpack(format, stream) | ||||
|   local vars = {} | ||||
|   local iterator = 1 | ||||
|   local endianness = true | ||||
| 
 | ||||
|   for i = 1, string.len(format) do | ||||
|  | @ -53,13 +96,13 @@ function Struct.unpack(format, stream) | |||
| 
 | ||||
|       local val = 0 | ||||
|       for j = 1, n do | ||||
|         local byte = string.byte(string.sub(stream, 1, 1)) | ||||
|         local byte = string.byte(string.sub(stream, iterator, iterator)) | ||||
|         if endianness then | ||||
|           val = val + byte * (2 ^ ((j - 1) * 8)) | ||||
|         else | ||||
|           val = val + byte * (2 ^ ((n - j) * 8)) | ||||
|         end | ||||
|         stream = string.sub(stream, 2) | ||||
|         iterator = iterator + 1 | ||||
|       end | ||||
| 
 | ||||
|       if signed then | ||||
|  | @ -67,17 +110,44 @@ function Struct.unpack(format, stream) | |||
|       end | ||||
| 
 | ||||
|       table.insert(vars, val) | ||||
|     elseif opt == 'f' or opt == 'd' then | ||||
|       local n = (opt == 'd') and 8 or 4 | ||||
|       local x = string.sub(stream, iterator, iterator + n - 1) | ||||
|       iterator = iterator + n | ||||
| 
 | ||||
|       if not endianness then | ||||
|         x = string.reverse(x) | ||||
|       end | ||||
| 
 | ||||
|       local sign = 1 | ||||
|       local mantissa = string.byte(x, (opt == 'd') and 7 or 3) % ((opt == 'd') and 16 or 128) | ||||
|       for i = n - 2, 1, -1 do | ||||
|         mantissa = mantissa * (2 ^ 8) + string.byte(x, i) | ||||
|       end | ||||
| 
 | ||||
|       if string.byte(x, n) > 127 then | ||||
|         sign = -1 | ||||
|       end | ||||
| 
 | ||||
|       local exponent = (string.byte(x, n) % 128) * ((opt == 'd') and 16 or 2) + math.floor(string.byte(x, n - 1) / ((opt == 'd') and 16 or 128)) | ||||
|       if exponent == 0 then | ||||
|         table.insert(vars, 0.0) | ||||
|       else | ||||
|         mantissa = (math.ldexp(mantissa, (opt == 'd') and -52 or -23) + 1) * sign | ||||
|         table.insert(vars, math.ldexp(mantissa, exponent - ((opt == 'd') and 1023 or 127))) | ||||
|       end | ||||
|     elseif opt == 's' then | ||||
|       local str = '' | ||||
|       for j = 1, string.len(stream) do | ||||
|       local bytes = {} | ||||
|       for j = 1 + iterator, string.len(stream) do | ||||
|         if string.sub(stream, j, j) == string.char(0) then | ||||
|           break | ||||
|         end | ||||
| 
 | ||||
|         str = str .. string.sub(stream, j, j) | ||||
|         table.insert(bytes, string.sub(stream, j, j)) | ||||
|       end | ||||
| 
 | ||||
|       stream = string.sub(stream, string.len(str) + 2) | ||||
|       local str = table.concat(bytes) | ||||
|       iterator = iterator + string.len(str) + 1 | ||||
|       table.insert(vars, str) | ||||
|     end | ||||
|   end | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Konrad Kuśnierz
						Konrad Kuśnierz