X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Packets%2FParseHelpers.hh;h=9eff3949a311422884a3f7c58e2df7c61b214076;hb=92f8630b75f3ef50e73c48cde58645dcd1534e27;hp=9fc6cc021b09f30f58ab4820c7504a126bdc1971;hpb=9a98d859501eb314cb36208e2787d27da0367b5e;p=senf.git diff --git a/Packets/ParseHelpers.hh b/Packets/ParseHelpers.hh index 9fc6cc0..9eff394 100644 --- a/Packets/ParseHelpers.hh +++ b/Packets/ParseHelpers.hh @@ -1,8 +1,8 @@ // $Id$ // -// Copyright (C) 2007 -// Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS) -// Kompetenzzentrum fuer Satelitenkommunikation (SatCom) +// Copyright (C) 2007 +// Fraunhofer Institute for Open Communication Systems (FOKUS) +// Competence Center NETwork research (NET), St. Augustin, GERMANY // Stefan Bund // // This program is free software; you can redistribute it and/or modify @@ -23,10 +23,10 @@ /** \file \brief ParseHelpers public header */ -#ifndef HH_ParseHelpers_ -#define HH_ParseHelpers_ 1 +#ifndef HH_SENF_Packets_ParseHelpers_ +#define HH_SENF_Packets_ParseHelpers_ 1 -#ifndef HH_Packets_ +#ifndef HH_SENF_Packets_Packets_ #error "Don't include 'ParseHelpers.hh' directly, include 'Packets.hh'" #endif @@ -47,20 +47,17 @@ the ethernet packet in DefaultBundle/EthernetPacket.hh) \code - struct Parse_EthVLan : public PacketParserBase + struct EthVLanPacketParser : public PacketParserBase { - typedef Parse_UIntField < 0, 3 > Parse_Priority; - typedef Parse_Flag < 3 > Parse_CFI; - typedef Parse_UIntField < 4, 16 > Parse_VLanId; - typedef Parse_UInt16 Parse_Type; - - SENF_PACKET_PARSER_INIT(Parse_EthVLan); - - SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS( - ((OverlayField)( priority, Parse_Priority )) - ((OverlayField)( cfi, Parse_CFI )) - ((Field )( vlanId, Parse_VLanId )) - ((Field )( type, Parse_Type )) ); + # 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); }; \endcode @@ -70,10 +67,9 @@ \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 - using \ref SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS, dynamically sized parsers are defined - using \ref SENF_PACKET_PARSER_DEFINE_FIELDS. The different members are implemented such - that: + You may define either a fixed or a dynamically sized parser. Fixed size parsers are defined by + starting the packet with \#include SENF_FIXED_PARSER(), dynamically sized parsers start + with \#include SENF_PARSER(). 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 @@ -81,95 +77,625 @@ \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_size's of all fields + \c init_byte's of all fields + + \section parserlanguage 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. - The central definition macros are \ref SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS and \ref - SENF_PACKET_PARSER_DEFINE_FIELDS. The argument to both has the same structure. It is a - (boost preprocessor style) sequence of field definitions where each field definition - provides the builder macro to use and the name and type of the field to define: + Central to this language is the concept of current offset. 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) \code - SENF_PACKET_PARSER_DEFINE[_FIXED]_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_SKIP_BITS( 2 ); + 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 ); + }; \endcode - For each field, this command will define - \li A method \a name() returning an instance of the \a type parser - \li \a name_t as a typedef for \a type, the fields value - \li \a name_offset to give the offset of the field from the beginning of the - parser. If the parser is a fixed size parser, this will be a static constant, otherwise - it will be a method. - - The \a builder argument selects, how the field is defined - \li Field defines a field and increments the current position by the size of the - field - \li OverlayField defines a field like Field but does \e not increment the - position. In the above example, this is used to overlay the different bitfield parsers: - All overlaying bitfield parser except the last one (the one with the highest bit - numbers) is marked as OverlayField. - - The \a name argument defines the name of the accessor method. - - The \a type argument is the parser to return for that field. Since none of the arguments may - contain a comma, This argument cannot be a multi-parameter template. Always use - typedefs to access templated parsers as shown above. - - The \ref SENF_PACKET_PARSER_INIT macro defines the constructor and the \c init() member. If - you want to provide your own \c init() implementation, use \ref - SENF_PACKET_PARSER_NO_INIT. The first statement in your init method should probably to call - \c defaultInit(). This will call the \c init() member of all the fields. Afterwards you can - set up the field values as needed: + 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. + + After \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. + + \section parsermacroinit 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 \#include SENF_PARSER() or with + \#include SENF_FIXED_PARSER(). 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. + + \section parsermacrofields 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: + +
Standard fields:
\ref SENF_PARSER_FIELD(), \ref SENF_PARSER_FIELD_RO(), + \ref SENF_PARSER_PRIVATE_FIELD() define standard fields.
+ +
Arbitrary custom field:
\ref SENF_PARSER_CUSTOM_FIELD()
+ + 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. + + \subsection parsermacrosbitfields 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. + + \section parsermacrooffset 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 + name_offset 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 + at the time \ref SENF_PARSER_FINALIZE() is called. 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. + + \ingroup packetparser + */ +///\addtogroup packetparsermacros +///\{ + +///\name Control information +///@{ + +/** \brief Define fixed size parser + + This macro must be called using \c \#include at the beginning of every fixed size parser using + the packet parser helper macros: + \code - struct SomePacket : public senf::PacketParserBase - { - SENF_PACKET_PARSER_NO_INIT(SomePacket); - - typedef senf::Parse_UInt8 Parse_Type; - typedef senf::Parse_Vector< senf::Parse_UInt32, - senf::SimpleVectorSizer - > Parse_Elements; - - SENF_PACKET_PARSER_DEFINE_FIELDS( - ((Field)( type, Parse_Type )) - ((Field)( elements, Parse_Elements )) - ); - - void init() const { - defaultInit(); - type() = 0x01; - elements().push_back(0x01020304u); - } - } + struct SomeParser : public senf::PacketParserBase + { + # include SENF_FIXED_PARSER() \endcode - \ingroup packetparser + The parser must directly or indirectly inherit from senf::PacketParserBase + + \hideinitializer */ +#define SENF_FIXED_PARSER() SENF_ABSOLUTE_INCLUDE_PATH(Packets/parse_fixed_setup.hh) -#define SENF_FIXED_PARSER() SENF_ABSOLUTE_INCLUDE_PATH(Packets/parse_fixed_setup.hh) -#define SENF_PARSER() SENF_ABSOLUTE_INCLUDE_PATH(Packets/parse_setup.hh) +/** \brief Define dynamically sized parser + + This macro must be called using \c \#include at the beginning of every dynamically sized parser + using the packet parser helper macros: -#define SENF_PARSER_INHERIT BOOST_PP_CAT( SENF_PARSER_INHERIT_ , SENF_PARSER_TYPE ) + \code + struct SomeParser : public senf::PacketParserBase + { + # include SENF_PARSER() + \endcode + + The parser must directly or indirectly inherit from senf::PacketParserBase + + \hideinitializer + */ +#define SENF_PARSER() SENF_ABSOLUTE_INCLUDE_PATH(Packets/parse_setup.hh) + +/** \brief Define parser initialization routine -#define SENF_PARSE_FIELD BOOST_PP_CAT( SENF_PARSE_FIELD_ , SENF_PARSER_TYPE ) -#define SENF_PARSE_FIELD_RO BOOST_PP_CAT( SENF_PARSE_FIELD_RO_ , SENF_PARSER_TYPE ) -#define SENF_PARSE_CUSTOM_FIELD BOOST_PP_CAT( SENF_PARSE_CUSTOM_FIELD_ , SENF_PARSER_TYPE ) -#define SENF_PARSE_BITFIELD BOOST_PP_CAT( SENF_PARSE_BITFIELD_ , SENF_PARSER_TYPE ) -#define SENF_PARSE_BITFIELD_RO BOOST_PP_CAT( SENF_PARSE_BITFIELD_RO_ , SENF_PARSER_TYPE ) + This macro allows to replace the default initialization code. The default \c init() + implementation will call \c defaultInit() which in turn will call \c init() of every field + defined before \ref SENF_PARSER_FINALIZE(). -#define SENF_PARSER_FINALIZE BOOST_PP_CAT( SENF_PARSER_FINALIZE_ , SENF_PARSER_TYPE ) + \ref SENF_PARSER_INIT() allows to replace \c init() with custom code: + \code + SENF_PARSER_INIT() { + defaultInit(); + foo() = 2; + } + \endcode + 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 \ref SENF_PARSER_INIT() + + \hideinitializer + */ +#define SENF_PARSER_INIT() void init(int) const + +#ifdef DOXYGEN + +/** \brief Define parser inheritance + + If the a parser does not directly inherit senf::PacketParserBase, \ref 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. + \code + struct MyParser : public BaseParser + { + # include SENF_FIXED_PARSER() // or SENF_PARSER() + + SENF_PARSER_INHERIT(BaseParser) + \endcode + + If you want to define collection fields which reference auxiliary fields in the base parser, + you must define the base parser as a variable parser not a fixed parser. + + \param[in] base name of base class + \hideinitializer + */ +#define SENF_PARSER_INHERIT(base) + +/** \brief Generate parser control members + + \ref SENF_PARSER_FINALIZE() will generate the necessary parser control members (default + constructor, parser size, parser initialization). \ref SENF_PARSER_FINALIZE() needs not be the + last macro command within the parser though it will often be the last command since \ref + SENF_PARSER_FINALIZE() does not account for fields defined later. + + \ref SENF_PARSER_FINALIZE() uses the information from \ref SENF_PARSER_INHERIT() to construct + the parsers base class (which must be a valid parser class). + + \c defaultInit() is defined to initialize all fields defined before the call to \ref + SENF_PARSER_FINALIZE(). Fields defined later will \e not be initialized. If \ref + SENF_PARSER_INIT() is not used, \c init() is defined to call \c defaultInit(). + + The parsers size (either \c fixed_bytes for fixed size parsers or \c bytes() and \c init_bytes + for dynamically sized parsers) is set to the current offset. By manipulating the current offset + before calling \ref SENF_PARSER_FINALIZE(), the parser size can therefore be arbitrarily + manipulated. E.g., using \ref SENF_PARSER_GOTO_OFFSET() allows to set the size to an arbitrary + value. + + \param[in] name name of the parser class currently being defined + */ +#define SENF_PARSER_FINALIZE(name) + +///@} + +///\name Parser fields +///@{ + +/** \brief Define normal parser field + + The family of \ref 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 \a name parameter. The + field will be parsed using the \a 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 (\ref 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.
+ + \param[in] name field name + \param[in] type parser type + + \see \ref SENF_PARSER_FIELD_RO(), \ref SENF_PARSER_PRIVATE_FIELD() + \hideinitializer + */ +#define SENF_PARSER_FIELD(name, type) + +/** \brief Define parser field (read-only) + + Define read-only parser field. Read-only fields may only be defined for \a type's which are + value parsers: The parser \a type must have a \c value_type typedef member and a \c value() + member, which returns the current value of the field. + + Defining such a field really defines \e two accessors: A read/write \e private field and a + read-only \e public accessor. The name of the private read/write field is given by adding a + trailing '_' to \a name. The read-only public accessor is called \a name. + + \see SENF_PARSER_FIELD() + \hideinitializer +*/ +#define SENF_PARSER_FIELD_RO(name, type) + +/** \brief Define parser field (private) + + Define a parser field which is marked as \c private and may only be accessed from the parser + class itself. + + \see SENF_PARSER_FIELD() + \hideinitializer + */ +#define SENF_PARSER_PRIVATE_FIELD(name, type) + +/** \brief Define custom field accessor + + This macro is used to define a field using a custom access method: + \code + // The following is the same as SENF_PARSER_FIELD( xyz, senf::UInt16Parser ) + // in a fixed size parser. -#define SENF_PARSER_SKIP BOOST_PP_CAT( SENF_PARSER_SKIP_ , SENF_PARSER_TYPE ) -#define SENF_PARSER_GOTO BOOST_PP_CAT( SENF_PARSER_GOTO_ , SENF_PARSER_TYPE ) -#define SENF_PARSER_GOTO_OFFSET BOOST_PP_CAT( SENF_PARSER_GOTO_OFFSET_ , SENF_PARSER_TYPE ) -#define SENF_PARSER_LABEL BOOST_PP_CAT( SENF_PARSER_LABEL_ , SENF_PARSER_TYPE ) + SENF_PARSER_CUSTOM_FIELD(xyz, senf::UInt16Parser, xyz_t::fixed_bytes) { + return parse( xyz_offset ); + } + \endcode + + 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 + */ +#define SENF_PARSER_CUSTOM_FIELD(name, type, size) + +///@} + +///\name Bit fields +///@{ + +/** \brief Define bit-field + + Bit fields are supported by a special family of parser macros. These macros simplify defining + fields using the senf::Parse_Int, senf::Parse_UInt and senf::FlagParser parsers by keeping track + of the current bit position and automatically creating the correct template parameters. + + The \a type parameter specifies the type of bitfield to define. This value is one of + \li \c signed, for signed bit fields (senf::IntFieldParser) + \li \c unsigned, for unsigned bit fields (senf::UIntFieldParser) or + \li \c bool, for single-bit flags (senf::FlagParser). + + The \a bits parameter specifies the number of bits the field covers. For \c signed or \c + unsigned fields, this value may be any numeric value from 1 to 32, for \c bool fields, this + value \e must be 1. + + For more information see \ref parsermacrosbitfields + + \param[in] name name of the bit field + \param[in] bits number of bits + \param[in] type bit field type, one of \c signed, \c unsigned or \c bool + + \see \ref SENF_PARSER_BITFIELD_RO(), \ref SENF_PARSER_PRIVATE_BITFIELD() + \hideinitializer + */ +#define SENF_PARSER_BITFIELD(name, bits, type) + +/** \brief Define bit-field (read-only) + + Define read-only bit field. This is for bit-fields what \ref SENF_PARSER_FIELD_RO is for ordinary fields. + + \see \ref SENF_PARSER_BITFIELD() \n \ref SENF_PARSER_FIELD_RO() + \hideinitializer + */ +#define SENF_PARSER_BITFIELD_RO(name, bits, type) + +/** \brief Define bit-field (private) + + Define a bit field which is marked as \c private and may only be accessed from the parser class + itself. + + \see \ref SENF_PARSER_BITFIELD() + \hideinitializer + */ +#define SENF_PARSER_PRIVATE_BITFIELD(name, bits, type) + +///@} + +///\name Current offset +///@{ + +/** \brief Skip bytes + + Moves the offset by the given distance (which may be negative). \a skip depends on the type of + parser being defined and is either \a bytes or \a bytes, \a init_bytes. + + \li If defining a fixed parser, \a bytes must be a constant integral expression which will be + added to the current offset + \li If defining a dynamically sized parser, the macro really takes two arguments, \a bytes and + \a init_bytes. \a bytes will adjust the current field offset whereas \a init_bytes will + adjust the parsers \c init_bytes value. \a bytes is allowed to be any integral expression, + and need \e not be constant. The second argument \a init_bytes on the other hand needs to be + a constant integral expression. + + \param[in] bytes number of bytes to skip + \param[in] init_bytes only for dynamically sized parsers, value to adjust the \c init_bytes value + with. + + \hideinitializer + */ +#define SENF_PARSER_SKIP(skip) + +/** \brief Skip bits within bitfield group + + This command will skip the given number of bits within a bitfield group. This command does \e + only affect bitfield commands. Therefore, a SENF_PARSER_SKIP_BITS command which is not followed + by a bitfield command will be ignored. + + \hideinitializer + */ +#define SENF_PARSER_SKIP_BITS(bits) + +/** \brief Change current offset + + This command will change the current offset to the field or label \a name. Fields defined after + this command will start at that position and will therefore overlay any fields defined earlier + for these byte positions. + + \ref SENF_PARSER_GOTO() does \e 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 \e complete group (\e not the field within the bit field), even if the + group covers multiple bytes before the bit field \a name. + + \param[in] name field or label to jump to + \hideinitializer + */ +#define SENF_PARSER_GOTO(name) + +/** \brief Change current offset to explicit value + + \ref SENF_PARSER_GOTO_OFFSET() allows to change the current offset manually to an arbitrary + value. The \a offset parameter depends on the type of field currently being defined. + + \li If defining a fixed size parser, the \a offset argument is a single \a bytes value + which is an integral constant expression to which the offset will be set. + \li If defining a dynamically sized parser, the \a offset argument is given by two + parameters \a bytes and \a init_bytes. \a bytes can be any integral expression (not + necessarily constant) giving the new byte position. \a init_bytes must be a constant + integral expression and will set the current initial size of the packet to this value. + + \param[in] offset Depending on the parser type, either single \a bytes value or two arguments \a + bytes and \a init_size. + \hideinitializer + */ +#define SENF_PARSER_GOTO_OFFSET(offset) + +/** \brief Define offset label + + This command defines \a 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. + + \ref SENF_PARSER_GOTO() can later be used to jump to a position which has previously been + labeled with \ref SENF_PARSER_LABEL() + + \param[in] name label name + \hideinitializer + */ +#define SENF_PARSER_LABEL(name) + +/** \brief 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. + + \param[in] name field or label name + \returns offset of the field from parsers start + \hideinitializer + */ +#define SENF_PARSER_OFFSET(name) + +/** \brief Get fixed field offset, if possible + + This macro will return the fixed offset to the field \a name, a compile-time constant + expression. This is identical to \ref SENF_PARSER_OFFSET() when defining a fixed size parser. + + Even in dynamically sized parsers this macro will work, if the field \a name is preceded by + fixed size fields only. This macro does \e not validate this condition, it will return an + arbitrary incorrect value otherwise. + + \pre Field \a name preceded by fixed size fields only + \param[in] name field or label name + \returns compile-time constant offset of the field from parsers start + \hideinitializer + */ +#define SENF_PARSER_FIXED_OFFSET(name) + +/** \brief 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 \e before the + current position are fixed-size parsers. This macro does \e not validate this condition, it will + return an arbitrary incorrect value otherwise. + + \pre Current position preceded by fixed-size parsers only + \returns compile-time constant offset from parsers start + \hideinitializer + */ +#define SENF_PARSER_CURRENT_FIXED_OFFSET() + +///@} + +#else + +#define SENF_PARSER_INHERIT BOOST_PP_CAT( SENF_PARSER_INHERIT_, SENF_PARSER_TYPE ) + +#define SENF_PARSER_FIELD BOOST_PP_CAT( SENF_PARSER_FIELD_, SENF_PARSER_TYPE ) +#define SENF_PARSER_FIELD_RO BOOST_PP_CAT( SENF_PARSER_FIELD_RO_, SENF_PARSER_TYPE ) +#define SENF_PARSER_BITFIELD BOOST_PP_CAT( SENF_PARSER_BITFIELD_, SENF_PARSER_TYPE ) +#define SENF_PARSER_BITFIELD_RO BOOST_PP_CAT( SENF_PARSER_BITFIELD_RO_, SENF_PARSER_TYPE ) +#define SENF_PARSER_CUSTOM_FIELD BOOST_PP_CAT( SENF_PARSER_CUSTOM_FIELD_, SENF_PARSER_TYPE ) + +#define SENF_PARSER_PRIVATE_FIELD BOOST_PP_CAT( SENF_PARSER_P_FIELD_, SENF_PARSER_TYPE ) +#define SENF_PARSER_PRIVATE_BITFIELD BOOST_PP_CAT( SENF_PARSER_P_BITFIELD_, SENF_PARSER_TYPE ) + +#define SENF_PARSER_SKIP BOOST_PP_CAT( SENF_PARSER_SKIP_, SENF_PARSER_TYPE ) +#define SENF_PARSER_SKIP_BITS BOOST_PP_CAT( SENF_PARSER_SKIP_BITS_, SENF_PARSER_TYPE ) +#define SENF_PARSER_GOTO BOOST_PP_CAT( SENF_PARSER_GOTO_, SENF_PARSER_TYPE ) +#define SENF_PARSER_GOTO_OFFSET BOOST_PP_CAT( SENF_PARSER_GOTO_OFFSET_, SENF_PARSER_TYPE ) +#define SENF_PARSER_LABEL BOOST_PP_CAT( SENF_PARSER_LABEL_, SENF_PARSER_TYPE ) + +#define SENF_PARSER_OFFSET BOOST_PP_CAT( SENF_PARSER_OFFSET_, SENF_PARSER_TYPE ) +#define SENF_PARSER_FIXED_OFFSET BOOST_PP_CAT( SENF_PARSER_FIXED_OFFSET_, SENF_PARSER_TYPE ) +#define SENF_PARSER_CURRENT_FIXED_OFFSET BOOST_PP_CAT( SENF_PARSER_CURRENT_FIXED_OFFSET_, SENF_PARSER_TYPE ) + +#define SENF_PARSER_FINALIZE BOOST_PP_CAT( SENF_PARSER_FINALIZE_, SENF_PARSER_TYPE ) + +#endif -#define SENF_PARSER_INIT() void init(int) +///\} ///////////////////////////////hh.e//////////////////////////////////////// #endif -#if !defined(HH_Packets__decls_) && !defined(HH_ParseHelpers_i_) -#define HH_ParseHelpers_i_ +#if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_ParseHelpers_i_) +#define HH_SENF_Packets_ParseHelpers_i_ //#include "ParseHelpers.cci" //#include "ParseHelpers.ct" //#include "ParseHelpers.cti"