X-Git-Url: http://g0dil.de/git?a=blobdiff_plain;f=Packets%2FPacket.hh;h=bb2ac904cf3bd0c0e24d422c74cbb71cbb4d8422;hb=3593676775cfadb0094eb4f472c6ced0763e0068;hp=18b3020afeed6fbf711686466f19c1267db3157d;hpb=0734bd14c709ca5ba1d0ed69c5b9f5d1487e5faa;p=senf.git diff --git a/Packets/Packet.hh b/Packets/Packet.hh index 18b3020..bb2ac90 100644 --- a/Packets/Packet.hh +++ b/Packets/Packet.hh @@ -28,7 +28,8 @@ // Custom includes #include - +#include +#include #include "../Utils/Exception.hh" #include "../Utils/Tags.hh" #include "../Utils/safe_bool.hh" @@ -313,6 +314,66 @@ namespace senf { ///@} + ///\name Annotations + ///@{ + + template + 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().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) + + \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 ///@{ @@ -329,17 +390,72 @@ namespace senf { 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 + 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()) + \endcode */ + + void finalizeTo(Packet 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 @@ -465,6 +581,12 @@ namespace senf { \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 + static ConcretePacket create( + ForwardReadableRange const & range, + typename boost::disable_if< boost::is_integral >::type * = 0); +#else template static ConcretePacket create(ForwardReadableRange const & range); ///< Create packet from given data @@ -475,6 +597,7 @@ namespace senf { \param[in] range Boost.Range of data to construct packet from. */ +#endif // Create packet as new packet after a given packet @@ -516,6 +639,13 @@ namespace senf { \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 + static ConcretePacket createAfter( + Packet packet, + ForwardReadableRange const & range, + typename boost::disable_if< boost::is_integral >::type * = 0); +#else template static ConcretePacket createAfter(Packet packet, ForwardReadableRange const & range); @@ -530,6 +660,7 @@ namespace senf { \param[in] range Boost.Range of data to construct packet from. */ +#endif // Create packet as new packet (header) before a given packet