Helper macros for defining new packet parsers

Macros

#define SENF_PARSER_ARRAY(name, elt_type, size)
 Define array field. More...
 
#define SENF_PARSER_LIST(name, size, elt_type)
 Define ListParser field. More...
 
#define SENF_PARSER_PRIVATE_LIST(name, size, elt_type)
 Define private ListParser field. More...
 
#define SENF_PARSER_VARIANT(name, chooser, types)
 Define VariantParser field. More...
 
#define SENF_PARSER_PRIVATE_VARIANT(name, chooser, types)
 Define private VariantParser field. More...
 
#define SENF_PARSER_VECTOR(name, size, elt_type)
 Define VectorParser field. More...
 
#define SENF_PARSER_PRIVATE_VECTOR(name, size, elt_type)
 Define private VectorParser field. More...
 

Control information

#define SENF_FIXED_PARSER()
 Define fixed size parser. More...
 
#define SENF_PARSER()
 Define dynamically sized parser. More...
 
#define SENF_PARSER_INIT()
 Define parser initialization routine. More...
 
#define SENF_PARSER_INHERIT(base)
 Define parser inheritance. More...
 
#define SENF_PARSER_FINALIZE(name)
 Generate parser control members. More...
 

Parser fields

#define SENF_PARSER_FIELD(name, type)
 Define normal parser field. More...
 
#define SENF_PARSER_FIELD_RO(name, type)
 Define parser field (read-only) More...
 
#define SENF_PARSER_PRIVATE_FIELD(name, type)
 Define parser field (private) More...
 
#define SENF_PARSER_CUSTOM_FIELD(name, type, size)
 Define custom field accessor. More...
 

Bit fields

#define SENF_PARSER_BITFIELD(name, bits, type)
 Define bit-field. More...
 
#define SENF_PARSER_BITFIELD_RO(name, bits, type)
 Define bit-field (read-only) More...
 
#define SENF_PARSER_PRIVATE_BITFIELD(name, bits, type)
 Define bit-field (private) More...
 

Current offset

#define SENF_PARSER_SKIP(skip)
 Skip bytes. More...
 
#define SENF_PARSER_SKIP_BITS(bits)
 Skip bits within bitfield group. More...
 
#define SENF_PARSER_GOTO(name)
 Change current offset. More...
 
#define SENF_PARSER_GOTO_OFFSET(offset)
 Change current offset to explicit value. More...
 
#define SENF_PARSER_LABEL(name)
 Define offset label. More...
 
#define SENF_PARSER_OFFSET(name)
 Get field offset. More...
 
#define SENF_PARSER_FIXED_OFFSET(name)
 Get fixed field offset, if possible. More...
 
#define SENF_PARSER_CURRENT_FIXED_OFFSET()
 Get current fixed offset, if possible. More...
 

Detailed Description

To simplify the definition of simple packet parsers, several macros are provided. Before using these macros you should familiarize yourself with the packet parser interface as described in senf::PacketParserBase.

These macros simplify providing the above defined interface. A typical packet declaration using these macros has the following form (This is a concrete example from the definition of the ethernet packet in DefaultBundle/EthernetPacket.hh)

struct EthVLanPacketParser : public PacketParserBase
{
# include SENF_FIXED_PARSER()
SENF_PARSER_BITFIELD( priority, 3, unsigned );
SENF_PARSER_BITFIELD( cfi, 1, bool );
SENF_PARSER_BITFIELD( vlanId, 12, unsigned );
SENF_PARSER_FIELD( type, UInt16Parser );
SENF_PARSER_FINALIZE(EthVLanPacketParser);
};
The macros take care of the following:
\li They define the accessor functions returning parsers of the given type.
\li They automatically calculate the offset of the fields from the preceding fields.
\li The macros provide a definition for \c init()
\li The macros define the \c bytes(), \c fixed_bytes and \c init_bytes members as needed.

You may define either a fixed or a dynamically sized parser. Fixed size parsers are defined by
starting the packet with <tt>\#include SENF_FIXED_PARSER()</tt>, dynamically sized parsers start
with <tt>\#include SENF_PARSER()</tt>. The different members are implemented such that:

\li The needed parser constructor is defined
\li \c init() calls \c defaultInit(). \c defaultInit() is defined to call \c init() on each
    of the fields.
\li \c bytes() (on dynamically sized parser) respectively \c fixed_bytes (on fixed size
    parsers) is defined to return the sum of the sizes of all fields.
\li On dynamically sized parsers, \c init_bytes is defined to return the sum of the
    \c init_byte's of all fields

The Parser Macro micro-language

The macros provided to help implement composite parsers implement a very small declarative
language. This way of to think of the macros simplifies understanding, how the macros work.

Central to this language is the concept of <em>current offset</em>. The current offset is the
place (in bytes) from the beginning of the parser at which the next field will be added. Adding
fields to the parser will advance this offset by the size of the field added. Additional
commands allow to arbitrarily manipulate the current offset manually.

For fixed size parsers, the current offset is a single constant integral value, the number of
bytes from the parsers start. For dynamically sized parsers, the current offset really consists
of two values: One is the number of bytes from the parsers start, which however needs not be a
constant expression, the other value is the \c init_bytes value at this point, which is an
integral constant.

To demonstrate this functionality, here a more complex example (taken from \c MPEGDVBBundle and
then simplified by removing some fields)
struct Parse_DSMCCSection : public PacketParserBase
{
# include SENF_FIXED_PARSER()
SENF_PARSER_FIELD ( table_id , UInt8Parser );
SENF_PARSER_BITFIELD ( ssi , 1 , bool );
SENF_PARSER_BITFIELD ( private_indicator , 1 , bool );
SENF_PARSER_BITFIELD ( sec_length , 12 , unsigned );
SENF_PARSER_FIELD ( table_id_extension , UInt16Parser );
SENF_PARSER_FINALIZE( Parse_DSMCCSection );
};
struct Parse_DatagramSection : public Parse_DSMCCSection
{
# include SENF_FIXED_PARSER()
SENF_PARSER_INHERIT( Parse_DSMCCSection );
SENF_PARSER_FIELD ( mac_addr_4 , UInt8Parser );
SENF_PARSER_FIELD ( mac_addr_3 , UInt8Parser );
SENF_PARSER_FINALIZE( Parse_DatagramSection );
// Parse table_id_extension as two bytes
SENF_PARSER_GOTO( table_id_extension );
SENF_PARSER_FIELD ( mac_addr_6 , UInt8Parser );
SENF_PARSER_FIELD ( mac_addr_5 , UInt8Parser );
};
This code defines two parsers, the second of which is based on the first. Both are fixed size
parsers. The definition of \c Parse_DSMCCSection is straight forward (more on bit fields
below).

The derived parser is a little bit more complex. It starts out the same defining itself as a
fixed size parser. Then the base class is imported. Among other things, this call sets the
current offset to the first byte after the base parser (the base parser need not be implemented
using the packet parser macros, it just needs to be a valid parser). The additional fields \c
mac_addr_4 and \c mac_addr_3 are defined. Then we finalize the parser declaration.

<em>After</em> \ref SENF_PARSER_FINALIZE we add two more fields but not at the end of the
parser. \ref SENF_PARSER_GOTO jumps back to a previously defined label or field. Since the base
parser \c Parse_DSMCCSection is defined using the packet parser macros, we can even jump to
labels or fields defined in the base parser. Here, we jump to the beginning of the \c
table_id_extension field. \c mac_addr_6 and \c mac_addr_5 are therefore defined starting at that
offset and therefore overlay the \c table_id_extension field.

Parser initialization

\par ""
    \ref SENF_FIXED_PARSER(), \ref SENF_PARSER(), \ref SENF_PARSER_INHERIT(), \ref
    SENF_PARSER_INIT(), \ref SENF_PARSER_FINALIZE()

Every parser using the parser macros starts either with <tt>\#include SENF_PARSER()</tt> or with
<tt>\#include SENF_FIXED_PARSER()</tt>. This command sets the current offset to zero and defines
the type of parser to define.

A following optional \ref SENF_PARSER_INHERIT(\e base_class) is necessary if the parser does not
derive from senf::PacketParserBase. This call sets the base class and advances the current
offset to the end of the base parser.

\ref SENF_PARSER_INIT() is used to define the parser initialization code (the \c init()
member).

\ref SENF_PARSER_FINALIZE(\e class_name) is called to define the parsers constructor, the \c
init() member and to set the parsers size (\c fixed_bytes for fixed size parsers or \c bytes()
and \c init_bytes for dynamically sized parsers). It is valid to define further fields \e after
\ref SENF_PARSER_FINALIZE() has been called, however
\li Fields defined after \ref SENF_PARSER_FINALIZE() will \e not be initialized by \c
    defaultInit() (and therefore not by the default provided \c init() member). This can be very
    helpful when defining overlaying fields to avoid initializing some bytes multiple times.
\li The size of the parser is given by the current offset at the time of the \ref
    SENF_PARSER_FINALIZE() call.

Defining fields

\par ""
    \ref SENF_PARSER_FIELD(), \ref SENF_PARSER_FIELD_RO(), \ref SENF_PARSER_PRIVATE_FIELD(),
    \ref SENF_PARSER_CUSTOM_FIELD()

There are quite a few commands available to define fields. All these macros do the same thing:
they define a field accessor plus some auxiliary symbols. The accessor will use the parser type
passed to the macro to parse the field. The current offset is adjusted according to the size of
that parser. Normally, the parser will return an instance of the given parser type.

There are some properties the field defining macros might have. These properties are parts
of the macro name:

\par \c RO: Read only fields
    Macros with \c RO in their name define read only fields. This is only possible, if the
    field's parser is a value parser (that is, it must have a \c value_type typedef member and
    must provide the \c value() accessor member function). In this case, the value returned from
    the \e name() accessor member is not the parser but the parsers value and therefore it does
    not allow assignment to the field.

\par \c PRIVATE: Fields private to the parser class
    A private field will not be accessible from the outside (it is made \c private to the parser
    class). This is very handy when providing other accessor members to access a field in a
    manner more suitable for the specific field, when combining several fields into a single
    return value etc.

The field defining macros come in groups which members only differ in their properties:

<dl><dt><em>Standard fields:</em><dt><dd>\ref SENF_PARSER_FIELD(), \ref SENF_PARSER_FIELD_RO(),
    \ref SENF_PARSER_PRIVATE_FIELD() define standard fields.</dd>

<dt><em>Arbitrary custom field:</em><dt><dd>\ref SENF_PARSER_CUSTOM_FIELD()</dd></dl>

See the documentation of each of these macros for a detailed description of the macro arguments
and usage. Bit-fields are handled in the following section.

There also some supplementary macros for defining fields of more complex composite types
(e.g. vectors). See the list of 'Defines' further down this page.

Bit-fields

\par ""
    \ref SENF_PARSER_BITFIELD(), \ref SENF_PARSER_BITFIELD_RO(), \ref
    SENF_PARSER_PRIVATE_BITFIELD()\n

Bit-fields play a special role. They are quite frequent in packet definitions but don't fit into
the byte offset based parsing infrastructure defined so far. Since defining the correctly
parameterized senf::IntFieldParser, senf::UIntFieldParser and senf::FlagParser typedefs is quite
tedious, these helper macros are provided.

It is important to recognize, that the current offset does \e not include the current bit
position. The current offset after defining a bit-field will be the first complete byte after
that bit-field. Only the bit-field macros additionally take care of the current bit position
which is reset automatically by any intervening non-bitfield command.

So bit-field commands will come in groups. Any group of consecutive bitfield commands defines a
set of consecutive bits. The group as a whole will always be considered to cover a fixed number
of complete bytes. If the group does not cover those bytes completely (there are some bit's left
at the end), those bit's will be skipped.

Since consecutive bit-field commands are aggregated into a single bit-field group, the offset of
all these bit-fields will be the offset of the \e beginning of the group irrespective of the
number of bits parsed so far. Changing the offset to some bitfield using \ref SENF_PARSER_GOTO()
will therefore always go to the position at the beginning of this bitfield group. And since the
current offset does not include the bit position, the bit position will be 0, the first bit. You
may however break a bit-field group into two groups (at a byte boundary) by placing a \ref
SENF_PARSER_LABEL() command between the two groups.

The additional command \ref SENF_PARSER_SKIP_BITS() can be used to skip bit's between two
bit-fields.

Manipulating the current offset

\par ""
    \ref SENF_PARSER_SKIP(), \ref SENF_PARSER_SKIP_BITS(), \ref SENF_PARSER_GOTO(), \ref
    SENF_PARSER_GOTO_OFFSET(), \ref SENF_PARSER_LABEL()

To define more complex parsers, there are some macro commands which change the current offset.

\ref SENF_PARSER_SKIP(\e bytes) will skip the given number of bytes. \ref
SENF_PARSER_SKIP_BITS(\e bits) will work within bitfield definition to skip that number of bits.

\ref SENF_PARSER_GOTO(\e label_or_field) will change the offset to the given field or label. The
following fields will therefore start at that offset and overlay any fields already defined.

\ref SENF_PARSER_GOTO_OFFSET(\e offset) will jump to the given byte offset from the start of the
parser.

\ref SENF_PARSER_LABEL(\e name) will define \e name as a label for the current offset which can
then later be referenced using \ref SENF_PARSER_GOTO(). This also defines
<em>name</em><tt>_offset</tt> as a constant or member (for fixed respectively dynamically sized
parsers).

It is very important to recognize, that the size of the parser is defined by the current offset
<em>at the time \ref SENF_PARSER_FINALIZE() is called</em>. This allows to arbitrarily
manipulate the size of the parser by changing the current offset accordingly. For dynamically
sized parsers, the offset can even be any expression involving member function calls. See the
documentation of the respective macros for more details.

Macro Definition Documentation

◆ SENF_FIXED_PARSER

#define SENF_FIXED_PARSER ( )

Define fixed size parser.

This macro must be called using #include at the beginning of every fixed size parser using the packet parser helper macros:

struct SomeParser : public senf::PacketParserBase
{
# include SENF_FIXED_PARSER()
The parser must directly or indirectly inherit from senf::PacketParserBase

Definition at line 293 of file ParseHelpers.hh.

◆ SENF_PARSER

#define SENF_PARSER ( )

Define dynamically sized parser.

This macro must be called using #include at the beginning of every dynamically sized parser using the packet parser helper macros:

struct SomeParser : public senf::PacketParserBase
{
# include SENF_PARSER()
The parser must directly or indirectly inherit from senf::PacketParserBase

Definition at line 310 of file ParseHelpers.hh.

◆ SENF_PARSER_ARRAY

#define SENF_PARSER_ARRAY (   name,
  elt_type,
  size 
)

Define array field.

This macro is a special helper to define a senf::ArrayParser type field, a fixed size collection of fixed size elements.

Parameters
[in]namefield name
[in]elt_typearray element type
[in]sizeconstant number of elements

Definition at line 100 of file ArrayParser.hh.

◆ SENF_PARSER_BITFIELD

#define SENF_PARSER_BITFIELD (   name,
  bits,
  type 
)

Define bit-field.

Bit fields are supported by a special family of parser macros. These macros simplify defining fields using the senf::IntFieldParser, senf::UIntFieldParser and senf::FlagParser parsers by keeping track of the current bit position and automatically creating the correct template parameters.

The type parameter specifies the type of bitfield to define. This value is one of

The bits parameter specifies the number of bits the field covers. For signed or unsigned fields, this value may be any numeric value from 1 to 32, for bool fields, this value must be 1.

For more information see Bit-fields

Parameters
[in]namename of the bit field
[in]bitsnumber of bits
[in]typebit field type, one of signed, unsigned or bool
See also
SENF_PARSER_BITFIELD_RO(), SENF_PARSER_PRIVATE_BITFIELD()

Definition at line 506 of file ParseHelpers.hh.

◆ SENF_PARSER_BITFIELD_RO

#define SENF_PARSER_BITFIELD_RO (   name,
  bits,
  type 
)

Define bit-field (read-only)

Define read-only bit field. This is for bit-fields what SENF_PARSER_FIELD_RO is for ordinary fields.

See also
SENF_PARSER_BITFIELD()
SENF_PARSER_FIELD_RO()

Definition at line 515 of file ParseHelpers.hh.

◆ SENF_PARSER_CURRENT_FIXED_OFFSET

#define SENF_PARSER_CURRENT_FIXED_OFFSET ( )

Get current fixed offset, if possible.

This macro will return the current fixed offset, a compile-time constant expression. This is always possible when defining a fixed size parser.

Even in dynamically sized parsers this macro will work, if all parser defined before the current position are fixed-size parsers. This macro does not validate this condition, it will return an arbitrary incorrect value otherwise.

Precondition
Current position preceded by fixed-size parsers only
Returns
compile-time constant offset from parsers start

Definition at line 654 of file ParseHelpers.hh.

◆ SENF_PARSER_CUSTOM_FIELD

#define SENF_PARSER_CUSTOM_FIELD (   name,
  type,
  size 
)

Define custom field accessor.

This macro is used to define a field using a custom access method:

// The following is the same as SENF_PARSER_FIELD( xyz, senf::UInt16Parser )
// in a fixed size parser.
SENF_PARSER_CUSTOM_FIELD(xyz, senf::UInt16Parser, xyz_t::fixed_bytes) {
return parse<xyz_t>( xyz_offset );
}
The macro defines the same auxiliary symbols defined by \ref SENF_PARSER_FIELD(\a name, \a
type), the accessor method however is provided by the user.

\a size depends on the type of parser being defined:

\li If defining a fixed parser, \a size is a single value \a bytes which must be a constant
    integral expression giving the fixed size of the field.
\li If defining a dynamically sized parser, \a size is given by two parameters \a bytes and \a
    init_bytes. \a bytes is an arbitrary (not necessarily constant) expression giving the
    dynamic size of the field whereas \a init_bytes is the constant initial size assigned to the
    field.

\param[in] name name of the field to define
\param[in] type return type of the accessor function
\param[in] size size of the field, either a single value \a bytes for fixed size parsers or two
    separate arguments \a bytes and \a init_bytes for dynamically sized parsers

Definition at line 474 of file ParseHelpers.hh.

◆ SENF_PARSER_FIELD

#define SENF_PARSER_FIELD (   name,
  type 
)

Define normal parser field.

The family of SENF_PARSER_FIELD() macros is used to define standard fields of a composite parser. Every field is accessed by an accessor method named after the name parameter. The field will be parsed using the type parser which must be a valid packet parser. If the current parser is defined as a fixed size parser, all sub parsers must also be fixed size, otherwise dynamically sized parser (e.g. collection parsers) are Ok.

Defining a field will always define several members:

return_type name() const

The accessor member will return the parsed value when called. For normal fields, return_type equals type, the type of the sub parser. This allows to change the value via the returned sub-parser. If the field is marked read-only (SENF_PARSER_FIELD_RO()), the return type will be type::value_type.

typedef type name_t

This typedef symbol is an alias for the fields type.

size_type const name_offset

Defined only for fixed size parsers, this gives the fixed starting offset of the field from the beginning of the parser.

size_type name_offset() const
Defined only for dynamically sized parsers, this member function will return the dynamic offset of the field from the beginning of the parser.
Parameters
[in]namefield name
[in]typeparser type
See also
SENF_PARSER_FIELD_RO(), SENF_PARSER_PRIVATE_FIELD()

Definition at line 418 of file ParseHelpers.hh.

◆ SENF_PARSER_FIELD_RO

#define SENF_PARSER_FIELD_RO (   name,
  type 
)

Define parser field (read-only)

Define read-only parser field. Read-only fields may only be defined for type's which are value parsers: The parser type must have a value_type typedef member and a value() member, which returns the current value of the field.

Defining such a field really defines two accessors: A read/write private field and a read-only public accessor. The name of the private read/write field is given by adding a trailing '_' to name. The read-only public accessor is called name.

See also
SENF_PARSER_FIELD()

Definition at line 433 of file ParseHelpers.hh.

◆ SENF_PARSER_FINALIZE

#define SENF_PARSER_FINALIZE (   name)

Generate parser control members.

SENF_PARSER_FINALIZE() will generate the necessary parser control members (default constructor, parser size, parser initialization). SENF_PARSER_FINALIZE() needs not be the last macro command within the parser though it will often be the last command since SENF_PARSER_FINALIZE() does not account for fields defined later.

SENF_PARSER_FINALIZE() uses the information from SENF_PARSER_INHERIT() to construct the parsers base class (which must be a valid parser class).

defaultInit() is defined to initialize all fields defined before the call to SENF_PARSER_FINALIZE(). Fields defined later will not be initialized. If SENF_PARSER_INIT() is not used, init() is defined to call defaultInit().

The parsers size (either fixed_bytes for fixed size parsers or bytes() and init_bytes for dynamically sized parsers) is set to the current offset. By manipulating the current offset before calling SENF_PARSER_FINALIZE(), the parser size can therefore be arbitrarily manipulated. E.g., using SENF_PARSER_GOTO_OFFSET() allows to set the size to an arbitrary value.

Parameters
[in]namename of the parser class currently being defined

Definition at line 378 of file ParseHelpers.hh.

◆ SENF_PARSER_FIXED_OFFSET

#define SENF_PARSER_FIXED_OFFSET (   name)

Get fixed field offset, if possible.

This macro will return the fixed offset to the field name, a compile-time constant expression. This is identical to SENF_PARSER_OFFSET() when defining a fixed size parser.

Even in dynamically sized parsers this macro will work, if the field name is preceded by fixed size fields only. This macro does not validate this condition, it will return an arbitrary incorrect value otherwise.

Precondition
Field name preceded by fixed size fields only
Parameters
[in]namefield or label name
Returns
compile-time constant offset of the field from parsers start

Definition at line 639 of file ParseHelpers.hh.

◆ SENF_PARSER_GOTO

#define SENF_PARSER_GOTO (   name)

Change current offset.

This command will change the current offset to the field or label name. Fields defined after this command will start at that position and will therefore overlay any fields defined earlier for these byte positions.

SENF_PARSER_GOTO() does not take into account the current bit position within bit fields. When passed the name of a field within a bit field group, this command will always jump to the beginning of the complete group (not the field within the bit field), even if the group covers multiple bytes before the bit field name.

Parameters
[in]namefield or label to jump to

Definition at line 577 of file ParseHelpers.hh.

◆ SENF_PARSER_GOTO_OFFSET

#define SENF_PARSER_GOTO_OFFSET (   offset)

Change current offset to explicit value.

SENF_PARSER_GOTO_OFFSET() allows to change the current offset manually to an arbitrary value. The offset parameter depends on the type of field currently being defined.

  • If defining a fixed size parser, the offset argument is a single bytes value which is an integral constant expression to which the offset will be set.
  • If defining a dynamically sized parser, the offset argument is given by two parameters bytes and init_bytes. bytes can be any integral expression (not necessarily constant) giving the new byte position. init_bytes must be a constant integral expression and will set the current initial size of the packet to this value.
Parameters
[in]offsetDepending on the parser type, either single bytes value or two arguments bytes and init_size.

Definition at line 595 of file ParseHelpers.hh.

◆ SENF_PARSER_INHERIT

#define SENF_PARSER_INHERIT (   base)

Define parser inheritance.

If the a parser does not directly inherit senf::PacketParserBase, SENF_PARSER_INHERIT() must be called to define the parser's base-class. This call will additionally move the current offset to the end of the inherited parser so additional fields can be added.

struct MyParser : public BaseParser
{
# include SENF_FIXED_PARSER() // or SENF_PARSER()
SENF_PARSER_INHERIT(BaseParser)
If you want to define collection fields which reference auxiliary fields in the base parser,
<em>you must define the base parser as a variable parser not a fixed parser</em>.

\param[in] base name of base class

Definition at line 354 of file ParseHelpers.hh.

◆ SENF_PARSER_INIT

#define SENF_PARSER_INIT ( )

Define parser initialization routine.

This macro allows to replace the default initialization code. The default init() implementation will call defaultInit() which in turn will call init() of every field defined before SENF_PARSER_FINALIZE().

SENF_PARSER_INIT() allows to replace init() with custom code:

defaultInit();
foo() = 2;
}

Defining the initialization code manually skips the automatic call of defaultInit(), which may be performed manually. Should the initialization code be more complex, it should be placed into a non-inline private member which is called from SENF_PARSER_INIT()

Definition at line 331 of file ParseHelpers.hh.

◆ SENF_PARSER_LABEL

#define SENF_PARSER_LABEL (   name)

Define offset label.

This command defines name as a label for the current offset. The member name_offset is defined (either as a constant for fixed size parsers or as a member function for dynamically sized parsers) to return the position at the point of label definition.

SENF_PARSER_GOTO() can later be used to jump to a position which has previously been labeled with SENF_PARSER_LABEL()

Parameters
[in]namelabel name

Definition at line 610 of file ParseHelpers.hh.

◆ SENF_PARSER_LIST

#define SENF_PARSER_LIST (   name,
  size,
  elt_type 
)

Define ListParser field.

This macro is a special helper to define a senf::ListParser type field, a list of elements of type elt_type (a parser) which size is determined by size.

// The size field should be declared private or read-only (size is accessible via the list)
// Define the list
SENF_PARSER_LIST ( list, list_size_, EltParser );
    Here \c EltParser can be an arbitrary parser and need not have a fixed size.

    \warning Realize, that the \a size field is controlled by the list parser. This field
        should therefore be declared either read-only or private and must be changed only via
        the list parser.

    Further additional tags are supported which modify the type of list created:

    <table class="senf fixedcolumn">
    <tr><td>\c bytes(\a size)</td><td>\a size gives the size of the list in bytes not the
    number of contained elements</td></tr>

    <tr><td>\c packetSize()</td><td>Use the size of the packet to get the list size. The
    list will occupy all space up to the end of the packet.</td></tr>

    <tr><td>\c transform(\a transform, \a size)</td><td>The \a transform is applied to the \a
    size value, the value is not used directly</td>

    <tr><td>\c transform(\a transform, \c bytes(\a size))</td><td>The \a transform is applied to
    the \a size value. The value is then interpreted containing the list size in bytes not
    number of elements</td>
    </table>

    The optional \a transform is a class with the following layout
struct MyTransform
{
typedef ... value_type;
static value_type get(other_type v);
static other_type set(value_type v);
};
    \c other_type is \a size ::\c value_type, the type of the value returned by the \a size
    field, whereas the \c value_type typedef is the arbitrary return type of the transform.

    The tags are applied to the \a size parameter:
SENF_PARSER_LIST ( list, transform(MyTransform, list_size_), EltParser );
    \warning There are some caveats when working with \c bytes() type lists:
    \li You may <b>only change the size of a contained element from a container wrapper</b>.
    \li While you hold a container wrapper, <b>only access the packet through this wrapper</b>
        or a nested wrapper either for reading or writing.

    \warning If lists are nested, you need to allocate a container wrapper for each level and
    may only access the packet through the lowest-level active container wrapper.

    \par "Implementation note:" These restrictions are necessary to ensure correct recalculation of the
        <tt>bytes</tt> field. For more info, see the comments in \ref ListBParser.ih

    \param[in] name field name
    \param[in] size name of field giving the list size
    \param[in] elt_type list element type

    \see
        How to use \ref packet_usage_fields_collection \n
        senf::ListParser the list parser API for list field access
        senf::ListParser_Container the list parser container API for list field access

Definition at line 306 of file ListParser.hh.

◆ SENF_PARSER_OFFSET

#define SENF_PARSER_OFFSET (   name)

Get field offset.

This macro will return the offset of the given field or label. This macro may only be used while defining the parser, normally while defining inline functions.

This macro will return the correct value when defining fixed or dynamically sized parsers.

Parameters
[in]namefield or label name
Returns
offset of the field from parsers start

Definition at line 623 of file ParseHelpers.hh.

◆ SENF_PARSER_PRIVATE_BITFIELD

#define SENF_PARSER_PRIVATE_BITFIELD (   name,
  bits,
  type 
)

Define bit-field (private)

Define a bit field which is marked as private and may only be accessed from the parser class itself.

See also
SENF_PARSER_BITFIELD()

Definition at line 525 of file ParseHelpers.hh.

◆ SENF_PARSER_PRIVATE_FIELD

#define SENF_PARSER_PRIVATE_FIELD (   name,
  type 
)

Define parser field (private)

Define a parser field which is marked as private and may only be accessed from the parser class itself.

See also
SENF_PARSER_FIELD()

Definition at line 443 of file ParseHelpers.hh.

◆ SENF_PARSER_PRIVATE_LIST

#define SENF_PARSER_PRIVATE_LIST (   name,
  size,
  elt_type 
)

Define private ListParser field.

See also
SENF_PARSER_LIST()

Definition at line 316 of file ListParser.hh.

◆ SENF_PARSER_PRIVATE_VARIANT

#define SENF_PARSER_PRIVATE_VARIANT (   name,
  chooser,
  types 
)

Define private VariantParser field.

See also
SENF_PARSER_VARIANT()

Definition at line 245 of file VariantParser.hh.

◆ SENF_PARSER_PRIVATE_VECTOR

#define SENF_PARSER_PRIVATE_VECTOR (   name,
  size,
  elt_type 
)

Define private VectorParser field.

See also
SENF_PARSER_VECTOR()

Definition at line 299 of file VectorParser.hh.

◆ SENF_PARSER_SKIP

#define SENF_PARSER_SKIP (   skip)

Skip bytes.

Moves the offset by the given distance (which may be negative). skip depends on the type of parser being defined and is either bytes or bytes, init_bytes.

  • If defining a fixed parser, bytes must be a constant integral expression which will be added to the current offset
  • If defining a dynamically sized parser, the macro really takes two arguments, bytes and init_bytes. bytes will adjust the current field offset whereas init_bytes will adjust the parsers init_bytes value. bytes is allowed to be any integral expression, and need not be constant. The second argument init_bytes on the other hand needs to be a constant integral expression.
Parameters
[in]bytesnumber of bytes to skip
[in]init_bytesonly for dynamically sized parsers, value to adjust the init_bytes value with.

Definition at line 551 of file ParseHelpers.hh.

◆ SENF_PARSER_SKIP_BITS

#define SENF_PARSER_SKIP_BITS (   bits)

Skip bits within bitfield group.

This command will skip the given number of bits within a bitfield group. This command does only affect bitfield commands. Therefore, a SENF_PARSER_SKIP_BITS command which is not followed by a bitfield command will be ignored.

Definition at line 561 of file ParseHelpers.hh.

◆ SENF_PARSER_VARIANT

#define SENF_PARSER_VARIANT (   name,
  chooser,
  types 
)

Define VariantParser field.

This macro is a special helper to define a senf::VariantParser type field.

struct SomeParser : public PacketParserBase
{
# include SENF_PARSER()
SENF_PARSER_VARIANT( content, type,
(novalue( disable, senf::VoidPacketParser ))
( id( uint8value, senf::UInt8Parser ))
( id( uint16value, senf::UInt16Parser ))
( id( uint24value, senf::UInt24Parser ))
( id( uint32value, senf::UInt32Parser )) );
SENF_PARSER_FINALIZE( SomeParser );
};
    The variant \c content chooses one of the sub parsers depending on the \c type field. If \c
    type is 0, senf::VoidPacketParser is selected, if it is 1, senf::UInt8Parser and so on.

    \warning Realize, that the \a chooser field is controlled by the variant parser. This field
        should therefore be declared either read-only or private and must be changed only via
        the variant parser.

    The \a types parameter specifies the types of sub-objects supported by this variant
    parser. This parameter is a (Boost.Preprocessor style) sequence
    <pre>(\a type) (\a type) ...</pre>
    of parser types with additional optional information:

    <table class="senf fixedcolumn">
    <tr><td>\a type</td><td>Do not provide accessor and use the 0-based type index as
    key.</td></tr>

    <tr><td>\c id(\a name, \a type)</td><td>Automatically create an accessor \a name, a test
    function <tt>has_</tt>\a name and a function to switch to this type <tt>init_</tt>\a name
    for this type. Identical to \c ids(\a name, <tt>has_</tt>\a name, <tt>init_</tt>\a name, \a
    type)</td></tr>

    <tr><td>\c novalue(\a name, \a type)</td><td>This is like \c id but only provides an
    initializer called \a name and no accessor. Identical to \c ids(\c na, \c na, \a name, \a
    type)</td></tr>

    <tr><td>\c ids(\a accessorId, \a testId, \a initId, \a type)</td><td>This is again like \c
    id but the names of the accessor, test function and init function are given
    explicitly. Setting any of the id's to \c na will disable that function.</td></tr>

    <tr><td>\c key(\a value, \a type)</td><td>Use \a value to identity this type. The type is
    selected, when the \a chooser is equal to \a value</td></tr>

    <tr><td>\c id(\a name, \c key(\a value, \a type))<br/>\c novalue(\a name, \c key(\a value,
    \a type))</td><td>The options may be nested in this way.</td></tr>
    </table>

    Whenever an id is specified for any type, the variant itself will automatically be made
    private so the only access to the variant from the outside is via the accessors.

    The functions defined by specifying an id are:

    <table class="senf fixedcolumn">
    <tr><td><em>name</em><tt>_t</tt></td><td>The type for this specific variant value if not \c
    novalue.</td></tr>

    <tr><td><em>name</em><tt>_t</tt> <em>name</em>()</td><td>Return the variant value at this id
    if not \c novalue.</td></tr>

    <tr><td><tt>void</tt> <tt>init_</tt><em>name</em>()</td><td>Set the variant to have a value
    of this type. If the field is \c novalue, the \c init_ prefix is omitted.</td></tr>

    <tr><td><tt>bool</tt> <tt>has_</tt><em>name</em>()</td><td>Return \c true, if the variant
    currently holds this kind of value, \c false otherwise. Only if not \c novalue.</td></tr>
    </table>

    If \c key specs are given, they designate the value to expect in the \a chooser field to
    select a specific variant type. If the \a chooser value does not match any key, the variant
    will be initialized to the \e first type.

    Further additional tags are supported which modify the way, the \a chooser field is
    interpreted:

    <table class="senf fixedcolumn">
    <tr><td>\c transform(\a transform, \a chooser)</td><td>The \a transform is applied to the \a
    chooser value, the value is not used directly</td>
    </table>

    The optional \a transform is a class with the following layout
struct MyTransform
{
typedef ... value_type;
static value_type get(other_type v);
static other_type set(value_type v);
};

other_type is the chooser ::value_type whereas the value_type typedef is the arbitrary return type of the transform.

The tags are applied to the chooser parameter:

    \param[in] name name of the field
    \param[in] chooser name of the field choosing the variant to use
    \param[in] types a Boost.Preprocessor style sequence of sub-parser types

    \see
        senf::VariantParser for the VariantParser API\n
        \ref SENF_PARSER_PRIVATE_VARIANT()

Definition at line 236 of file VariantParser.hh.

◆ SENF_PARSER_VECTOR

#define SENF_PARSER_VECTOR (   name,
  size,
  elt_type 
)

Define VectorParser field.

This macro is a special helper to define a senf::VectorParser type field, a vector of elements of type elt_type (a parser) which size is given by the size field.

// The size field should be declared private (size is accessible via the vector)
// Define the vector, here it has 32bit unsigned integer elements
    \warning Realize, that the \a size field is controlled by the vector parser. This field
        should therefore be declared either read-only or private and must be changed only via
        the vector parser.

    Further additional tags are supported which modify the way, the \a size field is
    interpreted:

    <table class="senf fixedcolumn">
    <tr><td>\c bytes(\a size)</td><td>\a size gives the size of the vector in bytes not the
    number of contained elements</td></tr>

    <tr><td>\c packetSize()</td><td>Use the size of the packet to get the vector size. The
    vector will occupy all space up to the end of the packet.</td></tr>

    <tr><td>\c transform(\a transform, \a size)</td><td>The \a transform is applied to the \a
    size value, the value is not used directly</td>
    </table>

    The optional \a transform is a class with the following layout
struct MyTransform
{
typedef ... value_type;
static value_type get(other_type v);
static other_type set(value_type v);
};

other_type is the size ::value_type where as the value_type typedef is the arbitrary return type of the transform.

The tags are applied to the size parameter:

SENF_PARSER_VECTOR ( vec, transform(MyTransform, vec_size_), senf::UInt32Parser );
SENF_PARSER_VECTOR ( vec, packetSize(), senf::UInt32Parser );
    \param[in] name field name
    \param[in] size name of field giving the vector size
    \param[in] elt_type vector element type

    \see
        How to use \ref packet_usage_fields_collection \n
        senf::VectorParser the vector parser API for vector field access
        senf::VectorParser_Container the vector parser container API for vector field access

Definition at line 289 of file VectorParser.hh.