Next: , Previous: , Up: Structs   [Contents][Index]


18.5.14 Optional Fields

Sometimes a field in a struct is optional, i.e. it exists or not depending on some criteria. A good example of this is the “extended header” in a MP3 id3v2 tag. From the specification:

The second bit (bit 6) indicates whether or not the header is followed
by an extended header. The extended header is described in section
3.2. A set bit indicates the presence of an extended header.

In order to express this in a Poke struct type, we could of course use an union, like:

type ID3V2_Tag =
  struct
  {
    ID3V2_Hdr hdr;
    union
    {
      ID3V2_Ext_Hdr hdr if hdr.extended_hdr_present;
      struct {};
    } ext;
    …
  }

That’s it, we use an union with an empty alternative. However, this is a bit cumbersome. Therefore Poke provides a more convenient way to denote this:

type ID3V2_Tag =
  struct
  {
     ID3V2_Hdr hdr;
     IDV2_Ext_Hdr ext_hdr if hdr.extended_hdr_present;
     …
  }

If both a constraint and an optional field expression are specified, the second should follow the first.

One important characteristic of optional fields to keep in mind is that they are always constructed or mapped, even when they are omitted. This is because, generally speaking, the value of an optional field may be necessary in order to determine whether the optional field is present or not.

This may result on unexpected results for the unaware pokist, like in the example below:

struct
{
  Header hdr;
  byte[hdr.len - hdr.padding] data if hdr.len >= hdr.padding;
}

where the array index may underflow if hdr.len is less or equal than hdr.padding.

For obvious reasons, optional fields are not allowed in unions.


Next: , Previous: , Up: Structs   [Contents][Index]