Module bytereader
A ByteReader
transforms Lua inputs adhering to a simple protocol into
a bytes-count pair that other C and C++ APIs are able to safely consume.
The protocol goes as follows:
The object at index arg
(in Lua state L
) is examined.
If it happens to be a string, we can use its bytes and length directly.
Failing that, the object's metatable (if it has one) is queried for field __bytes. If no value is found, the object clearly does not honor the protocol, so we error out.
If __bytes is neither a light userdata nor a function, we have a garden-variety object and can use its bytes and length directly, as with strings.
When __bytes is a light userdata, it is assumed to point to a ByteReaderFunc
struct, containing a reader function mGetBytes
and a user-supplied context
mContext
. (The light userdata must also be present as a key in the Lua
registry.) This is called as mGetBytes(L, reader, arg, mContext)
, where
reader
is our byte reader, whose mBytes and mCount members the
function should supply. (See below how to handle errors.)
The object in the foregoing cases must be a full userdata.
The remaining possibility is that __bytes is a function, to be called as
object = func(object)
The process (i.e. is the object a string? if not, does it have a __bytes metafield? et al.) then recurses on this new object, using the final result.
When bytes are successfully found, the reader's mBytes member will point
to them, with the byte count stored in mCount. If bReplace
is true
(the default), the final bytes object—either a string or full
userdata—is moved into slot arg
, overwriting the original object
(this only matters in the __bytes-as-function case, since otherwise the
object will already be in position).
Should an error happen along the way, mBytes will be NULL
and an error
message is pushed on the stack.