namespace senf {
- /** \brief xxx
-
- \todo document me
- \todo add usefull exceptions strings
-
- */
- struct UnsuportedTLVPacketException : public senf::Exception
- { UnsuportedTLVPacketException()
- : senf::Exception("length of length can be max. 4 bytes. Sorry."){} };
-
- /** \brief xxx
- \todo document me
- */
+
+ struct TLVLengthException : public senf::Exception
+ { TLVLengthException()
+ : senf::Exception("TLVLengthException"){} };
+
+
class DynamicTLVLengthParser
: public detail::packet::IntParserOps<DynamicTLVLengthParser, boost::uint32_t>,
public PacketParserBase
size_type bytes() const;
void init() const;
- private:
- typedef FlagParser < 0 > ExtendedLengthFlagParser;
- typedef UIntFieldParser < 1, 8 > FixedLengthParser;
-
- ExtendedLengthFlagParser extended_length_flag() const {
- return parse<ExtendedLengthFlagParser>( 0 );
- }
+# include SENF_PARSER()
+ SENF_PARSER_PRIVATE_BITFIELD ( extended_length_flag, 1, bool );
+ SENF_PARSER_PRIVATE_BITFIELD ( fixed_length_field, 7, unsigned );
- FixedLengthParser fixed_length_field() const {
- return parse<FixedLengthParser>( 0 );
- }
-
+ void shrink();
+ void maxValue(DynamicTLVLengthParser::value_type v);
+ private:
void resize(size_type size);
};
- /** \brief parse TLVPacket Packet
-
- \todo document me
+
+ /** \brief Base class for TLV-Packet-Parsers
- \see TLVPacketType
+ BaseTLVPacketParser is the abstract base class for TLV-Packet-Parsers. It defines the
+ \ref type() field as an \ref senf::UInt8Parser and the \ref length() field as a
+ DynamicTLVLengthParser. The length field is read-only.
+
+ To create your own \c TLVParser you have to inherit from BaseTLVPacketParser (don't
+ forget \ref SENF_PARSER_INHERIT) and define the \c value field. In the following example
+ the value is a vector of MacAddresses:
+ \code
+ struct MacAddressesTLVParser : public BaseTLVPacketParser {
+ # include SENF_PARSER()
+ SENF_PARSER_INHERIT ( BaseTLVPacketParser );
+ SENF_PARSER_VECTOR ( value, bytes(length), senf::MACAddressParser );
+ SENF_PARSER_FINALIZE( MacAddressesTLVParser );
+ };
+
+ struct MacAddressesTLVPacketType : public PacketTypeBase {
+ typedef MacAddressesTLVParser parser;
+ ...
+ static void finalize(ConcretePacket<MacAddressesTLVPacketType> p) {
+ p->shrinkLength();
+ }
+ };
+ \endcode
+
+ You have to adjust the maximum length value with the \ref maxLengthValue function
+ before the length value is set. The default maximum value is 127. So, in the above
+ example adding more than 21 MACAddresses to the vector will throw a TLVLengthException
+ if you don't call \c macAddressesTLVPacket->maxLengthValue( \e some_value) before.
+
+ \see DynamicTLVLengthParser \n
+ GenericTLVPacketParser \n
*/
- template <class TypeParser, class LengthParser>
- struct TLVPacketParser : public PacketParserBase
+ class BaseTLVPacketParser : public PacketParserBase
{
+ public:
# include SENF_PARSER()
+ SENF_PARSER_FIELD ( type, UInt8Parser );
+ SENF_PARSER_FIELD_RO ( length, DynamicTLVLengthParser );
+ SENF_PARSER_FINALIZE ( BaseTLVPacketParser );
- SENF_PARSER_FIELD( type, TypeParser );
- SENF_PARSER_FIELD( length, LengthParser );
+ /** \brief set maximum value of length field
+
+ The size of the length field will be increased if necessary.
+ \param v maximum value of length field
+ */
+ void maxLengthValue(DynamicTLVLengthParser::value_type v) const {
+ length_().maxValue(v);
+ }
- SENF_PARSER_FINALIZE(TLVPacketParser);
- };
+ /** \brief shrink size of length field to minimum
- /** \brief generic TLV Packet type
+ The size of the length field will be decreased to minimum necessary to hold
+ the current length value.
+ */
+ void shrinkLength() {
+ length_().shrink();
+ };
+
+ protected:
+ /// return size of length field
+ size_type length_bytes() const { return length_().bytes(); };
+ /// set length field to given value
+ void length(DynamicTLVLengthParser::value_type &v) { length_() = v; };
+ /// resize the Packet after the length field to given size
+ senf::safe_data_iterator resizeValue(DynamicTLVLengthParser::value_type size);
+ };
+
+
+ /** \brief Parser for a generic TLV packet
+
+ \see GenericTLVPacketType
+ */
+ struct GenericTLVPacketParser : public BaseTLVPacketParser
+ {
+# include SENF_PARSER()
+ SENF_PARSER_INHERIT ( BaseTLVPacketParser );
+ SENF_PARSER_SKIP ( length(), 0 );
+ SENF_PARSER_FINALIZE ( GenericTLVPacketParser );
+
+ SENF_PARSER_INIT() {
+ maxLengthValue( DynamicTLVLengthParser::max_value);
+ }
- \todo document me
+ senf::PacketInterpreterBase::range value() const;
- \ingroup protocolbundle_mpegdvb
+ template <class ForwardReadableRange>
+ void value(ForwardReadableRange const &range);
+ };
+
+ /** \brief Generic TLV packet
+
+ \par Packet type (typedef):
+ \ref GenericTLVPacket
+
+ \image html TLV.png
+
+ \ingroup protocolbundle_80221
*/
- template <class TypeParser, class LengthParser>
- struct TLVPacketType
- : public PacketTypeBase
+ struct GenericTLVPacketType
+ : public PacketTypeBase,
+ public PacketTypeMixin<GenericTLVPacketType>
{
- typedef ConcretePacket<TLVPacketType<TypeParser, LengthParser> > packet;
- typedef TLVPacketParser<TypeParser, LengthParser> parser;
+#ifndef DOXYGEN
+ typedef PacketTypeMixin<GenericTLVPacketType> mixin;
+#endif
+ typedef ConcretePacket<GenericTLVPacketType> packet; ///< GenericTLV packet typedef
+ typedef GenericTLVPacketParser parser; ///< typedef to the parser of GenericTLV packet
- static optional_range nextPacketRange(packet p);
- static size_type initSize();
+ using mixin::nextPacketRange;
+ using mixin::init;
+ using mixin::initSize;
- static void finalize(packet p);
+ /** \brief Dump given GenericTLVPacket in readable form to given output stream */
+ static void dump(packet p, std::ostream & os);
+ static void finalize(packet p); ///< Finalize packet.
+ /**< shrink size of length field to minimum
+ \see BaseTLVPacketParser::shrinkLength() */
- static void dump(packet p, std::ostream & os);
};
- typedef ConcretePacket<TLVPacketType<UInt32Parser, DynamicTLVLengthParser> > MIHInfoElement;
+ /** \brief GenericTLV packet typedef */
+ typedef ConcretePacket<GenericTLVPacketType> GenericTLVPacket;
}