1local m = {} -- the module table 2 3local mt = {} -- the module metatable 4 5-- given a binary array, set a metamethod to return its length 6-- (e.g., #binaryArray, calls this) 7function mt:__len() 8 return self.size 9end 10 11-- Create a new binary array of an initial size 12function m.New(sizeOrString) 13 -- the array storage itself 14 local o = {} 15 16 if type(sizeOrString) == "string" then 17 o.str = sizeOrString 18 o.size = #sizeOrString 19 elseif type(sizeOrString) == "number" then 20 o.data = {} 21 o.size = sizeOrString 22 else 23 error("Expect a integer size value or string to construct a binary array") 24 end 25 -- set the inheritance 26 setmetatable(o, {__index = mt, __len = mt.__len}) 27 return o 28end 29 30-- Get a slice of the binary array from start to end position 31function mt:Slice(startPos, endPos) 32 startPos = startPos or 0 33 endPos = endPos or self.size 34 local d = self.data 35 if d then 36 -- if the self.data is defined, we are building the buffer 37 -- in a Lua table 38 39 -- new table to store the slice components 40 local b = {} 41 42 -- starting with the startPos, put all 43 -- values into the new table to be concat later 44 -- updated the startPos based on the size of the 45 -- value 46 while startPos < endPos do 47 local v = d[startPos] or '/0' 48 table.insert(b, v) 49 startPos = startPos + #v 50 end 51 52 -- combine the table of strings into one string 53 -- this is faster than doing a bunch of concats by themselves 54 return table.concat(b) 55 else 56 -- n.b start/endPos are 0-based incoming, so need to convert 57 -- correctly. in python a slice includes start -> end - 1 58 return self.str:sub(startPos+1, endPos) 59 end 60end 61 62-- Grow the binary array to a new size, placing the exisiting data 63-- at then end of the new array 64function mt:Grow(newsize) 65 -- the new table to store the data 66 local newT = {} 67 68 -- the offset to be applied to existing entries 69 local offset = newsize - self.size 70 71 -- loop over all the current entries and 72 -- add them to the new table at the correct 73 -- offset location 74 local d = self.data 75 for i,data in pairs(d) do 76 newT[i + offset] = data 77 end 78 79 -- update this storage with the new table and size 80 self.data = newT 81 self.size = newsize 82end 83 84-- memorization for padding strings 85local pads = {} 86 87-- pad the binary with n \0 bytes at the starting position 88function mt:Pad(n, startPos) 89 -- use memorization to avoid creating a bunch of strings 90 -- all the time 91 local s = pads[n] 92 if not s then 93 s = string.rep('\0', n) 94 pads[n] = s 95 end 96 97 -- store the padding string at the start position in the 98 -- Lua table 99 self.data[startPos] = s 100end 101 102-- Sets the binary array value at the specified position 103function mt:Set(value, position) 104 self.data[position] = value 105end 106 107-- locals for slightly faster access 108local sunpack = string.unpack 109local spack = string.pack 110 111-- Pack the data into a binary representation 112function m.Pack(fmt, ...) 113 return spack(fmt, ...) 114end 115 116-- Unpack the data from a binary representation in 117-- a Lua value 118function m.Unpack(fmt, s, pos) 119 return sunpack(fmt, s.str, pos + 1) 120end 121 122-- Return the binary array module 123return m