blob: bf728cddd69001ef757c027d8226f37f88b997ac [file] [log] [blame]
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001local 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