///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
-
+
/** \brief Base class for generic TLV parsers
-
+
This abstract base class can be used to define generic TLV parsers. The following
class structure is assumed:
\image html GenericTLV.png
-
+
Your TLVParser base class has to define a \c type and a \c length field:
\code
struct MyTLVParserBase : public senf::PacketParserBase
SENF_PARSER_FINALIZE ( MyTLVParserBase );
};
\endcode
-
+
Your concrete TLV parsers will inherit from this base class and have to define a specific
value field and a \c typeId member:
\code
SENF_PARSER_INHERIT ( MyTLVParserBase );
SENF_PARSER_FIELD ( myValue, senf::UInt32Parser );
SENF_PARSER_FINALIZE ( MyConcreteTLVParser );
-
+
SENF_PARSER_INIT() {
type() = typeId;
length_() = 4;
- }
+ }
static const type_t::value_type typeId = 0x42;
};
\endcode
-
+
With GenericTLVParserBase you can define a generic parser class which provides
members to access the value data and and to cast the parser to a concrete tlv
- parser:
+ parser:
\code
struct MyGenericTLVParser : public senf::GenericTLVParserBase<MyTLVParserBase>
{
typedef senf::GenericTLVParserBase<MyTLVParserBase> base;
MyGenericTLVParser(data_iterator i, state_type s) : base(i,s) {}
-
+
// members for your generic TLV parser...
};
\endcode
-
+
If your generic TLV parser just inherits from GenericTLVParserBase and doesn't
add any additional functionality you can use a simple \c typedef as well:
\code
typedef senf::GenericTLVParserBase<MyTLVParserBase> MyGenericTLVParser;
\endcode
-
+
This generic tlv parser can now be used for example in a list:
\code
class MyTestPacketParser : public senf::PacketParserBase
SENF_PARSER_FINALIZE ( MyTestPacketParser );
};
\endcode
-
+
Now, you can access the TLV parsers in the list in a generic way or you
can cast the parsers to some concrete tlv parser:
\code
typedef MyTestPacket::Parser::tlv_list_t::container container_t;
container_t tlvContainer (p->tlv_list() );
optContainer_t::iterator listIter (tlvContainer.begin());
-
+
// listIter points to a MyGenericTLVParser, so you have generic access:
listIter->type() = 0x42;
listIter->value( someRangeOfValueData);
-
+
// cast to an instance of MyConcreteTLVParser:
if (listIter->is<MyConcreteTLVParser>()) {
MyConcreteTLVParser concreteTLVParser ( listIter->as<MyConcreteTLVParser>());
concreteTLVParser.myValue() = 0xabababab;
}
-
+
// add a MyConcreteTLV to the list:
MyConcreteTLVParser tlv ( tlvContainer.push_back_space().init<MyConcreteTLVParser>());
tlv.myValue() = 0xffff;
- \endcode
+ \endcode
- \see
+ \see
IPv6GenericOptionParser, WLANGenericInfoElementParser, MIHGenericTLVParser \n
GenericTLVParserRegistry
*/
class GenericTLVParserBase : public Base
{
public:
- GenericTLVParserBase(senf::PacketParserBase::data_iterator i, senf::PacketParserBase::state_type s)
+ GenericTLVParserBase(senf::PacketParserBase::data_iterator i, senf::PacketParserBase::state_type s)
: Base(i,s) {}
-
+
senf::PacketParserBase::size_type bytes() const;
void init() const;
template <class Parser>
Parser init();
-
+
template <class Parser>
Parser as() const;
-
+
template <class Parser>
bool is() const;
senf::PacketInterpreterBase::range value() const;
void dump(std::ostream & os) const;
-
+
#ifndef DOXYGEN
template<class ForwardReadableRange>
void value(ForwardReadableRange const & val,
template <class Type, class ForwardReadableRange>
void value(std::pair<Type, ForwardReadableRange> const & val,
- typename boost::enable_if<boost::is_convertible<Type, typename Base::type_t::value_type> >::type * = 0);
+ typename boost::enable_if<boost::is_convertible<Type, typename Base::type_t::value_type> >::type * = 0);
#else
template<class ForwardReadableRange>
void value(ForwardReadableRange const & val);
-
+
template <class ForwardReadableRange>
void value(std::pair<typename Base::type_t::value_type, ForwardReadableRange> const & val);
-#endif
-
+#endif
+
private:
template<class ForwardReadableRange>
void value_(ForwardReadableRange const &range);
-
+
Base & self();
Base const & self() const;
};
-
-
+
+
namespace detail {
template <class BaseParser>
struct GenericTLVParserRegistry_EntryBase {
+ virtual ~GenericTLVParserRegistry_EntryBase() {}
virtual void dump(GenericTLVParserBase<BaseParser> const & parser, std::ostream & os) const = 0;
virtual PacketParserBase::size_type bytes(GenericTLVParserBase<BaseParser> const & parser) const = 0;
};
-
+
template <class BaseParser, class Parser>
struct GenericTLVParserRegistry_Entry
: GenericTLVParserRegistry_EntryBase<BaseParser>
virtual void dump(GenericTLVParserBase<BaseParser> const & parser, std::ostream & os) const;
virtual PacketParserBase::size_type bytes(GenericTLVParserBase<BaseParser> const & parser) const;
};
-
+
//Helper Functor for STL-compatible predicate (E.g. find_if, for_each ...)
template <class BaseParser, class Parser>
class Predicate
{
public:
- const bool operator() (BaseParser const &p) const{
+ bool operator() (BaseParser const &p) const {
return p.template is<Parser>();
}
};
}
-
+
/** \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:
+
+ 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
+ \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.
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.
-
+
\see
GenericTLVParserBase for the general TLV class structure \n
IPv6OptionParser::Registry, WLANInfoElementParser::Registry,
- MIHBaseTLVParser::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,
+ 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();
-
+
typedef GenericTLVParserBase<BaseParser> GenericTLVParser;
-
+
bool isRegistered(GenericTLVParserBase<BaseParser> const & parser) const;
bool isRegistered(Keytype const & key) const;
-
+
void dump(GenericTLVParser const & parser, std::ostream & os) const;
void dump(GenericTLVParser const & parser, Keytype const & key, std::ostream & os) const;
-
+
PacketParserBase::size_type bytes(GenericTLVParser const & parser) const;
PacketParserBase::size_type bytes(GenericTLVParser const & parser, Keytype const & key) const;
};
-
+
struct TLVParserNotRegisteredException : public senf::Exception
- {
- TLVParserNotRegisteredException() : senf::Exception("tlv parser not registered") {}
+ {
+ TLVParserNotRegisteredException() : senf::Exception("tlv parser not registered") {}
};
-
+
/** \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 macro will declare an anonymous global variable in such a way, that constructing
this variable will register the given tlv parser.
\hideinitializer
ConreteTLVParser::Registry::RegistrationProxy<ConreteTLVParser> \
BOOST_PP_CAT(tlvparserRegistration_, __LINE__); \
}
-
+
}
///////////////////////////////hh.e////////////////////////////////////////