Advertisement
CloneTrooper1019

PackInts

Jun 15th, 2019
313
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 3.81 KB | None | 0 0
  1. ---------------------------------------------------------------------------------------------------------------------
  2. -- Pack Functions
  3. ---------------------------------------------------------------------------------------------------------------------
  4.  
  5. local MAX_PACK_VALUE = 2 ^ 53 -- Beyond this value, doubles have a consecutive gap of 2.
  6.  
  7. local function createByteReader(buffer)
  8.     local read = buffer:gmatch(".")
  9.    
  10.     return function ()
  11.         local char = read()
  12.         if char then
  13.             return char:byte()
  14.         end
  15.     end
  16. end
  17.  
  18. local function packInt(value)
  19.     assert(math.abs(value) < MAX_PACK_VALUE, "packInt - Cannot pack values above 2^53 reliably!")
  20.    
  21.     local pack = ""
  22.     local sign = value / math.abs(value)
  23.     local value = math.floor(value * sign)
  24.    
  25.     while value > 0 do
  26.         pack = pack .. string.char(value % 256)
  27.         value = math.floor(value / 256)
  28.     end
  29.    
  30.     local flags = #pack
  31.    
  32.     if sign < 0 then
  33.         flags = flags + 16
  34.     end
  35.    
  36.     return string.char(flags) .. pack
  37. end
  38.  
  39. local function packInts(ints)
  40.     if #ints > 255 then
  41.         error("packInts - Too many ints to pack!")
  42.     end
  43.    
  44.     local packed = string.char(#ints)
  45.    
  46.     for _,value in pairs(ints) do
  47.         packed = packed .. packInt(value)
  48.     end
  49.    
  50.     return packed
  51. end
  52.  
  53. local function unpackInt(input)
  54.     local readByte
  55.    
  56.     if type(input) == "function" then
  57.         readByte = input
  58.     elseif type(input) == "string" then
  59.         readByte = createByteReader(packed)
  60.     else
  61.         error("unpackInt - Argument #1 should be either an iterator function or a packed int string.")
  62.     end
  63.    
  64.     local value = 0
  65.     local flags = readByte()
  66.    
  67.     local length = flags % 16
  68.     local negate = math.floor(flags / 16)
  69.    
  70.     for i = 0, length - 1 do
  71.         local byte = readByte()
  72.         local layer = 2 ^ (8 * i)
  73.         value = value + (byte * layer)
  74.     end
  75.    
  76.     if negate > 0 then
  77.         value = -value
  78.     end
  79.    
  80.     return value
  81. end
  82.  
  83. local function unpackInts(packed)
  84.     local readByte = createByteReader(packed)
  85.     local numInts = readByte()
  86.    
  87.     local values = {}
  88.    
  89.     for i = 1, numInts do
  90.         local value = unpackInt(readByte)
  91.         table.insert(values, value)
  92.     end
  93.    
  94.     return values
  95. end
  96.  
  97. ---------------------------------------------------------------------------------------------------------------------
  98. -- Generate Ints
  99. ---------------------------------------------------------------------------------------------------------------------
  100.  
  101. local values = {}
  102. local strings = {}
  103.  
  104. for i = 1,200 do
  105.     local lower = math.random(8, 36)
  106.     local upper = math.random(8, 36)
  107.    
  108.     local value = math.random(-2 ^ lower, 2 ^ upper)
  109.     local str = string.format("%i", value)
  110.    
  111.     table.insert(values, value)
  112.     table.insert(strings, str)
  113. end
  114.  
  115. ---------------------------------------------------------------------------------------------------------------------
  116. -- Prepare Output
  117. ---------------------------------------------------------------------------------------------------------------------
  118.  
  119. local packBuffer = packInts(values)
  120.  
  121. local readable = packBuffer:gsub(".", function (char)
  122.     return string.format("%02X ", char:byte())
  123. end)
  124.  
  125. local div = '\n' .. string.rep('-', 120) .. '\n'
  126.  
  127. ---------------------------------------------------------------------------------------------------------------------
  128. -- Write Output
  129. ---------------------------------------------------------------------------------------------------------------------
  130.  
  131. print(div)
  132.  
  133. print("Values:\n\n" .. table.concat(strings, ", ") .. '\n')
  134. print("Bytes: " .. (#values * 8))
  135.  
  136. print(div)
  137.  
  138. print("Packed:\n\n" .. readable .. ā€˜\nā€™)
  139. print("Bytes: " .. #packBuffer)
  140.  
  141. print(div)
  142.  
  143. ---------------------------------------------------------------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement