Packets: Allow packet parsers to access the packet chain
[senf.git] / Packets / PacketInterpreter.hh
1 // Copyright (C) 2007 
2 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
3 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
4 //     Stefan Bund <g0dil@berlios.de>
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the
18 // Free Software Foundation, Inc.,
19 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20
21 /** \file
22     \brief PacketInterpreter public header */
23
24 #ifndef HH_PacketInterpreter_
25 #define HH_PacketInterpreter_ 1
26
27 // Custom includes
28 #include "../boost/intrusive/ilist.hpp"
29 #include <boost/optional.hpp>
30 #include <boost/range.hpp>
31 #include <boost/type_traits/aligned_storage.hpp>
32 #include <boost/type_traits/alignment_of.hpp>
33 #include "../Utils/intrusive_refcount.hh"
34 #include "../Utils/pool_alloc_mixin.hh"
35 #include "PacketData.hh"
36 #include "../Utils/TypeIdValue.hh"
37
38 //#include "PacketInterpreter.mpp"
39 ///////////////////////////////hh.p////////////////////////////////////////
40
41 namespace senf {
42
43     template <class PacketType> class PacketInterpreter;
44
45     /** \brief Internal: Base packet interpreter class
46         
47         \internal
48
49         This is the base class for the persistent interpreter. This class encapsulates all the
50         functionality accessible via the packet handle, most handle operations are just forwarded.
51       */
52     class PacketInterpreterBase
53         : protected PacketData, 
54           public detail::packet::interpreter_list_base,
55           public intrusive_refcount_t<PacketInterpreterBase>
56     {
57     public:
58         ///////////////////////////////////////////////////////////////////////////
59         // Types
60
61         typedef senf::detail::packet::smart_pointer<
62             PacketInterpreterBase>::ptr_t ptr;
63
64         typedef senf::detail::packet::iterator iterator;
65         typedef senf::detail::packet::const_iterator const_iterator;
66         typedef senf::detail::packet::size_type size_type;
67         typedef senf::detail::packet::difference_type difference_type;
68         typedef senf::detail::packet::byte byte;
69
70         typedef boost::iterator_range<iterator> range;
71         typedef boost::optional< boost::iterator_range<iterator> > optional_range;
72         typedef optional_range no_range;
73
74         enum Append_t { Append };
75         enum Prepend_t { Prepend };
76         enum NoInit_t { noinit };
77
78         /** \brief Internal: Abstract packet factory
79
80             \internal
81
82             This abstract class provides an abstract packet factory interface. It allows to call
83             almost any one of the create / createAfter / createBefore static PacketInterpreter
84             without static information on the type of packet to create.
85          */
86         struct Factory { 
87             virtual ~Factory();
88
89             // Create completely new packet
90
91             virtual ptr create() const = 0;
92             virtual ptr create(NoInit_t) const = 0;
93             virtual ptr create(size_type size) const = 0;
94             virtual ptr create(size_type size, NoInit_t) const = 0;
95             template <class ForwardReadableRange>
96             ptr create(ForwardReadableRange const & range) const;
97             
98             // Create packet as new packet after a given packet
99
100             virtual ptr createAfter(PacketInterpreterBase::ptr packet) const = 0;
101             virtual ptr createAfter(PacketInterpreterBase::ptr packet, NoInit_t) const = 0;
102             virtual ptr createAfter(PacketInterpreterBase::ptr packet, size_type size) const = 0;
103             virtual ptr createAfter(PacketInterpreterBase::ptr packet, size_type size, 
104                                     NoInit_t) const = 0;
105             template <class ForwardReadableRange>
106             ptr createAfter(PacketInterpreterBase::ptr packet, 
107                             ForwardReadableRange const & range) const;
108             
109             // Create packet as new packet (header) const before a given packet
110
111             virtual ptr createBefore(PacketInterpreterBase::ptr packet) const = 0;
112             virtual ptr createBefore(PacketInterpreterBase::ptr packet, NoInit_t) const = 0;
113
114             // Parse next packet in chain
115
116             virtual ptr parseNext(ptr packet) const = 0;
117         };
118
119         typedef Factory const * factory_t;
120
121         ///////////////////////////////////////////////////////////////////////////
122         ///\name Structors and default members
123         ///@{
124
125         // protected constructors
126         // no copy
127         // no conversion constructors
128
129         virtual ~PacketInterpreterBase();
130
131         static                             factory_t no_factory();
132         
133         ptr clone();
134  
135         ///@}
136         ///////////////////////////////////////////////////////////////////////////
137
138         ///\name Interpreter chain access
139         ///@{
140
141         ptr next();
142         ptr prev();
143         ptr first();
144         ptr last();
145
146         template <class Type> typename PacketInterpreter<Type>::ptr parseNextAs();
147                                        ptr                          parseNextAs(factory_t factory);
148         template <class Type>          bool                         is();
149         template <class Type> typename PacketInterpreter<Type>::ptr as();
150
151         ptr append(ptr packet);
152
153         ///@}
154
155         ///\name Data access
156         ///@{
157
158         using PacketData::valid;
159         PacketData & data();
160         
161         ///@}
162
163         ///\name Access to the abstract interface
164         ///@{
165
166         optional_range nextPacketRange();
167         void finalize();
168         void dump(std::ostream & os);
169         TypeIdValue typeId();
170         factory_t factory();
171         factory_t nextPacketType();
172
173         ///@}
174
175     protected:
176         // protected structors
177
178         PacketInterpreterBase(detail::PacketImpl * impl, iterator b, iterator e, Append_t);
179         PacketInterpreterBase(detail::PacketImpl * impl, iterator b, iterator e, Prepend_t);
180
181         ptr appendClone(detail::PacketImpl * impl, iterator base, iterator new_base);
182         ptr appendClone(detail::PacketImpl * impl, range r);
183
184     public:
185         // Need this for g++ < 4.0. Since PacketInterpreter is not publicly visible, it should not
186         // be a real problem to make impl() public here
187         using PacketData::impl;
188
189     private:
190         // abstract packet type interface
191
192         virtual optional_range v_nextPacketRange() = 0;
193         virtual ptr v_appendClone(detail::PacketImpl * impl, iterator base, iterator new_base) = 0;
194         virtual ptr v_appendClone(detail::PacketImpl * impl, range r) =0;
195         virtual void v_finalize() = 0;
196         virtual void v_dump(std::ostream & os) = 0;
197         virtual TypeIdValue v_type() = 0;
198         virtual factory_t v_factory() = 0;
199         virtual factory_t v_nextPacketType() = 0;
200
201         // reference/memory management. Only to be called by intrusive_refcount_t.
202
203         void add_ref();
204         bool release();
205
206         // containment management. Only to be called by PacketImpl.
207
208         void assignImpl(detail::PacketImpl *);
209         void releaseImpl();
210
211         friend class detail::PacketImpl;
212         friend class intrusive_refcount_t<PacketInterpreterBase>;
213         template <class PacketType> friend class PacketInterpreter;
214         friend class detail::packet::test::TestDriver;
215         friend class PacketParserBase;
216     };
217
218     /** \brief Internal: Concrete packet interpreter
219
220         \internal
221
222         Instantiations of this class build the interpreter chain. This class is accessed by the
223         packet handles. It provides the packet-type specific functionality in addition to the
224         interface defined in the PacketInterpreterBase class.
225
226         \see PacketTypeBase for the \a PacketType interface
227       */
228     template <class PacketType>
229     class PacketInterpreter
230         : public PacketInterpreterBase,
231           public pool_alloc_mixin< PacketInterpreter<PacketType> >
232     {
233     public:
234         ///////////////////////////////////////////////////////////////////////////
235         // Types
236
237         typedef typename senf::detail::packet::smart_pointer<
238             PacketInterpreter>::ptr_t ptr;
239         typedef PacketType type;
240         typedef typename type::parser parser;
241
242         ///////////////////////////////////////////////////////////////////////////
243         ///\name Structors and default members
244         ///@{
245
246         // private constructors
247         // no copy
248         // no conversion constructors
249
250         ~PacketInterpreter();
251
252         static factory_t factory();
253
254         // Create completely new packet
255
256         static ptr create();
257         static ptr create(NoInit_t);
258         static ptr create(size_type size);
259         static ptr create(size_type size, NoInit_t);
260         template <class ForwardReadableRange>
261         static ptr create(ForwardReadableRange const & range);
262
263         // Create packet as new packet after a given packet
264
265         static ptr createAfter(PacketInterpreterBase::ptr packet);
266         static ptr createAfter(PacketInterpreterBase::ptr packet, NoInit_t);
267         static ptr createAfter(PacketInterpreterBase::ptr packet, size_type size);
268         static ptr createAfter(PacketInterpreterBase::ptr packet, size_type size, NoInit_t);
269         template <class ForwardReadableRange>
270         static ptr createAfter(PacketInterpreterBase::ptr packet, 
271                                ForwardReadableRange const & range);
272
273         // Create packet as new packet (header) before a given packet
274
275         static ptr createBefore(PacketInterpreterBase::ptr packet);
276         static ptr createBefore(PacketInterpreterBase::ptr packet, NoInit_t);
277
278         // Create a clone of the current packet
279
280         ptr clone();
281
282         ///@}
283         ///////////////////////////////////////////////////////////////////////////
284
285         // Packet field access
286
287         parser fields();
288         parser * fields_p();
289
290         // PacketType access
291
292         static size_type initSize();
293         static size_type initHeadSize();
294
295     protected:
296
297     private:
298         // Private structors
299
300         PacketInterpreter(detail::PacketImpl * impl, iterator b, iterator e, Append_t);
301         PacketInterpreter(detail::PacketImpl * impl, iterator b, iterator e, Prepend_t);
302
303         static ptr create(detail::PacketImpl * impl, iterator b, iterator e, Append_t);
304         static ptr create(detail::PacketImpl * impl, iterator b, iterator e, Prepend_t);
305
306         // PacketType access
307
308         void init();
309
310         // virtual interface
311
312         virtual optional_range v_nextPacketRange();
313         virtual PacketInterpreterBase::ptr v_appendClone(detail::PacketImpl * impl, 
314                                                          iterator base, iterator new_base);
315         virtual PacketInterpreterBase::ptr v_appendClone(detail::PacketImpl * impl, range r);
316         virtual void v_finalize();
317         virtual void v_dump(std::ostream & os);
318         virtual TypeIdValue v_type();
319         virtual factory_t v_factory();
320         virtual factory_t v_nextPacketType();
321
322         // factory
323
324         /** \brief Internal: Implementation of abstract factory interface
325             
326             \internal
327
328             Implements the abstract factory interface for \a PacketType
329          */
330         struct FactoryImpl : public Factory {
331             // Create completely new packet
332
333             virtual PacketInterpreterBase::ptr create() const;
334             virtual PacketInterpreterBase::ptr create(NoInit_t) const;
335             virtual PacketInterpreterBase::ptr create(size_type size) const;
336             virtual PacketInterpreterBase::ptr create(size_type size,NoInit_t) const;
337             
338             // Create packet as new packet after a given packet
339
340             virtual PacketInterpreterBase::ptr createAfter(PacketInterpreterBase::ptr packet) 
341                 const;
342             virtual PacketInterpreterBase::ptr createAfter(PacketInterpreterBase::ptr packet, 
343                                                            NoInit_t) const;
344             virtual PacketInterpreterBase::ptr createAfter(PacketInterpreterBase::ptr packet, 
345                                                            size_type size) const;
346             virtual PacketInterpreterBase::ptr createAfter(PacketInterpreterBase::ptr packet, 
347                                                            size_type size, NoInit_t) const;
348             
349             // Create packet as new packet (header) before a given packet
350
351             virtual PacketInterpreterBase::ptr createBefore(PacketInterpreterBase::ptr packet) 
352                 const;
353             virtual PacketInterpreterBase::ptr createBefore(PacketInterpreterBase::ptr packet,
354                                                             NoInit_t) 
355                 const;
356
357             // Parse next packet in chain
358
359             virtual PacketInterpreterBase::ptr parseNext(PacketInterpreterBase::ptr packet) 
360                 const;
361         };
362
363         static const FactoryImpl factory_;
364
365         parser * parser_p();
366
367         boost::aligned_storage< sizeof(parser), 
368                                 boost::alignment_of<parser>::value > parserStorage_;
369
370         friend class detail::packet::test::TestDriver;
371         friend class PacketInterpreterBase;
372         friend class FactoryImpl;
373     };
374
375     /** \brief Invalid packet chain operation
376
377         This exception signals an invalid operation on the chain like trying to find a non-existent
378         chain member and other similar error conditions. 
379      */
380     struct InvalidPacketChainException : public std::exception
381     { virtual char const * what() const throw() { return "invalid packet chain"; } };
382     
383 }
384
385 ///////////////////////////////hh.e////////////////////////////////////////
386 #endif
387 #if !defined(SENF_PACKETS_DECL_ONLY) && !defined(HH_PacketInterpreter_i_)
388 #define HH_PacketInterpreter_i_
389 #include "PacketInterpreter.cci"
390 #include "PacketInterpreter.ct"
391 #include "PacketInterpreter.cti"
392 #endif
393
394 \f
395 // Local Variables:
396 // mode: c++
397 // fill-column: 100
398 // c-file-style: "senf"
399 // indent-tabs-mode: nil
400 // ispell-local-dictionary: "american"
401 // compile-command: "scons -u test"
402 // comment-column: 40
403 // End: