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