Packets: Complete reimplementation of parse helper macros
[senf.git] / Packets / ParseHelpers.hh
1 // $Id$
2 //
3 // Copyright (C) 2007 
4 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
5 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief ParseHelpers public header */
25
26 #ifndef HH_ParseHelpers_
27 #define HH_ParseHelpers_ 1
28
29 #ifndef HH_Packets_
30 #error "Don't include 'ParseHelpers.hh' directly, include 'Packets.hh'"
31 #endif
32
33 // Custom includes
34
35 //#include "ParseHelpers.mpp"
36 #include "ParseHelpers.ih"
37 ///////////////////////////////hh.p////////////////////////////////////////
38
39 /** \defgroup packetparsermacros Helper macros for defining new packet parsers
40
41     To simplify the definition of simple packet parsers, several macros are provided. Before
42     using these macros you should familiarize yourself with the packet parser interface as
43     described in senf::PacketParserBase.
44
45     These macros simplify providing the above defined interface. A typical packet declaration
46     using these macros has the following form (This is a concrete example from the definition of
47     the ethernet packet in <tt>DefaultBundle/EthernetPacket.hh</tt>)
48
49     \code
50     struct Parse_EthVLan : public PacketParserBase
51     {
52         typedef Parse_UIntField < 0,  3 > Parse_Priority;
53         typedef Parse_Flag          < 3 > Parse_CFI;
54         typedef Parse_UIntField < 4, 16 > Parse_VLanId;
55         typedef Parse_UInt16              Parse_Type;
56
57         SENF_PACKET_PARSER_INIT(Parse_EthVLan);
58
59         SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS(
60             ((OverlayField)( priority, Parse_Priority ))
61             ((OverlayField)( cfi,      Parse_CFI      ))
62             ((Field       )( vlanId,   Parse_VLanId   ))
63             ((Field       )( type,     Parse_Type     )) );
64     };
65     \endcode
66
67     The macros take care of the following:
68     \li They define the accessor functions returning parsers of the given type.
69     \li They automatically calculate the offset of the fields from the preceding fields.
70     \li The macros provide a definition for \c init() 
71     \li The macros define the \c bytes(), \c fixed_bytes and \c init_bytes members as needed.
72
73     You may define either a fixed or a dynamically sized parser. Fixed size parsers are defined
74     using \ref SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS, dynamically sized parsers are defined
75     using \ref SENF_PACKET_PARSER_DEFINE_FIELDS. The different members are implemented such
76     that:
77
78     \li The needed parser constructor is defined
79     \li \c init() calls \c defaultInit(). \c defaultInit() is defined to call \c init() on each
80         of the fields.
81     \li \c bytes() (on dynamically sized parser) respectively \c fixed_bytes (on fixed size
82         parsers) is defined to return the sum of the sizes of all fields.
83     \li On dynamically sized parsers, \c init_bytes is defined to return the sum of the
84         \c init_size's of all fields
85
86     The central definition macros are \ref SENF_PACKET_PARSER_DEFINE_FIXED_FIELDS and \ref
87     SENF_PACKET_PARSER_DEFINE_FIELDS. The argument to both has the same structure. It is a
88     (boost preprocessor style) sequence of field definitions where each field definition
89     provides the builder macro to use and the name and type of the field to define:
90     \code
91       SENF_PACKET_PARSER_DEFINE[_FIXED]_FIELDS(
92           (( <builder> )( <name>, <type> ))
93           ...
94       )
95     \endcode
96
97     For each field, this command will define
98     \li A method \a name() returning an instance of the \a type parser
99     \li \a name<tt>_t</tt> as a typedef for \a type, the fields value
100     \li \a name<tt>_offset</tt> to give the offset of the field from the beginning of the
101         parser. If the parser is a fixed size parser, this will be a static constant, otherwise
102         it will be a method.
103
104     The \a builder argument selects, how the field is defined
105     \li <tt>Field</tt> defines a field and increments the current position by the size of the
106         field
107     \li <tt>OverlayField</tt> defines a field like <tt>Field</tt> but does \e not increment the
108         position. In the above example, this is used to overlay the different bitfield parsers:
109         All overlaying bitfield parser except the last one (the one with the highest bit
110         numbers) is marked as OverlayField.
111
112     The \a name argument defines the name of the accessor method.
113
114     The \a type argument is the parser to return for that field. Since none of the arguments may
115     contain a comma, <em>This argument cannot be a multi-parameter template</em>. Always use
116     typedefs to access templated parsers as shown above.
117
118     The \ref SENF_PACKET_PARSER_INIT macro defines the constructor and the \c init() member. If
119     you want to provide your own \c init() implementation, use \ref
120     SENF_PACKET_PARSER_NO_INIT. The first statement in your init method should probably to call
121     \c defaultInit(). This will call the \c init() member of all the fields. Afterwards you can
122     set up the field values as needed:
123     \code
124       struct SomePacket : public senf::PacketParserBase
125       {
126           SENF_PACKET_PARSER_NO_INIT(SomePacket);
127
128           typedef senf::Parse_UInt8 Parse_Type;
129           typedef senf::Parse_Vector< senf::Parse_UInt32,
130                                       senf::SimpleVectorSizer<senf::Parse_UInt16>
131                                     > Parse_Elements;
132
133           SENF_PACKET_PARSER_DEFINE_FIELDS(
134               ((Field)( type,     Parse_Type     ))
135               ((Field)( elements, Parse_Elements ))
136           );
137
138           void init() const {
139               defaultInit();
140               type() = 0x01;
141               elements().push_back(0x01020304u);
142           }
143       }
144     \endcode
145
146     \ingroup packetparser
147  */
148
149 #define SENF_FIXED_PARSER() SENF_ABSOLUTE_INCLUDE_PATH(Packets/parse_fixed_setup.hh)
150 #define SENF_PARSER()       SENF_ABSOLUTE_INCLUDE_PATH(Packets/parse_setup.hh)
151
152 #define SENF_FIXED_PARSER_INITIALIZE()                                                            \
153     private:                                                                                      \
154         SENF_MPL_SLOT_DEF_ZERO(index);                                                            \
155         SENF_MPL_SLOT_DEF_ZERO(offset);                                                           \
156         SENF_MPL_SLOT_DEF_ZERO(bit);                                                              \
157         SENF_MPL_SLOT_DEF_ZERO(bitfield_size);                                                    \
158         void init_chain(senf::mpl::rv<0>*) {}                                                     \
159     public:
160
161 #define SENF_PARSER_INITIALIZE()                                                                  \
162     private:                                                                                      \
163         SENF_MPL_SLOT_DEF_ZERO(index);                                                            \
164         SENF_MPL_SLOT_DEF_ZERO(init_bytes);                                                       \
165         SENF_MPL_SLOT_DEF_ZERO(bit);                                                              \
166         SENF_MPL_SLOT_DEF_ZERO(bitfield_size);                                                    \
167         void init_chain(senf::mpl::rv<0>*) {}                                                     \
168         size_type field_offset_(senf::mpl::rv<0>*) const { return 0; }                            \
169     public:
170
171 #define SENF_PARSER_FIELD(name, type)              SENF_PARSER_FIELD_I(name, type, var, rw)
172 #define SENF_PARSER_FIELD_RO(name, type)           SENF_PARSER_FIELD_I(name, type, var, ro)
173 #define SENF_PARSER_CUSTOM_FIELD(name, type, size) SENF_PARSER_CUSTOM_FIELD_I(name, type, size, var)
174
175 #define SENF_PARSER_FIXED_FIELD(name, type)              SENF_PARSER_FIELD_I(name, type, fix, rw)
176 #define SENF_PARSER_FIXED_FIELD_RO(name, type)           SENF_PARSER_FIELD_I(name, type, fix, ro)
177 #define SENF_PARSER_FIXED_CUSTOM_FIELD(name, type, size) SENF_PARSER_CUSTOM_FIELD_I(name, type, size, fix)
178
179 #define SENF_PARSER_FIELD_AFTER(name, type, prev)              SENF_PARSER_FIELD_I_AFTER(name, type, prev, var, rw)
180 #define SENF_PARSER_FIELD_RO_AFTER(name, type, prev)           SENF_PARSER_FIELD_I_AFTER(name, type, prev, var, ro)
181 #define SENF_PARSER_CUSTOM_FIELD_AFTER(name, type, size, prev) SENF_PARSER_CUSTOM_FIELD_I_AFTER(name, type, size, prev, var)
182
183 #define SENF_PARSER_FIXED_FIELD_AFTER(name, type, prev)              SENF_PARSER_FIELD_I_AFTER(name, type, prev, fix, rw)
184 #define SENF_PARSER_FIXED_FIELD_RO_AFTER(name, type, prev)           SENF_PARSER_FIELD_I_AFTER(name, type, prev, fix, ro)
185 #define SENF_PARSER_FIXED_CUSTOM_FIELD_AFTER(name, type, size, prev) SENF_PARSER_CUSTOM_FIELD_I_AFTER(name, type, size, prev, fix)
186
187 #define SENF_PARSER_BITFIELD(name, bits, type)    SENF_PARSER_BITFIELD_I(name, bits, type, var, rw)
188 #define SENF_PARSER_BITFIELD_RO(name, bits, type) SENF_PARSER_BITFIELD_I(name, bits, type, var, ro)
189
190 #define SENF_PARSER_FIXED_BITFIELD(name, bits, type)    SENF_PARSER_BITFIELD_I(name, bits, type, fix, rw)
191 #define SENF_PARSER_FIXED_BITFIELD_RO(name, bits, type) SENF_PARSER_BITFIELD_I(name, bits, type, fix, ro)
192
193 #define SENF_PARSER_INIT()                                                                        \
194      void init(int)
195
196 #define SENF_PARSER_FINALIZE_GENERIC(name, base)                                                  \
197          void defaultInit() {                                                                     \
198              init_chain(static_cast<senf::mpl::rv<SENF_MPL_SLOT_GET(index)>*>(0));                \
199          }                                                                                        \
200          name(data_iterator i, state_type s) : base(i,s) {}                                       \
201     private:                                                                                      \
202          template <class T> void init(T) { defaultInit(); }                                       \
203     public:                                                                                       \
204          void init() { init(0); }
205
206 #define SENF_PARSER_FINALIZE_INHERITED_DYNAMIC(name, base)                                        \
207     SENF_PARSER_FINALIZE_GENERIC(name, base)                                                      \
208     size_type bytes() const {                                                                     \
209         return field_offset_(static_cast<senf::mpl::rv<SENF_MPL_SLOT_GET(index)>*>(0));           \
210     }                                                                                             \
211     static size_type const init_bytes = SENF_MPL_SLOT_GET(init_bytes)
212
213 #define SENF_PARSER_FINALIZE_INHERITED_FIXED(name, base)                                          \
214     SENF_PARSER_FINALIZE_GENERIC(name, base)                                                      \
215     static size_type const fixed_bytes = SENF_MPL_SLOT_GET(offset);
216
217 #define SENF_PARSER_FINALIZE_FIXED(name)                                                          \
218     SENF_PARSER_FINALIZE_INHERITED_FIXED(name, senf::PacketParserBase)
219
220 #define SENF_PARSER_FINALIZE_DYNAMIC(name)                                                        \
221     SENF_PARSER_FINALIZE_INHERITED_DYNAMIC(name, senf::PacketParserBase)
222
223 ///////////////////////////////hh.e////////////////////////////////////////
224 #endif
225 #if !defined(HH_Packets__decls_) && !defined(HH_ParseHelpers_i_)
226 #define HH_ParseHelpers_i_
227 //#include "ParseHelpers.cci"
228 //#include "ParseHelpers.ct"
229 //#include "ParseHelpers.cti"
230 #endif
231
232 \f
233 // Local Variables:
234 // mode: c++
235 // fill-column: 100
236 // comment-column: 40
237 // c-file-style: "senf"
238 // indent-tabs-mode: nil
239 // ispell-local-dictionary: "american"
240 // compile-command: "scons -u test"
241 // End: