2 // Fraunhofer Institut fuer offene Kommunikationssysteme (FOKUS)
3 // Kompetenzzentrum fuer Satelitenkommunikation (SatCom)
4 // Stefan Bund <g0dil@berlios.de>
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.
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.
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.
22 \brief PacketInterpreter public header */
24 #ifndef HH_PacketInterpreter_
25 #define HH_PacketInterpreter_ 1
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"
38 //#include "PacketInterpreter.mpp"
39 ///////////////////////////////hh.p////////////////////////////////////////
43 template <class PacketType> class PacketInterpreter;
45 /** \brief Internal: Base packet interpreter class
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.
52 class PacketInterpreterBase
53 : protected PacketData,
54 public detail::packet::interpreter_list_base,
55 public intrusive_refcount_t<PacketInterpreterBase>
58 ///////////////////////////////////////////////////////////////////////////
61 typedef senf::detail::packet::smart_pointer<
62 PacketInterpreterBase>::ptr_t ptr;
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;
70 typedef boost::iterator_range<iterator> range;
71 typedef boost::optional< boost::iterator_range<iterator> > optional_range;
72 typedef optional_range no_range;
74 enum Append_t { Append };
75 enum Prepend_t { Prepend };
76 enum NoInit_t { noinit };
78 /** \brief Internal: Abstract packet factory
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.
89 // Create completely new packet
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;
98 // Create packet as new packet after a given packet
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,
105 template <class ForwardReadableRange>
106 ptr createAfter(PacketInterpreterBase::ptr packet,
107 ForwardReadableRange const & range) const;
109 // Create packet as new packet (header) const before a given packet
111 virtual ptr createBefore(PacketInterpreterBase::ptr packet) const = 0;
112 virtual ptr createBefore(PacketInterpreterBase::ptr packet, NoInit_t) const = 0;
114 // Parse next packet in chain
116 virtual ptr parseNext(ptr packet) const = 0;
119 typedef Factory const * factory_t;
121 ///////////////////////////////////////////////////////////////////////////
122 ///\name Structors and default members
125 // protected constructors
127 // no conversion constructors
129 virtual ~PacketInterpreterBase();
131 static factory_t no_factory();
136 ///////////////////////////////////////////////////////////////////////////
138 ///\name Interpreter chain access
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();
151 ptr append(ptr packet);
158 using PacketData::valid;
163 ///\name Access to the abstract interface
166 optional_range nextPacketRange();
168 void dump(std::ostream & os);
169 TypeIdValue typeId();
171 factory_t nextPacketType();
176 // protected structors
178 PacketInterpreterBase(detail::PacketImpl * impl, iterator b, iterator e, Append_t);
179 PacketInterpreterBase(detail::PacketImpl * impl, iterator b, iterator e, Prepend_t);
181 ptr appendClone(detail::PacketImpl * impl, iterator base, iterator new_base);
182 ptr appendClone(detail::PacketImpl * impl, range r);
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;
190 // abstract packet type interface
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;
201 // reference/memory management. Only to be called by intrusive_refcount_t.
206 // containment management. Only to be called by PacketImpl.
208 void assignImpl(detail::PacketImpl *);
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;
218 /** \brief Internal: Concrete packet interpreter
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.
226 \see PacketTypeBase for the \a PacketType interface
228 template <class PacketType>
229 class PacketInterpreter
230 : public PacketInterpreterBase,
231 public pool_alloc_mixin< PacketInterpreter<PacketType> >
234 ///////////////////////////////////////////////////////////////////////////
237 typedef typename senf::detail::packet::smart_pointer<
238 PacketInterpreter>::ptr_t ptr;
239 typedef PacketType type;
240 typedef typename type::parser parser;
242 ///////////////////////////////////////////////////////////////////////////
243 ///\name Structors and default members
246 // private constructors
248 // no conversion constructors
250 ~PacketInterpreter();
252 static factory_t factory();
254 // Create completely new packet
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);
263 // Create packet as new packet after a given packet
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);
273 // Create packet as new packet (header) before a given packet
275 static ptr createBefore(PacketInterpreterBase::ptr packet);
276 static ptr createBefore(PacketInterpreterBase::ptr packet, NoInit_t);
278 // Create a clone of the current packet
283 ///////////////////////////////////////////////////////////////////////////
285 // Packet field access
292 static size_type initSize();
293 static size_type initHeadSize();
300 PacketInterpreter(detail::PacketImpl * impl, iterator b, iterator e, Append_t);
301 PacketInterpreter(detail::PacketImpl * impl, iterator b, iterator e, Prepend_t);
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);
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();
324 /** \brief Internal: Implementation of abstract factory interface
328 Implements the abstract factory interface for \a PacketType
330 struct FactoryImpl : public Factory {
331 // Create completely new packet
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;
338 // Create packet as new packet after a given packet
340 virtual PacketInterpreterBase::ptr createAfter(PacketInterpreterBase::ptr packet)
342 virtual PacketInterpreterBase::ptr createAfter(PacketInterpreterBase::ptr packet,
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;
349 // Create packet as new packet (header) before a given packet
351 virtual PacketInterpreterBase::ptr createBefore(PacketInterpreterBase::ptr packet)
353 virtual PacketInterpreterBase::ptr createBefore(PacketInterpreterBase::ptr packet,
357 // Parse next packet in chain
359 virtual PacketInterpreterBase::ptr parseNext(PacketInterpreterBase::ptr packet)
363 static const FactoryImpl factory_;
367 boost::aligned_storage< sizeof(parser),
368 boost::alignment_of<parser>::value > parserStorage_;
370 friend class detail::packet::test::TestDriver;
371 friend class PacketInterpreterBase;
372 friend class FactoryImpl;
375 /** \brief Invalid packet chain operation
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.
380 struct InvalidPacketChainException : public std::exception
381 { virtual char const * what() const throw() { return "invalid packet chain"; } };
385 ///////////////////////////////hh.e////////////////////////////////////////
387 #if !defined(HH_Packets__decls_) && !defined(HH_PacketInterpreter_i_)
388 #define HH_PacketInterpreter_i_
389 #include "PacketInterpreter.cci"
390 #include "PacketInterpreter.ct"
391 #include "PacketInterpreter.cti"
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