4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
6 // The contents of this file are subject to the Fraunhofer FOKUS Public License
7 // Version 1.0 (the "License"); you may not use this file except in compliance
8 // with the License. You may obtain a copy of the License at
9 // http://senf.berlios.de/license.html
11 // The Fraunhofer FOKUS Public License Version 1.0 is based on,
12 // but modifies the Mozilla Public License Version 1.1.
13 // See the full license text for the amendments.
15 // Software distributed under the License is distributed on an "AS IS" basis,
16 // WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
17 // for the specific language governing rights and limitations under the License.
19 // The Original Code is Fraunhofer FOKUS code.
21 // The Initial Developer of the Original Code is Fraunhofer-Gesellschaft e.V.
22 // (registered association), Hansastraße 27 c, 80686 Munich, Germany.
23 // All Rights Reserved.
26 // Thorsten Horstmann <tho@berlios.de>
29 \brief GenericTLV public header */
31 #ifndef HH_SENF_Packets_GenericTLV_
32 #define HH_SENF_Packets_GenericTLV_ 1
35 #include <boost/ptr_container/ptr_map.hpp>
36 #include <senf/Packets/Packets.hh>
37 #include <senf/Utils/type_traits.hh>
38 #include <senf/Utils/singleton.hh>
40 //#include "GenericTLV.hh.mpp"
41 //-/////////////////////////////////////////////////////////////////////////////////////////////////
45 /** \brief Base class for generic TLV parsers
47 This abstract base class can be used to define generic TLV parsers. The following
48 class structure is assumed:
49 \image html GenericTLV.png
51 Your TLVParser base class has to define a \c type and a \c length field:
53 struct MyTLVParserBase : public senf::PacketParserBase
55 # include SENF_PARSER()
56 SENF_PARSER_FIELD ( type, senf::UInt8Parser );
57 SENF_PARSER_FIELD_RO ( length, senf::UInt8Parser );
58 SENF_PARSER_FINALIZE ( MyTLVParserBase );
62 Your concrete TLV parsers will inherit from this base class and have to define a specific
63 value field and a \c typeId member:
65 struct MyConcreteTLVParser : public MyTLVParserBase
67 # include SENF_PARSER()
68 SENF_PARSER_INHERIT ( MyTLVParserBase );
69 SENF_PARSER_FIELD ( myValue, senf::UInt32Parser );
70 SENF_PARSER_FINALIZE ( MyConcreteTLVParser );
76 static const type_t::value_type typeId = 0x42;
80 With GenericTLVParserBase you can define a generic parser class which provides
81 members to access the value data and and to cast the parser to a concrete tlv
84 struct MyGenericTLVParser : public senf::GenericTLVParserBase<MyTLVParserBase>
86 typedef senf::GenericTLVParserBase<MyTLVParserBase> base;
87 MyGenericTLVParser(data_iterator i, state_type s) : base(i,s) {}
89 // members for your generic TLV parser...
93 If your generic TLV parser just inherits from GenericTLVParserBase and doesn't
94 add any additional functionality you can use a simple \c typedef as well:
96 typedef senf::GenericTLVParserBase<MyTLVParserBase> MyGenericTLVParser;
99 This generic tlv parser can now be used for example in a list:
101 class MyTestPacketParser : public senf::PacketParserBase
103 # include SENF_PARSER()
104 SENF_PARSER_FIELD_RO ( list_length, senf::UInt8Parser );
105 SENF_PARSER_LIST ( tlv_list, list_length, MyGenericTLVParser );
106 SENF_PARSER_FINALIZE ( MyTestPacketParser );
110 Now, you can access the TLV parsers in the list in a generic way or you
111 can cast the parsers to some concrete tlv parser:
114 typedef MyTestPacket::Parser::tlv_list_t::container container_t;
115 container_t tlvContainer (p->tlv_list() );
116 optContainer_t::iterator listIter (tlvContainer.begin());
118 // listIter points to a MyGenericTLVParser, so you have generic access:
119 listIter->type() = 0x42;
120 listIter->value( someRangeOfValueData);
122 // cast to an instance of MyConcreteTLVParser:
123 if (listIter->is<MyConcreteTLVParser>()) {
124 MyConcreteTLVParser concreteTLVParser ( listIter->as<MyConcreteTLVParser>());
125 concreteTLVParser.myValue() = 0xabababab;
128 // add a MyConcreteTLV to the list:
129 MyConcreteTLVParser tlv ( tlvContainer.push_back_space().init<MyConcreteTLVParser>());
130 tlv.myValue() = 0xffff;
134 IPv6GenericOptionParser, WLANGenericInfoElementParser, MIHGenericTLVParser \n
135 GenericTLVParserRegistry
137 template <class Base>
138 class GenericTLVParserBase : public Base
141 GenericTLVParserBase(senf::PacketParserBase::data_iterator i, senf::PacketParserBase::state_type s)
144 senf::PacketParserBase::size_type bytes() const;
147 template <class Parser>
150 template <class Parser>
153 template <class Parser>
156 senf::PacketInterpreterBase::range value() const;
158 void dump(std::ostream & os) const;
161 template<class ForwardReadableRange>
162 void value(ForwardReadableRange const & val,
163 typename boost::disable_if<senf::is_pair<ForwardReadableRange> >::type * = 0);
165 template<class First, class Second>
166 void value(std::pair<First, Second> const & val,
167 typename boost::disable_if<boost::is_convertible<First, typename Base::type_t::value_type> >::type * = 0);
169 template <class Type, class ForwardReadableRange>
170 void value(std::pair<Type, ForwardReadableRange> const & val,
171 typename boost::enable_if<boost::is_convertible<Type, typename Base::type_t::value_type> >::type * = 0);
173 template<class ForwardReadableRange>
174 void value(ForwardReadableRange const & val);
176 template <class ForwardReadableRange>
177 void value(std::pair<typename Base::type_t::value_type, ForwardReadableRange> const & val);
181 template<class ForwardReadableRange>
182 void value_(ForwardReadableRange const &range);
185 Base const & self() const;
190 template <class BaseParser>
191 struct GenericTLVParserRegistry_EntryBase {
192 virtual ~GenericTLVParserRegistry_EntryBase() {}
193 virtual void dump(GenericTLVParserBase<BaseParser> const & parser, std::ostream & os) const = 0;
194 virtual PacketParserBase::size_type bytes(GenericTLVParserBase<BaseParser> const & parser) const = 0;
197 template <class BaseParser, class Parser>
198 struct GenericTLVParserRegistry_Entry
199 : GenericTLVParserRegistry_EntryBase<BaseParser>
201 virtual void dump(GenericTLVParserBase<BaseParser> const & parser, std::ostream & os) const;
202 virtual PacketParserBase::size_type bytes(GenericTLVParserBase<BaseParser> const & parser) const;
205 //Helper Functor for STL-compatible predicate (E.g. find_if, for_each ...)
206 template <class BaseParser, class Parser>
210 bool operator() (BaseParser const &p) const {
211 return p.template is<Parser>();
216 /** \brief TLV parser registration facility
218 The %GenericTLVParserRegistry provides a generic facility to globally register concrete
219 TLV parser by the type value. The concrete TLV parser must therefore provide a \c typeId
220 member. See GenericTLVParserBase for details about the assumed class structure.
222 Every registry is identified by the base tlv parser class. Parsers can be registered
225 GenericTLVParserRegistry<MyTLVParserBase>::RegistrationProxy<ConcreteTLVParser>
226 registerConcreteTLVParser;
228 This global variable declaration will register ConcreteTLVParser. The variable
229 registerConcreteTLVParser is a dummy. It's only function is to force the call of
230 it's constructor during global construction time. This static registration only
231 works when the symbol is included into the final binary.
233 To simplify the registration the \ref SENF_PACKET_TLV_REGISTRY_REGISTER macro can be used.
234 The \c ConreteTLVParser must therefore provide a \c Registry typedef pointing to the
235 %GenericTLVParserRegistry; typically you put this typedef to the TLVBaseParser class.
237 struct MyTLVParserBase : public senf::PacketParserBase
240 typedef GenericTLVParserRegistry<MyTLVParserBase> Registry;
242 struct MyConcreteTLVParser : public MyTLVParserBase
245 static const type_t::value_type typeId = 0x42;
246 void dump(std::ostream & os) const;
249 // register MyConcreteTLVParser to the MyTLVParserBase-Registry with the type id 0x42:
250 SENF_PACKET_TLV_REGISTRY_REGISTER( MyConcreteTLVParser );
253 The registry provides a dump() member to dump an instance of a generic TLV parser.
254 If the type value of the given TLV parser is registered the generic tlv will be
255 casted to the registered concrete TLV parser and the dump member from this parser
259 GenericTLVParserBase for the general TLV class structure \n
260 IPv6OptionParser::Registry, WLANInfoElementParser::Registry,
261 MIHBaseTLVParser::Registry
263 template <class BaseParser, class Keytype = typename BaseParser::type_t::value_type>
264 class GenericTLVParserRegistry
265 : public senf::singleton<GenericTLVParserRegistry<BaseParser,Keytype> >
267 typedef boost::ptr_map<Keytype,
268 detail::GenericTLVParserRegistry_EntryBase<BaseParser> > Map;
271 GenericTLVParserRegistry() {};
273 using senf::singleton<GenericTLVParserRegistry<BaseParser,Keytype> >::instance;
274 friend class senf::singleton<GenericTLVParserRegistry<BaseParser,Keytype> >;
276 template <class PacketParser>
277 struct RegistrationProxy {
281 template <typename Parser>
282 void registerParser();
284 typedef GenericTLVParserBase<BaseParser> GenericTLVParser;
286 bool isRegistered(GenericTLVParserBase<BaseParser> const & parser) const;
287 bool isRegistered(Keytype const & key) const;
289 void dump(GenericTLVParser const & parser, std::ostream & os) const;
290 void dump(GenericTLVParser const & parser, Keytype const & key, std::ostream & os) const;
292 PacketParserBase::size_type bytes(GenericTLVParser const & parser) const;
293 PacketParserBase::size_type bytes(GenericTLVParser const & parser, Keytype const & key) const;
296 struct TLVParserNotRegisteredException : public senf::Exception
298 TLVParserNotRegisteredException() : senf::Exception("tlv parser not registered") {}
302 /** \brief Statically add an entry to a TLV parser registry
304 This macro will declare an anonymous global variable in such a way, that constructing
305 this variable will register the given tlv parser.
308 \see senf::GenericTLVParserRegistry
310 # define SENF_PACKET_TLV_REGISTRY_REGISTER( ConreteTLVParser ) \
312 ConreteTLVParser::Registry::RegistrationProxy<ConreteTLVParser> \
313 BOOST_PP_CAT(tlvparserRegistration_, __LINE__); \
318 //-/////////////////////////////////////////////////////////////////////////////////////////////////
319 //#include "GenericTLV.cci"
320 #include "GenericTLV.ct"
321 #include "GenericTLV.cti"
328 // comment-column: 40
329 // c-file-style: "senf"
330 // indent-tabs-mode: nil
331 // ispell-local-dictionary: "american"
332 // compile-command: "scons -u test"