Skip to content

Commit d086f30

Browse files
Victor NogueiraVictorNogueiraRio
authored andcommitted
Add support for union
1 parent be9e8c4 commit d086f30

File tree

1 file changed

+73
-0
lines changed

1 file changed

+73
-0
lines changed

lua/memory/layout.lua

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,79 @@ local function layoutstruct(fields, byteidx, bitoff)
170170
return spec, byteidx, bitoff
171171
end
172172

173+
local function layoutunion(fields, byteidx, bitoff)
174+
assert(type(fields) == "table" and #fields > 0, "invalid type")
175+
local spec = {
176+
pos = byteidx,
177+
bitoff = bitoff,
178+
bits = 0,
179+
bytes = 0,
180+
}
181+
182+
local specs = {}
183+
local maxsizefield = 0
184+
local byteidxmax = 0
185+
local bitoffmax = 0
186+
for _, field in ipairs(fields) do
187+
local key = field.key
188+
local type = field.type
189+
if type == nil then type = "number" end
190+
local build = assert(layout[type], "unsupported type")
191+
local field, byteidxtemp, bitofftemp = build(field, byteidx, bitoff)
192+
193+
if field.bits == nil then
194+
if field.bytes * 8 > maxsizefield then
195+
maxsizefield = field.bytes * 8
196+
byteidxmax = byteidxtemp
197+
bitoffmax = bitofftemp
198+
spec.bytes = byteidxtemp-spec.pos
199+
spec.bits = 8*(spec.bytes)+bitofftemp-spec.bitoff
200+
end
201+
else
202+
if field.bits > maxsizefield then
203+
maxsizefield = field.bits
204+
byteidxmax = byteidxtemp
205+
bitoffmax = bitofftemp
206+
spec.bytes = byteidxtemp-spec.pos
207+
spec.bits = 8*(spec.bytes)+bitofftemp-spec.bitoff
208+
end
209+
end
210+
211+
if key ~= nil then
212+
specs[key] = field
213+
end
214+
end
215+
spec.fields = specs
216+
return spec, byteidxmax, bitoffmax
217+
end
218+
219+
function layout.union(field, ...)
220+
local spec, byteidx, bitoff = layoutunion(field, ...)
221+
function spec.read(self)
222+
local pointer = self[spec]
223+
if pointer == nil then
224+
pointer = setmetatable({ struct = spec, parent = self }, Pointer)
225+
self[spec] = pointer
226+
end
227+
return pointer
228+
end
229+
function spec.write(self, value, key)
230+
if getmetatable(value) == Pointer then
231+
local src, dst = value.struct, spec
232+
assert(src.bitoff == 0 and src.bits%8 == 0
233+
and dst.bitoff == 0 and dst.bits%8 == 0, "unsupported")
234+
assert(dst.bytes == src.bytes, "size mismatch")
235+
local selfpos = rawget(self.parent, "pos")
236+
local valuepos = rawget(value.parent, "pos")
237+
memcopy(self.parent.buffer, value.parent.buffer,
238+
selfpos+dst.pos, selfpos+dst.pos+dst.bytes-1, valuepos+src.pos)
239+
else
240+
error("unsupported")
241+
end
242+
end
243+
return spec, byteidx, bitoff
244+
end
245+
173246
function layout.struct(field, ...)
174247
local spec, byteidx, bitoff = layoutstruct(field, ...)
175248
function spec.read(self)

0 commit comments

Comments
 (0)