9c6e5bfce10378bf1ce6a295bf48869bdb9aa581
[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     };
216
217     /** \brief Internal: Concrete packet interpreter
218
219         \internal
220
221         Instantiations of this class build the interpreter chain. This class is accessed by the
222         packet handles. It provides the packet-type specific functionality in addition to the
223         interface defined in the PacketInterpreterBase class.
224
225         \see PacketTypeBase for the \a PacketType interface
226       */
227     template <class PacketType>
228     class PacketInterpreter
229         : public PacketInterpreterBase,
230           public pool_alloc_mixin< PacketInterpreter<PacketType> >
231     {
232     public:
233         ///////////////////////////////////////////////////////////////////////////
234         // Types
235
236         typedef typename senf::detail::packet::smart_pointer<
237             PacketInterpreter>::ptr_t ptr;
238         typedef PacketType type;
239         typedef typename type::parser parser;
240
241         ///////////////////////////////////////////////////////////////////////////
242         ///\name Structors and default members
243         ///@{
244
245         // private constructors
246         // no copy
247         // no conversion constructors
248
249         ~PacketInterpreter();
250
251         static factory_t factory();
252
253         // Create completely new packet
254
255         static ptr create();
256         static ptr create(NoInit_t);
257         static ptr create(size_type size);
258         static ptr create(size_type size, NoInit_t);
259         template <class ForwardReadableRange>
260         static ptr create(ForwardReadableRange const & range);
261
262         // Create packet as new packet after a given packet
263
264         static ptr createAfter(PacketInterpreterBase::ptr packet);
265         static ptr createAfter(PacketInterpreterBase::ptr packet, NoInit_t);
266         static ptr createAfter(PacketInterpreterBase::ptr packet, size_type size);
267         static ptr createAfter(PacketInterpreterBase::ptr packet, size_type size, NoInit_t);
268         template <class ForwardReadableRange>
269         static ptr createAfter(PacketInterpreterBase::ptr packet, 
270                                ForwardReadableRange const & range);
271
272         // Create packet as new packet (header) before a given packet
273
274         static ptr createBefore(PacketInterpreterBase::ptr packet);
275         static ptr createBefore(PacketInterpreterBase::ptr packet, NoInit_t);
276
277         // Create a clone of the current packet
278
279         ptr clone();
280
281         ///@}
282         ///////////////////////////////////////////////////////////////////////////
283
284         // Packet field access
285
286         parser fields();
287         parser * fields_p();
288
289         // PacketType access
290
291         static size_type initSize();
292         static size_type initHeadSize();
293
294     protected:
295
296     private:
297         // Private structors
298
299         PacketInterpreter(detail::PacketImpl * impl, iterator b, iterator e, Append_t);
300         PacketInterpreter(detail::PacketImpl * impl, iterator b, iterator e, Prepend_t);
301
302         static ptr create(detail::PacketImpl * impl, iterator b, iterator e, Append_t);
303         static ptr create(detail::PacketImpl * impl, iterator b, iterator e, Prepend_t);
304
305         // PacketType access
306
307         void init();
308
309         // virtual interface
310
311         virtual optional_range v_nextPacketRange();
312         virtual PacketInterpreterBase::ptr v_appendClone(detail::PacketImpl * impl, 
313                                                          iterator base, iterator new_base);
314         virtual PacketInterpreterBase::ptr v_appendClone(detail::PacketImpl * impl, range r);
315         virtual void v_finalize();
316         virtual void v_dump(std::ostream & os);
317         virtual TypeIdValue v_type();
318         virtual factory_t v_factory();
319         virtual factory_t v_nextPacketType();
320
321         // factory
322
323         /** \brief Internal: Implementation of abstract factory interface
324             
325             \internal
326
327             Implements the abstract factory interface for \a PacketType
328          */
329         struct FactoryImpl : public Factory {
330             // Create completely new packet
331
332             virtual PacketInterpreterBase::ptr create() const;
333             virtual PacketInterpreterBase::ptr create(NoInit_t) const;
334             virtual PacketInterpreterBase::ptr create(size_type size) const;
335             virtual PacketInterpreterBase::ptr create(size_type size,NoInit_t) const;
336             
337             // Create packet as new packet after a given packet
338
339             virtual PacketInterpreterBase::ptr createAfter(PacketInterpreterBase::ptr packet) 
340                 const;
341             virtual PacketInterpreterBase::ptr createAfter(PacketInterpreterBase::ptr packet, 
342                                                            NoInit_t) const;
343             virtual PacketInterpreterBase::ptr createAfter(PacketInterpreterBase::ptr packet, 
344                                                            size_type size) const;
345             virtual PacketInterpreterBase::ptr createAfter(PacketInterpreterBase::ptr packet, 
346                                                            size_type size, NoInit_t) const;
347             
348             // Create packet as new packet (header) before a given packet
349
350             virtual PacketInterpreterBase::ptr createBefore(PacketInterpreterBase::ptr packet) 
351                 const;
352             virtual PacketInterpreterBase::ptr createBefore(PacketInterpreterBase::ptr packet,
353                                                             NoInit_t) 
354                 const;
355
356             // Parse next packet in chain
357
358             virtual PacketInterpreterBase::ptr parseNext(PacketInterpreterBase::ptr packet) 
359                 const;
360         };
361
362         static const FactoryImpl factory_;
363
364         parser * parser_p();
365
366         boost::aligned_storage< sizeof(parser), 
367                                 boost::alignment_of<parser>::value > parserStorage_;
368
369         friend class detail::packet::test::TestDriver;
370         friend class PacketInterpreterBase;
371         friend class FactoryImpl;
372     };
373
374     /** \brief Invalid packet chain operation
375
376         This exception signals an invalid operation on the chain like trying to find a non-existent
377         chain member and other similar error conditions. 
378      */
379     struct InvalidPacketChainException : public std::exception
380     { virtual char const * what() const throw() { return "invalid packet chain"; } };
381     
382 }
383
384 ///////////////////////////////hh.e////////////////////////////////////////
385 #endif
386 #if !defined(SENF_PACKETS_DECL_ONLY) && !defined(HH_PacketInterpreter_i_)
387 #define HH_PacketInterpreter_i_
388 #include "PacketInterpreter.cci"
389 #include "PacketInterpreter.ct"
390 #include "PacketInterpreter.cti"
391 #endif
392
393 \f
394 // Local Variables:
395 // mode: c++
396 // fill-column: 100
397 // c-file-style: "senf"
398 // indent-tabs-mode: nil
399 // ispell-local-dictionary: "american"
400 // compile-command: "scons -u test"
401 // comment-column: 40
402 // End: