// $Id$
//
-// Copyright (C) 2007
-// Fraunhofer Institute for Open Communication Systems (FOKUS)
-// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Copyright (C) 2007
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
// Stefan Bund <g0dil@berlios.de>
//
// This program is free software; you can redistribute it and/or modify
/** \file
\brief Packet public header */
-#ifndef HH_Packet_
-#define HH_Packet_ 1
+#ifndef HH_SENF_Packets_Packet_
+#define HH_SENF_Packets_Packet_ 1
// Custom includes
#include <boost/operators.hpp>
-
+#include <boost/utility.hpp>
+#include <boost/type_traits/is_integral.hpp>
#include "../Utils/Exception.hh"
+#include "../Utils/Tags.hh"
#include "../Utils/safe_bool.hh"
#include "PacketInterpreter.hh"
/** \defgroup packet_module Packet Handling
- The basic groundwork of the Packet library is the packet handling:
+ The basic groundwork of the %Packet library is the packet handling:
\li The packet classes provide access to a chain of packet headers (more generically called
interpreters).
///\addtogroup packet_module
///@{
- /** \brief Main Packet class
+ /** \brief Main %Packet class
- Packet is the main externally visible class of the packet library. Packet is a handle into
- the internal packet representation. From Packet you may access the data of that specific
+ %Packet is the main externally visible class of the packet library. %Packet is a handle into
+ the internal packet representation. From %Packet you may access the data of that specific
sub-packet/header/interpreter and navigate to the neighboring
sub-packets/headers/interpreters.
- Packet is protocol agnostic. This class only provides non-protocol dependent members. To
+ %Packet is protocol agnostic. This class only provides non-protocol dependent members. To
access the protocol specific features of a packet (like header fields) the ConcretePacket
- class extending Packet is provided.
+ class extending %Packet is provided.
\section packet_semantics Semantics
\ref ConcretePacket < \ref EthernetPacketType >).
\see
- \ref ConcretePacket for the type specific interface\n
+ \ref ConcretePacket for the %type specific interface\n
\ref PacketData for the sequence interface\n
\ref packetparser for a specification of the parser interface
- */
+ */
class Packet
: public safe_bool<Packet>,
public boost::equality_comparable<Packet>
typedef void type; ///< Type of the packet.
typedef senf::detail::packet::size_type size_type;
- ///< Unsigned type to represent packet size
+ ///< Unsigned type to represent packet size
typedef PacketInterpreterBase::factory_t factory_t; ///< Packet factory type (see below)
- enum NoInit_t { noinit }; ///< Special argument flag
- /**< Used in some ConcretePacket constructors */
-
///////////////////////////////////////////////////////////////////////////
///\name Structors and default members
///@{
template <class PacketType>
Packet(ConcretePacket<PacketType> packet); ///< Copy-construct Packet from ConcretePacket
- /**< This constructor allows to convert an arbitrary
- ConcretePacket into a general Packet, loosing the
- protocol specific interface. */
+ /**< This constructor allows to convert an arbitrary
+ ConcretePacket into a general Packet, loosing the
+ protocol specific interface. */
///@}
///////////////////////////////////////////////////////////////////////////
///\name Interpreter chain access
///@{
- Packet next() const;
- ///< Get next packet in chain
- /**< \returns in - valid() packet, if no next packet
- exists */
- Packet next(NoThrow_t) const;
- ///< Get next packet in chain
- /**< \returns in - valid() packet, if no next packet
- exists */
+ Packet next() const;
+ ///< Get next packet in chain
+ /**< \throws InvalidPacketChainException if no next packet
+ exists */
+ Packet next(NoThrow_t) const;
+ ///< Get next packet in chain
+ /**< \returns in - valid() packet if no next packet
+ exists */
template <class OtherPacket> OtherPacket next() const;
- ///< Get next packet in chain and cast to \a OtherPacket
- /**< \throws std::bad_cast if the next() packet is not of
- type \a OtherPacket
- \returns in - valid() packet, if no next packet
- exists */
+ ///< Get next packet in chain and cast to \a OtherPacket
+ /**< \throws std::bad_cast if the next() packet is not of
+ type \a OtherPacket
+ \throws InvalidPacketChainException if no next packet
+ exists */
template <class OtherPacket> OtherPacket next(NoThrow_t) const;
- ///< Get next packet in chain and cast to \a OtherPacket
- /**< \throws std::bad_cast if the next() packet is not of
- type \a OtherPacket
- \returns in - valid() packet, if no next packet
- exists */
+ ///< Get next packet in chain and cast to \a OtherPacket
+ /**< \throws std::bad_cast if the next() packet is not of
+ type \a OtherPacket
+ \returns in - valid() packet if no next packet
+ exists */
template <class OtherPacket> OtherPacket find() const;
- ///< Search chain forward for packet of type \a OtherPacket
- /**< The search will start with the current packet.
- \returns in - valid() packet, if no packet of type \a
- OtherPacket can be found. */
+ ///< Search chain forward for packet of type \a OtherPacket
+ /**< The search will start with the current packet.
+ \throws InvalidPacketChainException if no packet of
+ type \a OtherPacket can be found. */
template <class OtherPacket> OtherPacket find(NoThrow_t) const;
- ///< Search chain forward for packet of type \a OtherPacket
- /**< The search will start with the current packet.
- \returns in - valid() packet, if no packet of type \a
- OtherPacket can be found. */
+ ///< Search chain forward for packet of type \a OtherPacket
+ /**< The search will start with the current packet.
+ \returns in - valid() packet if no packet of type \a
+ OtherPacket can be found. */
- Packet prev() const;
- ///< Get previous packet in chain
- /**< \returns in - valid() packet, if no previous packet
- exists */
- Packet prev(NoThrow_t) const;
- ///< Get previous packet in chain
- /**< \returns in - valid() packet, if no previous packet
- exists */
+ Packet prev() const;
+ ///< Get previous packet in chain
+ /**< \throws InvalidPacketChainException if no previous
+ packet exists */
+ Packet prev(NoThrow_t) const;
+ ///< Get previous packet in chain
+ /**< \returns in - valid() packet if no previous packet
+ exists */
template <class OtherPacket> OtherPacket prev() const;
- ///< Get previous packet in chain and cast to \a OtherPacket
- /**< \throws std::bad_cast, if the previous packet is not of
- type \a OtherPacket
- \returns in - valid() packet, if no previous packet
- exists */
+ ///< Get previous packet in chain and cast to \a OtherPacket
+ /**< \throws std::bad_cast, if the previous packet is not of
+ type \a OtherPacket
+ \throws InvalidPacketChainException if no previous
+ packet exists */
template <class OtherPacket> OtherPacket prev(NoThrow_t) const;
- ///< Get previous packet in chain and cast to \a OtherPacket
- /**< \throws std::bad_cast, if the previous packet is not of
- type \a OtherPacket
- \returns in - valid() packet, if no previous packet
- exists */
+ ///< Get previous packet in chain and cast to \a OtherPacket
+ /**< \throws std::bad_cast, if the previous packet is not of
+ type \a OtherPacket
+ \returns in - valid() packet if no previous packet
+ exists */
template <class OtherPacket> OtherPacket rfind() const;
- ///< Search chain backwards for packet of type \a OtherPacket
- /**< The search will start with the current packet.
- \returns in - valid() packet, if no packet of type \a
- OtherPacket can be found. */
+ ///< Search chain backwards for packet of type \a OtherPacket
+ /**< The search will start with the current packet.
+ \throws InvalidPacketChainException if no packet of
+ type \a OtherPacket can be found. */
template <class OtherPacket> OtherPacket rfind(NoThrow_t) const;
- ///< Search chain backwards for packet of type \a OtherPacket
- /**< The search will start with the current packet.
- \returns in - valid() packet, if no packet of type \a
- OtherPacket can be found. */
+ ///< Search chain backwards for packet of type \a OtherPacket
+ /**< The search will start with the current packet.
+ \returns in - valid() packet if no packet of type \a
+ OtherPacket can be found. */
- Packet first() const;
- ///< Return first packet in chain
+ Packet first() const;
+ ///< Return first packet in chain
template <class OtherPacket> OtherPacket first() const;
- ///< Return first packet in chain and cast
- /**< \throws std::bad_cast if the first() packet is not of
- type \a OtherPacket */
+ ///< Return first packet in chain and cast
+ /**< \throws std::bad_cast if the first() packet is not of
+ type \a OtherPacket */
- Packet last() const;
- ///< Return last packet in chain
+ Packet last() const;
+ ///< Return last packet in chain
template <class OtherPacket> OtherPacket last() const;
- ///< Return last packet in chain and cast
- /**< \throws std::bad_cast if the last() packet is not of
- type \a OtherPacket */
+ ///< Return last packet in chain and cast
+ /**< \throws std::bad_cast if the last() packet is not of
+ type \a OtherPacket */
template <class OtherPacket> OtherPacket parseNextAs() const;
- ///< Interpret payload of \c this as \a OtherPacket
- /**< parseNextAs() will throw away the packet chain after
- the current packet if necessary. It will then parse the
- payload section of \c this packet as given by \a
- OtherPacket. The new packet is added to the chain after
- \c this.
- \returns new packet instance sharing the same data and
- placed after \c this packet in the chain. */
- Packet parseNextAs(factory_t factory) const;
- ///< Interpret payload of \c this as \a factory type packet
- /**< parseNextAs() will throw away the packet chain after
- the current packet if necessary. It will then parse the
- payload section of \c this packet as given by \a
- factory. The new packet is added to the chain after
- \c this.
- \returns new packet instance sharing the same data and
- placed after \c this packet in the chain. */
+ ///< Interpret payload of \c this as \a OtherPacket
+ /**< parseNextAs() will throw away the packet chain after
+ the current packet if necessary. It will then parse the
+ payload section of \c this packet as given by \a
+ OtherPacket. The new packet is added to the chain after
+ \c this.
+ \returns new packet instance sharing the same data and
+ placed after \c this packet in the chain. */
+ Packet parseNextAs(factory_t factory) const;
+ ///< Interpret payload of \c this as \a factory type packet
+ /**< parseNextAs() will throw away the packet chain after
+ the current packet if necessary. It will then parse the
+ payload section of \c this packet as given by \a
+ factory. The new packet is added to the chain after
+ \c this.
+ \returns new packet instance sharing the same data and
+ placed after \c this packet in the chain. */
template <class OtherPacket> bool is() const;
- ///< Check, whether \c this packet is of the given type
+ ///< Check, whether \c this packet is of the given type
template <class OtherPacket> OtherPacket as() const;
- ///< Cast current packet to the given type
- /**< This operations returns a handle to the same packet
- header/interpreter however cast to the given
- ConcretePacket type.
- \throws std::bad_cast if the current packet is not of
- type \a OtherPacket */
-
- Packet append(Packet packet) const; ///< Append the given packet to \c this packet
- /**< This operation will replace the payload section of \c
- this packet with \a packet. This operation will replace
- the packet chain after \c this packet with a clone of
- \a packet and will replace the raw data of the payload
- of \c this with the raw data of \a packet. \c this
- packet will not share any date with \a packet.
- \returns Packet handle to the cloned \a packet, placed
- after \c this in the packet/header/interpreter
- chain. */
+ ///< Cast current packet to the given type
+ /**< This operations returns a handle to the same packet
+ header/interpreter however cast to the given
+ ConcretePacket type.
+ \throws std::bad_cast if the current packet is not of
+ type \a OtherPacket */
+
+ Packet append(Packet const & packet) const; ///< Append the given packet to \c this packet
+ /**< This operation will replace the payload section of \c
+ this packet with \a packet. This operation will replace
+ the packet chain after \c this packet with a clone of
+ \a packet and will replace the raw data of the payload
+ of \c this with the raw data of \a packet. \c this
+ packet will not share any date with \a packet.
+ \returns Packet handle to the cloned \a packet, placed
+ after \c this in the packet/header/interpreter
+ chain. */
///@}
///@}
+ ///\name Annotations
+ ///@{
+
+ template <class Annotation>
+ Annotation & annotation(); ///< Get packet annotation
+ /**< This member will retrieve an arbitrary packet
+ annotation. Every annotation is identified by a unique
+ \a Annotation type. This type should \e always be a \c
+ struct.
+
+ \code
+ struct MyAnnotation {
+ int value;
+ };
+
+ senf::Packet p (...);
+
+ p.annotation<MyAnnotation>().value = 1;
+ \endcode
+
+ Annotations are shared by all headers / interpreters
+ within a single packet chain.
+
+ If an annotation is \e not a POD type (more
+ specifically, if it's constructor or destructor is not
+ trivial including base classes and members), the \a
+ Annotation type \e must inherit from
+ senf::ComplexAnnotation. Failing to follow this rule
+ will result in undefined behavior and will probably
+ lead to a program crash.
+
+ \code
+ struct MyStringAnnotation : senf::ComplexAnnotation {
+ std::string value;
+ };
+ \endcode
+ (This type is not POD since \c std::string is not POD)
+
+ \see \ref packet_usage_annotation
+
+ \implementation The annotation system is implemented
+ quite efficiently since annotations are stored
+ within a packet embedded vector of fixed size (the
+ size is determined automatically at runtime by the
+ number of different annotations
+ used). Additionally, non-complex small annotations
+ require no additional memory management (\c new /
+ \c delete).
+
+ \idea Pool the annotation vectors: In the destructor
+ swap the vector into a vector graveyard (swapping
+ two vectors is an O(1) no allocation operation). In
+ the constructor, if there is a vector in the
+ graveyard, swap it in from there. Of course, it
+ would be better to do away with the vector and just
+ allocate the space together with the packet but
+ that looks quite complicated to do ... especially
+ considering that the packetimpl itself uses a pool.
+ */
+
+ ///@}
+
///\name Other methods
///@{
- bool operator==(Packet other) const; ///< Check for packet identity
- /**< Two packet handles compare equal if they really are the
- same packet header in the same packet chain. */
+ bool operator==(Packet const & other) const; ///< Check for packet identity
+ /**< Two packet handles compare equal if they really are the
+ same packet header in the same packet chain. */
bool boolean_test() const; ///< Check, whether the packet is valid()
/**< \see valid() */
bool valid() const; ///< Check, whether the packet is valid()
This is an alias for boolean_test() which is called
when using a packet in a boolean context. */
- void finalize() const; ///< Update calculated fields
- /**< This call will update all calculated fields of the
- packet after it has been created or changed. This
- includes checksums, payload size fields or other
- fields, which can be set from other information in the
- packet. Each concrete packet type should document,
- which fields are set by finalize().
-
- finalize() will automatically process all
+ void finalizeThis(); ///< Update calculated fields
+ /**< The finalize() fammily of members will update
+ calculated packet fields: checksums, size fields and so
+ on. This includes any field, which can be set from
+ other information in the packet. Each concrete packet
+ type should document, which fields are set by
+ finalize().
+
+ finalizeThis() will \e only process the current
+ header. Even if only changing fields in this protocol,
+ depending on the protocol it may not be enough to
+ finalize this header only. See the packet type
+ documentation. */
+
+ template <class Other>
+ void finalizeTo(); ///< Update calculated fields
+ /**< The finalize() fammily of members will update
+ calculated packet fields: checksums, size fields and so
+ on. This includes any field, which can be set from
+ other information in the packet. Each concrete packet
+ type should document, which fields are set by
+ finalize().
+
+ finalizeTo() will automatically process all
+ packets/headers/interpreters from the \e first
+ occurrence of packet type \a Other (beginning at \c
+ this packet searching forward towards deeper nested
+ packets) backwards up to \c this.
+
+ This call is equivalent to
+ \code
+ p.finalizeTo(p.next<Other>())
+ \endcode */
+
+ void finalizeTo(Packet const & other); ///< Update calculated fields
+ /**< The finalize() fammily of members will update
+ calculated packet fields: checksums, size fields and so
+ on. This includes any field, which can be set from
+ other information in the packet. Each concrete packet
+ type should document, which fields are set by
+ finalize().
+
+ finalizeTo(other) will automatically process all
+ packets/headers/interpreters beginning at \a other
+ backwards towards outer packets up to \c this. */
+
+ void finalizeAll(); ///< Update calculated fields
+ /**< The finalize() fammily of members will update
+ calculated packet fields: checksums, size fields and so
+ on. This includes any field, which can be set from
+ other information in the packet. Each concrete packet
+ type should document, which fields are set by
+ finalize().
+
+ finalizeAll() will automatically process all
packets/headers/interpreters from the end of the chain
- backwards up to \c this. */
+ (the most inner packet) backwards up to \c this.
+
+ This call is equivalent to
+ \code
+ p.finalizeTo(p.last())
+ \endcode
+
+ Beware, that finalizeAll() will \e not finalize any
+ headers before \c this, it will \e only process inner
+ headers. */
void dump(std::ostream & os) const; ///< Write out a printable packet representation
- /**< This method is provided mostly to help debugging packet
- problems. Each concrete packet should implement a dump
- method writing out all fields of the packet in a
- readable representation. dump() will call this member
- for each packet/header/interpreter in the chain from \c
- this packet up to the end of the chain. */
+ /**< This method is provided mostly to help debugging packet
+ problems. Each concrete packet should implement a dump
+ method writing out all fields of the packet in a
+ readable representation. dump() will call this member
+ for each packet/header/interpreter in the chain from \c
+ this packet up to the end of the chain. */
TypeIdValue typeId() const; ///< Get id of \c this packet
- /**< This value is used e.g. in the packet registry to
- associate packet types with other information.
- \returns A type holding the same information as a
- type_info object, albeit assignable */
+ /**< This value is used e.g. in the packet registry to
+ associate packet types with other information.
+ \returns A type holding the same information as a
+ type_info object, albeit assignable */
factory_t factory() const; ///< Return factory instance of \c this packet
- /**< The returned factory instance can be used to create new
- packets of the given type without knowing the concrete
- type of the packet. The value may be stored away for
- later use if needed. */
-
+ /**< The returned factory instance can be used to create new
+ packets of the given type without knowing the concrete
+ type of the packet. The value may be stored away for
+ later use if needed. */
+
///@}
protected:
private:
Packet checkNext() const;
Packet checkLast() const;
-
+
PacketInterpreterBase::ptr packet_;
-
+
template <class PacketType>
friend class ConcretePacket;
friend class PacketParserBase;
The new members provided by ConcretePacket over packet are mostly comprised of the packet
constructors. These come in three major flavors:
-
+
\li The create() family of constructors will create completely new packets.
\li The createAfter() family of constructors will create new packets (with new data for the
packet) \e after a given existing packet.
\li The createBefore() family of constructors will create new packets (again with new data)
\e before a given existing packet.
-
+
Whereas create() will create a completely new packet with it's own chain and data storage,
createAfter() and createBefore() extend a packet with additional
headers/interpreters. createAfter() will set the payload of the given packet to the new
createAfter() differs from Packet::parseNextAs() in that the former creates a new packet \e
replacing any possibly existing data whereas the latter will interpret the already \e
existing data as given by the type argument.
-
+
\see \ref PacketTypeBase for a specification of the interface to be provided by the \a
PacketType policy class.
- */
+ */
template <class PacketType>
class ConcretePacket
: public Packet
public:
///////////////////////////////////////////////////////////////////////////
// Types
-
+
typedef PacketType type;
typedef typename PacketType::parser Parser;
// no conversion constructors
ConcretePacket(); ///< Create uninitialized packet handle
- /**< An uninitialized handle is not valid(). It does not
- allow any operation except assignment and checking for
- validity. */
+ /**< An uninitialized handle is not valid(). It does not
+ allow any operation except assignment and checking for
+ validity. */
static factory_t factory(); ///< Return factory for packets of specific type
- /**< This \e static member is like Packet::factory() for a
- specific packet of type \a PacketType */
+ /**< This \e static member is like Packet::factory() for a
+ specific packet of type \a PacketType */
// Create completely new packet
static ConcretePacket create(); ///< Create default initialized packet
- /**< The packet will be initialized to it's default empty
- state. */
- static ConcretePacket create(NoInit_t); ///< Create uninitialized empty packet
- /**< This will create a completely empty and uninitialized
- packet with <tt>size() == 0</tt>.
- \param[in] noinit This parameter must always have the
- value \c senf::noinit. */
+ /**< The packet will be initialized to it's default empty
+ state. */
+ static ConcretePacket create(senf::NoInit_t); ///< Create uninitialized empty packet
+ /**< This will create a completely empty and uninitialized
+ packet with <tt>size() == 0</tt>.
+ \param[in] senf::noinit This parameter must always have the
+ value \c senf::noinit. */
static ConcretePacket create(size_type size); ///< Create default initialized packet
- /**< This member will create a default initialized packet
- with the given size. If the size parameter is smaller
- than the minimum allowed packet size an exception will
- be thrown.
- \param[in] size Size of the packet to create in bytes.
- \throws TruncatedPacketException if \a size is smaller
- than the smallest permissible size for this type of
- packet. */
- static ConcretePacket create(size_type size, NoInit_t); ///< Create uninitialized packet
- /**< Creates an uninitialized (all-zero) packet of the exact
- given size.
- \param[in] size Size of the packet to create in bytes
- \param[in] noinit This parameter must always have the
- value \c senf::noinit. */
+ /**< This member will create a default initialized packet
+ with the given size. If the size parameter is smaller
+ than the minimum allowed packet size an exception will
+ be thrown.
+ \param[in] size Size of the packet to create in bytes.
+ \throws TruncatedPacketException if \a size is smaller
+ than the smallest permissible size for this type of
+ packet. */
+ static ConcretePacket create(size_type size, senf::NoInit_t);
+ ///< Create uninitialized packet
+ /**< Creates an uninitialized (all-zero) packet of the exact
+ given size.
+ \param[in] size Size of the packet to create in bytes
+ \param[in] senf::noinit This parameter must always have the
+ value \c senf::noinit. */
+#ifndef DOXYGEN
+ template <class ForwardReadableRange>
+ static ConcretePacket create(
+ ForwardReadableRange const & range,
+ typename boost::disable_if< boost::is_integral<ForwardReadableRange> >::type * = 0);
+#else
template <class ForwardReadableRange>
static ConcretePacket create(ForwardReadableRange const & range);
- ///< Create packet from given data
- /**< The packet will be created from a copy of the given
- data. The data from the range will be copied directly
- into the packet representation. The data will \e not be
- validated in any way.
- \param[in] range <a
- href="http://www.boost.org/libs/range/index.html">Boost.Range</a>
- of data to construct packet from. */
+ ///< Create packet from given data
+ /**< The packet will be created from a copy of the given
+ data. The data from the range will be copied directly
+ into the packet representation. The data will \e not be
+ validated in any way.
+ \param[in] range <a
+ href="http://www.boost.org/libs/range/index.html">Boost.Range</a>
+ of data to construct packet from. */
+#endif
// Create packet as new packet after a given packet
- static ConcretePacket createAfter(Packet packet);
- ///< Create default initialized packet after \a packet
- /**< The packet will be initialized to it's default empty
- state. It will be appended as next header/interpreter
- after \a packet in that packets interpreter chain.
- \param[in] packet Packet to append new packet to. */
- static ConcretePacket createAfter(Packet packet, NoInit_t);
- ///< Create uninitialized empty packet after\a packet
- /**< This will create a completely empty and uninitialized
- packet with <tt>size() == 0</tt>. It will be appended
- as next header/interpreter after \a packet in that
- packets interpreter chain.
- \param[in] packet Packet to append new packet to.
- \param[in] noinit This parameter must always have the
- value \c senf::noinit. */
- static ConcretePacket createAfter(Packet packet, size_type size);
- ///< Create default initialized packet after \a packet
- /**< This member will create a default initialized packet
- with the given size. If the size parameter is smaller
- than the minimum allowed packet size an exception will
- be thrown. It will be appended as next
- header/interpreter after \a packet in that packets
- interpreter chain.
- \param[in] packet Packet to append new packet to.
- \param[in] size Size of the packet to create in bytes.
- \throws TruncatedPacketException if \a size is smaller
- than the smallest permissible size for this type of
- packet. */
- static ConcretePacket createAfter(Packet packet, size_type size, NoInit_t);
- ///< Create uninitialized packet after \a packet
- /**< Creates an uninitialized (all-zero) packet of the exact
- given size. It will be appended as next
- header/interpreter after \a packet in that packets
- interpreter chain.
- \param[in] packet Packet to append new packet to.
- \param[in] size Size of the packet to create in bytes
- \param[in] noinit This parameter must always have the
- value \c senf::noinit. */
+ static ConcretePacket createAfter(Packet const & packet);
+ ///< Create default initialized packet after \a packet
+ /**< The packet will be initialized to it's default empty
+ state. It will be appended as next header/interpreter
+ after \a packet in that packets interpreter chain.
+ \param[in] packet Packet to append new packet to. */
+ static ConcretePacket createAfter(Packet const & packet, senf::NoInit_t);
+ ///< Create uninitialized empty packet after\a packet
+ /**< This will create a completely empty and uninitialized
+ packet with <tt>size() == 0</tt>. It will be appended
+ as next header/interpreter after \a packet in that
+ packets interpreter chain.
+ \param[in] packet Packet to append new packet to.
+ \param[in] senf::noinit This parameter must always have the
+ value \c senf::noinit. */
+ static ConcretePacket createAfter(Packet const & packet, size_type size);
+ ///< Create default initialized packet after \a packet
+ /**< This member will create a default initialized packet
+ with the given size. If the size parameter is smaller
+ than the minimum allowed packet size an exception will
+ be thrown. It will be appended as next
+ header/interpreter after \a packet in that packets
+ interpreter chain.
+ \param[in] packet Packet to append new packet to.
+ \param[in] size Size of the packet to create in bytes.
+ \throws TruncatedPacketException if \a size is smaller
+ than the smallest permissible size for this type of
+ packet. */
+ static ConcretePacket createAfter(Packet const & packet, size_type size, senf::NoInit_t);
+ ///< Create uninitialized packet after \a packet
+ /**< Creates an uninitialized (all-zero) packet of the exact
+ given size. It will be appended as next
+ header/interpreter after \a packet in that packets
+ interpreter chain.
+ \param[in] packet Packet to append new packet to.
+ \param[in] size Size of the packet to create in bytes
+ \param[in] senf::noinit This parameter must always have the
+ value \c senf::noinit. */
+#ifndef DOXYGEN
template <class ForwardReadableRange>
- static ConcretePacket createAfter(Packet packet,
+ static ConcretePacket createAfter(
+ Packet const & packet,
+ ForwardReadableRange const & range,
+ typename boost::disable_if< boost::is_integral<ForwardReadableRange> >::type * = 0);
+#else
+ template <class ForwardReadableRange>
+ static ConcretePacket createAfter(Packet const & packet,
ForwardReadableRange const & range);
- ///< Create packet from given data after \a packet
- /**< The packet will be created from a copy of the given
- data. The data from the range will be copied directly
- into the packet representation. The data will \e not be
- validated in any way. It will be appended as next
- header/interpreter after \a packet in that packets
- interpreter chain.
- \param[in] packet Packet to append new packet to.
- \param[in] range <a
- href="http://www.boost.org/libs/range/index.html">Boost.Range</a>
- of data to construct packet from. */
+ ///< Create packet from given data after \a packet
+ /**< The packet will be created from a copy of the given
+ data. The data from the range will be copied directly
+ into the packet representation. The data will \e not be
+ validated in any way. It will be appended as next
+ header/interpreter after \a packet in that packets
+ interpreter chain.
+ \param[in] packet Packet to append new packet to.
+ \param[in] range <a
+ href="http://www.boost.org/libs/range/index.html">Boost.Range</a>
+ of data to construct packet from. */
+#endif
// Create packet as new packet (header) before a given packet
- static ConcretePacket createBefore(Packet packet);
- ///< Create default initialized packet before \a packet
- /**< The packet will be initialized to it's default empty
- state. It will be prepended as previous
- header/interpreter before \a packet in that packets
- interpreter chain.
- \param[in] packet Packet to prepend new packet to. */
- static ConcretePacket createBefore(Packet packet, NoInit_t);
- ///< Create uninitialized empty packet before \a packet
- /**< Creates a completely empty and uninitialized packet. It
- will be prepended as previous header/interpreter before
- \a packet in that packets interpreter chain.
- \param[in] packet Packet to prepend new packet to. */
+ static ConcretePacket createBefore(Packet const & packet);
+ ///< Create default initialized packet before \a packet
+ /**< The packet will be initialized to it's default empty
+ state. It will be prepended as previous
+ header/interpreter before \a packet in that packets
+ interpreter chain.
+ \param[in] packet Packet to prepend new packet to. */
+ static ConcretePacket createBefore(Packet const & packet, senf::NoInit_t);
+ ///< Create uninitialized empty packet before \a packet
+ /**< Creates a completely empty and uninitialized packet. It
+ will be prepended as previous header/interpreter before
+ \a packet in that packets interpreter chain.
+ \param[in] packet Packet to prepend new packet to. */
// Create a clone of the current packet
ConcretePacket clone() const;
-
+
///@}
///////////////////////////////////////////////////////////////////////////
-
+
// Field access
-
- Parser * operator->() const; ///< Access packet fields
+
+ struct ParserProxy
+ {
+ ParserProxy(Parser const & p) : p_ (p) {}
+ Parser * operator->() { return &p_; }
+ Parser p_;
+ };
+
+ ParserProxy operator->() const; ///< Access packet fields
/**< This operator allows to access the parsed fields of the
packet using the notation <tt>packet->field()</tt>. The
fields of the packet are specified by the PacketType's
/ recreation ...)
\see \ref packetparser for the parser interface. */
+ Parser parser() const; ///< Access packet field parser directly
+ /**< Access the parser of the packet. This is the same
+ object returned by the operator->() operator. The
+ operator however does not allow to access this object
+ itself, only it's members.
+ \see \ref packetparser for the parser interface */
+
protected:
private:
///////////////////////////////hh.e////////////////////////////////////////
#endif
-#if !defined(HH_Packets__decls_) && !defined(HH_Packet_i_)
-#define HH_Packet_i_
+#if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_Packet_i_)
+#define HH_SENF_Packets_Packet_i_
#include "Packet.cci"
#include "Packet.ct"
#include "Packet.cti"