Bitfields
Just like an ordinary C compiler, TempLuator supports bitfields. There is just one function for bitfields definition:
BITFIELD(Type, Name, Comment, NumBits, CvtFn)
Here Type is a string that defines the type of the bitfield variable and Name is a string that defines the name of the variable. Both these parameters are mandatory. Optional Comment parameter lets you print comment. The numeric NumBits parameter (mandatory) defines the number of bits in the bitfield. The last mandatory parameter CvtFn is a function that performs desired processing of the data read from the input file.
Definition of the BITFIELD() function is simple:
function BITFIELD(typ, nam, comment, numbits, cvtfn)
StartType(typ, nam .. ":" .. numbits)
local CvtRet = cvtfn(ReadBits(numbits)) if CvtRet ~= nil then PrintNumber(CvtRet) end
EndType(comment)
end
The StartType() and EndType() functions are internal functions which start and end a type definition and are used almost everywhere. As you can see, the BITFIELD() functions reads NumBits bits from the input file (using the ReadBits() function), then passes the just read bits to the supplied conversion function. If the value returned from the conversion function is not nil, then the BITFIELD() function prints the result of the conversion as a number. By returning nil from your conversion function you tell the BITFIELD() function that you have printed the value yourself and the fucntion does not need to show it.
Here is an example from the actual JPEG template explaining how the function is used and its output:
BITFIELD("BYTE", "Tq", "Quantization table destination identifier", 4, ToUI8)
BYTE Tq:4 = 0; // Quantization table destination identifier
Here we use the ToUI8() function as the numeric convertor. However, you can supply your own function if you need any special processing. This function should expect one parameter (which is ReaderData) and return a number. For example, here is a function that prints the bits as binary number in x86 assembler notation (a real life example from the ZIP template):
local function ToBinary(val)
local NumBits = val.Bits
if NumBits > 32 then error("PrintBinary: too many bits") end
local Mask = 2 ^ (NumBits - 1)
local Val = ToUI32(val)
local Str = ""
for i = 1, NumBits do
if TestBit(Val, Mask) then Str = Str .. "1" else Str = Str .. "0" end
Mask = Mask / 2
end
return Str .. "b"
end
In any case, don't forget that the bits are read with the ReadBits() function so all complications of bit reading also apply to the BITFIELD() function.