4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Stefan Bund <g0dil@berlios.de>
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.
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.
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.
24 \brief PacketInterpreter public header */
26 #ifndef HH_PacketInterpreter_
27 #define HH_PacketInterpreter_ 1
30 #include "../boost/intrusive/ilist.hpp"
31 #include <boost/optional.hpp>
32 #include <boost/range.hpp>
33 #include <boost/type_traits/aligned_storage.hpp>
34 #include <boost/type_traits/alignment_of.hpp>
35 #include "../Utils/intrusive_refcount.hh"
36 #include "../Utils/pool_alloc_mixin.hh"
37 #include "PacketData.hh"
38 #include "../Utils/TypeIdValue.hh"
40 //#include "PacketInterpreter.mpp"
41 ///////////////////////////////hh.p////////////////////////////////////////
45 template <class PacketType> class PacketInterpreter;
47 /** \brief Internal: Base packet interpreter class
51 This is the base class for the persistent interpreter. This class encapsulates all the
52 functionality accessible via the packet handle, most handle operations are just forwarded.
54 class PacketInterpreterBase
55 : protected PacketData,
56 public detail::packet::interpreter_list_base,
57 public intrusive_refcount_t<PacketInterpreterBase>
60 ///////////////////////////////////////////////////////////////////////////
63 typedef senf::detail::packet::smart_pointer<
64 PacketInterpreterBase>::ptr_t ptr;
66 typedef senf::detail::packet::iterator iterator;
67 typedef senf::detail::packet::const_iterator const_iterator;
68 typedef senf::detail::packet::size_type size_type;
69 typedef senf::detail::packet::difference_type difference_type;
70 typedef senf::detail::packet::byte byte;
72 typedef boost::iterator_range<iterator> range;
73 typedef boost::optional< boost::iterator_range<iterator> > optional_range;
74 typedef optional_range no_range;
76 enum Append_t { Append };
77 enum Prepend_t { Prepend };
78 enum NoInit_t { noinit };
80 /** \brief Internal: Abstract packet factory
84 This abstract class provides an abstract packet factory interface. It allows to call
85 almost any one of the create / createAfter / createBefore static PacketInterpreter
86 without static information on the type of packet to create.
91 // Create completely new packet
93 virtual ptr create() const = 0;
94 virtual ptr create(NoInit_t) const = 0;
95 virtual ptr create(size_type size) const = 0;
96 virtual ptr create(size_type size, NoInit_t) const = 0;
97 template <class ForwardReadableRange>
98 ptr create(ForwardReadableRange const & range) const;
100 // Create packet as new packet after a given packet
102 virtual ptr createAfter(PacketInterpreterBase::ptr packet) const = 0;
103 virtual ptr createAfter(PacketInterpreterBase::ptr packet, NoInit_t) const = 0;
104 virtual ptr createAfter(PacketInterpreterBase::ptr packet, size_type size) const = 0;
105 virtual ptr createAfter(PacketInterpreterBase::ptr packet, size_type size,
107 template <class ForwardReadableRange>
108 ptr createAfter(PacketInterpreterBase::ptr packet,
109 ForwardReadableRange const & range) const;
111 // Create packet as new packet (header) const before a given packet
113 virtual ptr createBefore(PacketInterpreterBase::ptr packet) const = 0;
114 virtual ptr createBefore(PacketInterpreterBase::ptr packet, NoInit_t) const = 0;
116 // Parse next packet in chain
118 virtual ptr parseNext(ptr packet) const = 0;
121 typedef Factory const * factory_t;
123 ///////////////////////////////////////////////////////////////////////////
124 ///\name Structors and default members
127 // protected constructors
129 // no conversion constructors
131 virtual ~PacketInterpreterBase();
133 static factory_t no_factory();
138 ///////////////////////////////////////////////////////////////////////////
140 ///\name Interpreter chain access
148 template <class Type> typename PacketInterpreter<Type>::ptr parseNextAs();
149 ptr parseNextAs(factory_t factory);
150 template <class Type> bool is();
151 template <class Type> typename PacketInterpreter<Type>::ptr as();
153 ptr append(ptr packet);
160 using PacketData::valid;
165 ///\name Access to the abstract interface
168 optional_range nextPacketRange();
170 void dump(std::ostream & os);
171 TypeIdValue typeId();
173 factory_t nextPacketType();
178 // protected structors
180 PacketInterpreterBase(detail::PacketImpl * impl, iterator b, iterator e, Append_t);
181 PacketInterpreterBase(detail::PacketImpl * impl, iterator b, iterator e, Prepend_t);
183 ptr appendClone(detail::PacketImpl * impl, iterator base, iterator new_base);
184 ptr appendClone(detail::PacketImpl * impl, range r);
187 // Need this for g++ < 4.0. Since PacketInterpreter is not publicly visible, it should not
188 // be a real problem to make impl() public here
189 using PacketData::impl;
192 // abstract packet type interface
194 virtual optional_range v_nextPacketRange() = 0;
195 virtual ptr v_appendClone(detail::PacketImpl * impl, iterator base, iterator new_base) = 0;
196 virtual ptr v_appendClone(detail::PacketImpl * impl, range r) =0;
197 virtual void v_finalize() = 0;
198 virtual void v_dump(std::ostream & os) = 0;
199 virtual TypeIdValue v_type() = 0;
200 virtual factory_t v_factory() = 0;
201 virtual factory_t v_nextPacketType() = 0;
203 // reference/memory management. Only to be called by intrusive_refcount_t.
208 // containment management. Only to be called by PacketImpl.
210 void assignImpl(detail::PacketImpl *);
213 friend class detail::PacketImpl;
214 friend class intrusive_refcount_t<PacketInterpreterBase>;
215 template <class PacketType> friend class PacketInterpreter;
216 friend class detail::packet::test::TestDriver;
217 friend class PacketParserBase;
220 /** \brief Internal: Concrete packet interpreter
224 Instantiations of this class build the interpreter chain. This class is accessed by the
225 packet handles. It provides the packet-type specific functionality in addition to the
226 interface defined in the PacketInterpreterBase class.
228 \see PacketTypeBase for the \a PacketType interface
230 template <class PacketType>
231 class PacketInterpreter
232 : public PacketInterpreterBase,
233 public pool_alloc_mixin< PacketInterpreter<PacketType> >
236 ///////////////////////////////////////////////////////////////////////////
239 typedef typename senf::detail::packet::smart_pointer<
240 PacketInterpreter>::ptr_t ptr;
241 typedef PacketType type;
242 typedef typename type::parser parser;
244 ///////////////////////////////////////////////////////////////////////////
245 ///\name Structors and default members
248 // private constructors
250 // no conversion constructors
252 ~PacketInterpreter();
254 static factory_t factory();
256 // Create completely new packet
259 static ptr create(NoInit_t);
260 static ptr create(size_type size);
261 static ptr create(size_type size, NoInit_t);
262 template <class ForwardReadableRange>
263 static ptr create(ForwardReadableRange const & range);
265 // Create packet as new packet after a given packet
267 static ptr createAfter(PacketInterpreterBase::ptr packet);
268 static ptr createAfter(PacketInterpreterBase::ptr packet, NoInit_t);
269 static ptr createAfter(PacketInterpreterBase::ptr packet, size_type size);
270 static ptr createAfter(PacketInterpreterBase::ptr packet, size_type size, NoInit_t);
271 template <class ForwardReadableRange>
272 static ptr createAfter(PacketInterpreterBase::ptr packet,
273 ForwardReadableRange const & range);
275 // Create packet as new packet (header) before a given packet
277 static ptr createBefore(PacketInterpreterBase::ptr packet);
278 static ptr createBefore(PacketInterpreterBase::ptr packet, NoInit_t);
280 // Create a clone of the current packet
285 ///////////////////////////////////////////////////////////////////////////
287 // Packet field access
294 static size_type initSize();
295 static size_type initHeadSize();
302 PacketInterpreter(detail::PacketImpl * impl, iterator b, iterator e, Append_t);
303 PacketInterpreter(detail::PacketImpl * impl, iterator b, iterator e, Prepend_t);
305 static ptr create(detail::PacketImpl * impl, iterator b, iterator e, Append_t);
306 static ptr create(detail::PacketImpl * impl, iterator b, iterator e, Prepend_t);
314 virtual optional_range v_nextPacketRange();
315 virtual PacketInterpreterBase::ptr v_appendClone(detail::PacketImpl * impl,
316 iterator base, iterator new_base);
317 virtual PacketInterpreterBase::ptr v_appendClone(detail::PacketImpl * impl, range r);
318 virtual void v_finalize();
319 virtual void v_dump(std::ostream & os);
320 virtual TypeIdValue v_type();
321 virtual factory_t v_factory();
322 virtual factory_t v_nextPacketType();
326 /** \brief Internal: Implementation of abstract factory interface
330 Implements the abstract factory interface for \a PacketType
332 struct FactoryImpl : public Factory {
333 // Create completely new packet
335 virtual PacketInterpreterBase::ptr create() const;
336 virtual PacketInterpreterBase::ptr create(NoInit_t) const;
337 virtual PacketInterpreterBase::ptr create(size_type size) const;
338 virtual PacketInterpreterBase::ptr create(size_type size,NoInit_t) const;
340 // Create packet as new packet after a given packet
342 virtual PacketInterpreterBase::ptr createAfter(PacketInterpreterBase::ptr packet)
344 virtual PacketInterpreterBase::ptr createAfter(PacketInterpreterBase::ptr packet,
346 virtual PacketInterpreterBase::ptr createAfter(PacketInterpreterBase::ptr packet,
347 size_type size) const;
348 virtual PacketInterpreterBase::ptr createAfter(PacketInterpreterBase::ptr packet,
349 size_type size, NoInit_t) const;
351 // Create packet as new packet (header) before a given packet
353 virtual PacketInterpreterBase::ptr createBefore(PacketInterpreterBase::ptr packet)
355 virtual PacketInterpreterBase::ptr createBefore(PacketInterpreterBase::ptr packet,
359 // Parse next packet in chain
361 virtual PacketInterpreterBase::ptr parseNext(PacketInterpreterBase::ptr packet)
365 static const FactoryImpl factory_;
369 boost::aligned_storage< sizeof(parser),
370 boost::alignment_of<parser>::value > parserStorage_;
372 friend class detail::packet::test::TestDriver;
373 friend class PacketInterpreterBase;
374 friend class FactoryImpl;
377 /** \brief Invalid packet chain operation
379 This exception signals an invalid operation on the chain like trying to find a non-existent
380 chain member and other similar error conditions.
382 struct InvalidPacketChainException : public std::exception
383 { virtual char const * what() const throw() { return "invalid packet chain"; } };
387 ///////////////////////////////hh.e////////////////////////////////////////
389 #if !defined(HH_Packets__decls_) && !defined(HH_PacketInterpreter_i_)
390 #define HH_PacketInterpreter_i_
391 #include "PacketInterpreter.cci"
392 #include "PacketInterpreter.ct"
393 #include "PacketInterpreter.cti"
400 // c-file-style: "senf"
401 // indent-tabs-mode: nil
402 // ispell-local-dictionary: "american"
403 // compile-command: "scons -u test"
404 // comment-column: 40