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 "../Utils/Tags.hh"
38 #include "PacketData.hh"
39 #include "../Utils/TypeIdValue.hh"
41 //#include "PacketInterpreter.mpp"
42 ///////////////////////////////hh.p////////////////////////////////////////
46 template <class PacketType> class PacketInterpreter;
48 /** \brief Internal: Base packet interpreter class
52 This is the base class for the persistent interpreter. This class encapsulates all the
53 functionality accessible via the packet handle, most handle operations are just forwarded.
55 class PacketInterpreterBase
56 : protected PacketData,
57 public detail::packet::interpreter_list_base,
58 public intrusive_refcount_t<PacketInterpreterBase>
61 ///////////////////////////////////////////////////////////////////////////
64 typedef senf::detail::packet::smart_pointer<
65 PacketInterpreterBase>::ptr_t ptr;
67 typedef senf::detail::packet::iterator iterator;
68 typedef senf::detail::packet::const_iterator const_iterator;
69 typedef senf::detail::packet::size_type size_type;
70 typedef senf::detail::packet::difference_type difference_type;
71 typedef senf::detail::packet::byte byte;
73 typedef boost::iterator_range<iterator> range;
74 typedef boost::optional< boost::iterator_range<iterator> > optional_range;
75 typedef optional_range no_range;
77 enum Append_t { Append };
78 enum Prepend_t { Prepend };
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(senf::NoInit_t) const = 0;
95 virtual ptr create(size_type size) const = 0;
96 virtual ptr create(size_type size, senf::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, senf::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,
106 senf::NoInit_t) const = 0;
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, senf::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 finalizeTo(ptr other);
171 void dump(std::ostream & os);
172 TypeIdValue typeId();
174 factory_t nextPacketType();
179 // protected structors
181 PacketInterpreterBase(detail::PacketImpl * impl, iterator b, iterator e, Append_t);
182 PacketInterpreterBase(detail::PacketImpl * impl, iterator b, iterator e, Prepend_t);
184 ptr appendClone(detail::PacketImpl * impl, iterator base, iterator new_base);
185 ptr appendClone(detail::PacketImpl * impl, range r);
188 // Need this for g++ < 4.0. Since PacketInterpreter is not publicly visible, it should not
189 // be a real problem to make impl() public here
190 using PacketData::impl;
193 // abstract packet type interface
195 virtual optional_range v_nextPacketRange() = 0;
196 virtual ptr v_appendClone(detail::PacketImpl * impl, iterator base, iterator new_base) = 0;
197 virtual ptr v_appendClone(detail::PacketImpl * impl, range r) =0;
198 virtual void v_finalize() = 0;
199 virtual void v_dump(std::ostream & os) = 0;
200 virtual TypeIdValue v_type() = 0;
201 virtual factory_t v_factory() = 0;
202 virtual factory_t v_nextPacketType() = 0;
204 // reference/memory management. Only to be called by intrusive_refcount_t.
209 // containment management. Only to be called by PacketImpl.
211 void assignImpl(detail::PacketImpl *);
214 friend class detail::PacketImpl;
215 friend class intrusive_refcount_base;
216 template <class PacketType> friend class PacketInterpreter;
217 friend class detail::packet::test::TestDriver;
218 friend class PacketParserBase;
221 /** \brief Internal: Concrete packet interpreter
225 Instantiations of this class build the interpreter chain. This class is accessed by the
226 packet handles. It provides the packet-type specific functionality in addition to the
227 interface defined in the PacketInterpreterBase class.
229 \see PacketTypeBase for the \a PacketType interface
231 template <class PacketType>
232 class PacketInterpreter
233 : public PacketInterpreterBase,
234 public pool_alloc_mixin< PacketInterpreter<PacketType> >
237 ///////////////////////////////////////////////////////////////////////////
240 typedef typename senf::detail::packet::smart_pointer<
241 PacketInterpreter>::ptr_t ptr;
242 typedef PacketType type;
243 typedef typename type::parser parser;
245 ///////////////////////////////////////////////////////////////////////////
246 ///\name Structors and default members
249 // private constructors
251 // no conversion constructors
253 ~PacketInterpreter();
255 static factory_t factory();
257 // Create completely new packet
260 static ptr create(senf::NoInit_t);
261 static ptr create(size_type size);
262 static ptr create(size_type size, senf::NoInit_t);
263 template <class ForwardReadableRange>
264 static ptr create(ForwardReadableRange const & range);
266 // Create packet as new packet after a given packet
268 static ptr createAfter(PacketInterpreterBase::ptr packet);
269 static ptr createAfter(PacketInterpreterBase::ptr packet, senf::NoInit_t);
270 static ptr createAfter(PacketInterpreterBase::ptr packet, size_type size);
271 static ptr createAfter(PacketInterpreterBase::ptr packet, size_type size, senf::NoInit_t);
272 template <class ForwardReadableRange>
273 static ptr createAfter(PacketInterpreterBase::ptr packet,
274 ForwardReadableRange const & range);
276 // Create packet as new packet (header) before a given packet
278 static ptr createBefore(PacketInterpreterBase::ptr packet);
279 static ptr createBefore(PacketInterpreterBase::ptr packet, senf::NoInit_t);
281 // Create a clone of the current packet
286 ///////////////////////////////////////////////////////////////////////////
288 // Packet field access
295 static size_type initSize();
296 static size_type initHeadSize();
303 PacketInterpreter(detail::PacketImpl * impl, iterator b, iterator e, Append_t);
304 PacketInterpreter(detail::PacketImpl * impl, iterator b, iterator e, Prepend_t);
306 static ptr create(detail::PacketImpl * impl, iterator b, iterator e, Append_t);
307 static ptr create(detail::PacketImpl * impl, iterator b, iterator e, Prepend_t);
315 virtual optional_range v_nextPacketRange();
316 virtual PacketInterpreterBase::ptr v_appendClone(detail::PacketImpl * impl,
317 iterator base, iterator new_base);
318 virtual PacketInterpreterBase::ptr v_appendClone(detail::PacketImpl * impl, range r);
319 virtual void v_finalize();
320 virtual void v_dump(std::ostream & os);
321 virtual TypeIdValue v_type();
322 virtual factory_t v_factory();
323 virtual factory_t v_nextPacketType();
327 /** \brief Internal: Implementation of abstract factory interface
331 Implements the abstract factory interface for \a PacketType
333 struct FactoryImpl : public Factory {
334 // Create completely new packet
336 virtual PacketInterpreterBase::ptr create() const;
337 virtual PacketInterpreterBase::ptr create(senf::NoInit_t) const;
338 virtual PacketInterpreterBase::ptr create(size_type size) const;
339 virtual PacketInterpreterBase::ptr create(size_type size,senf::NoInit_t) const;
341 // Create packet as new packet after a given packet
343 virtual PacketInterpreterBase::ptr createAfter(PacketInterpreterBase::ptr packet)
345 virtual PacketInterpreterBase::ptr createAfter(PacketInterpreterBase::ptr packet,
346 senf::NoInit_t) const;
347 virtual PacketInterpreterBase::ptr createAfter(PacketInterpreterBase::ptr packet,
348 size_type size) const;
349 virtual PacketInterpreterBase::ptr createAfter(PacketInterpreterBase::ptr packet,
350 size_type size, senf::NoInit_t) const;
352 // Create packet as new packet (header) before a given packet
354 virtual PacketInterpreterBase::ptr createBefore(PacketInterpreterBase::ptr packet)
356 virtual PacketInterpreterBase::ptr createBefore(PacketInterpreterBase::ptr packet,
360 // Parse next packet in chain
362 virtual PacketInterpreterBase::ptr parseNext(PacketInterpreterBase::ptr packet)
366 static const FactoryImpl factory_;
370 boost::aligned_storage< sizeof(parser),
371 boost::alignment_of<parser>::value > parserStorage_;
373 friend class detail::packet::test::TestDriver;
374 friend class PacketInterpreterBase;
375 friend class FactoryImpl;
378 /** \brief Invalid packet chain operation
380 This exception signals an invalid operation on the chain like trying to find a non-existent
381 chain member and other similar error conditions.
383 struct InvalidPacketChainException : public senf::Exception
384 { InvalidPacketChainException() : senf::Exception("invalid packet chain"){} };
388 ///////////////////////////////hh.e////////////////////////////////////////
390 #if !defined(HH_Packets__decls_) && !defined(HH_PacketInterpreter_i_)
391 #define HH_PacketInterpreter_i_
392 #include "PacketInterpreter.cci"
393 #include "PacketInterpreter.ct"
394 #include "PacketInterpreter.cti"
401 // c-file-style: "senf"
402 // indent-tabs-mode: nil
403 // ispell-local-dictionary: "american"
404 // compile-command: "scons -u test"
405 // comment-column: 40