#define HH_SENF_Packets_GenericTLV_ 1
// Custom includes
+#include <boost/ptr_container/ptr_map.hpp>
#include <senf/Packets/Packets.hh>
#include <senf/Utils/type_traits.hh>
+#include <senf/Utils/singleton.hh>
//#include "GenericTLV.hh.mpp"
///////////////////////////////hh.p////////////////////////////////////////
\endcode
Your concrete TLV parsers will inherit from this base class and have to define a specific
- value field and a \c TYPEID member:
+ value field and a \c typeId member:
\code
struct MyConcreteTLVParser : public MyTLVParserBase
{
SENF_PARSER_FINALIZE ( MyConcreteTLVParser );
SENF_PARSER_INIT() {
- type() = TYPEID;
+ type() = typeId;
length_() = 4;
}
- static const type_t::value_type TYPEID = 0x42;
+ static const type_t::value_type typeId = 0x42;
};
\endcode
typedef senf::GenericTLVParserBase<MyTLVParserBase> MyGenericTLVParser;
\endcode
- This generiv tlv parser can now be used for example in a list:
+ This generic tlv parser can now be used for example in a list:
\code
class MyTestPacketParser : public senf::PacketParserBase
{
\endcode
\see
- IPv6GenericOptionTLVParser, WLANGenericInfoElementParser, MIHGenericTLVParser
+ IPv6GenericOptionParser, WLANGenericInfoElementParser, MIHGenericTLVParser \n
+ GenericTLVParserRegistry
*/
template <class Base>
class GenericTLVParserBase : public Base
senf::PacketInterpreterBase::range value() const;
+ void dump(std::ostream & os) const;
+
#ifndef DOXYGEN
template<class ForwardReadableRange>
void value(ForwardReadableRange const & val,
Base & self();
Base const & self() const;
};
-}
+
+
+ namespace detail {
+ template <class BaseParser>
+ struct GenericTLVParserRegistry_EntryBase {
+ virtual void dump(GenericTLVParserBase<BaseParser> const & parser, std::ostream & os) const = 0;
+ };
+
+ template <class BaseParser, class Parser>
+ struct GenericTLVParserRegistry_Entry
+ : GenericTLVParserRegistry_EntryBase<BaseParser>
+ {
+ virtual void dump(GenericTLVParserBase<BaseParser> const & parser, std::ostream & os) const;
+ };
+ }
+
+ /** \brief TLV parser registration facility
+
+ The %GenericTLVParserRegistry provides a generic facility to globally register concrete
+ TLV parser by the type value. The concrete TLV parser must therefore provide a \c typeId
+ member. See GenericTLVParserBase for details about the assumed class structure.
+
+ Every registry is identified by the base tlv parser class. Parsers can be registered
+ statically only:
+ \code
+ GenericTLVParserRegistry<MyTLVParserBase>::RegistrationProxy<ConcreteTLVParser>
+ registerConcreteTLVParser;
+ \endcode
+ This global variable declaration will register ConcreteTLVParser. The variable
+ registerConcreteTLVParser is a dummy. It's only function is to force the call of
+ it's constructor during global construction time. This static registration only
+ works when the symbol is included into the final binary.
+
+ To simplify the registration the \ref SENF_PACKET_TLV_REGISTRY_REGISTER macro can be used.
+ The \c ConreteTLVParser must therefore provide a \c Registry typedef pointing to the
+ %GenericTLVParserRegistry; typically you put this typedef to the TLVBaseParser class.
+ \code
+ struct MyTLVParserBase : public senf::PacketParserBase
+ {
+ ...
+ typedef GenericTLVParserRegistry<MyTLVParserBase> Registry;
+ };
+ struct MyConcreteTLVParser : public MyTLVParserBase
+ {
+ ....
+ static const type_t::value_type typeId = 0x42;
+ void dump(std::ostream & os) const;
+ };
+
+ // register MyConcreteTLVParser to the MyTLVParserBase-Registry with the type id 0x42:
+ SENF_PACKET_TLV_REGISTRY_REGISTER( MyConcreteTLVParser );
+ \endcode
+
+ The registry provides a dump() member to dump an instance of a generic TLV parser.
+ If the type value of the given TLV parser is registered the generic tlv will be
+ casted to the registered concrete TLV parser and the dump member from this parser
+ will be called. Otherwise the generic TLV parser will be dumped in a generic way
+ (hexdump of the value).
+
+ \see
+ GenericTLVParserBase for the general TLV class structure \n
+ IPv6OptionParser::Registry, WLANInfoElementParser::Registry,
+ MIHBaseTLVParser::Registry
+ */
+ template <class BaseParser, class Keytype = typename BaseParser::type_t::value_type>
+ class GenericTLVParserRegistry
+ : public senf::singleton<GenericTLVParserRegistry<BaseParser,Keytype> >
+ {
+ typedef boost::ptr_map<Keytype,
+ detail::GenericTLVParserRegistry_EntryBase<BaseParser> > Map;
+ Map map_;
+
+ GenericTLVParserRegistry() {};
+ public:
+ using senf::singleton<GenericTLVParserRegistry<BaseParser,Keytype> >::instance;
+ friend class senf::singleton<GenericTLVParserRegistry<BaseParser,Keytype> >;
+
+ template <class PacketParser>
+ struct RegistrationProxy {
+ RegistrationProxy();
+ };
+ template <typename Parser>
+ void registerParser();
+
+ bool isRegistered(GenericTLVParserBase<BaseParser> const & parser) const;
+ bool isRegistered(Keytype const & key) const;
+
+ void dump(GenericTLVParserBase<BaseParser> const & parser, std::ostream & os) const;
+ void dump(GenericTLVParserBase<BaseParser> const & parser, Keytype const & key, std::ostream & os) const;
+ };
+
+ /** \brief Statically add an entry to a TLV parser registry
+
+ This macro will declare an anonymous global variable in such a way, that constructing
+ this variable will register the given tlv parser.
+
+ \hideinitializer
+ \see senf::GenericTLVParserRegistry
+ */
+# define SENF_PACKET_TLV_REGISTRY_REGISTER( ConreteTLVParser ) \
+ namespace { \
+ ConreteTLVParser::Registry::RegistrationProxy<ConreteTLVParser> \
+ BOOST_PP_CAT(tlvparserRegistration_, __LINE__); \
+ }
+
+}
///////////////////////////////hh.e////////////////////////////////////////
//#include "GenericTLV.cci"