Packets: added GenericTLVParserRegistry
tho [Thu, 15 Oct 2009 12:23:32 +0000 (12:23 +0000)]
Utils: added signed/unsigned formatter for value parsers

git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1498 270642c3-0616-0410-b53a-bc976706d245

senf/Packets/80211Bundle/InformationElements.hh
senf/Packets/80211Bundle/WLANBeaconPacket.test.cc
senf/Packets/GenericTLV.ct
senf/Packets/GenericTLV.cti
senf/Packets/GenericTLV.hh
senf/Packets/GenericTLV.test.cc
senf/Packets/PacketParser.hh
senf/Utils/Format.cti
senf/Utils/Format.hh

index a40691c..69fa2a9 100644 (file)
@@ -56,9 +56,9 @@ namespace senf {
         SENF_PARSER_FINALIZE ( WLANSSIDInfoElementParser        );
      
         SENF_PARSER_INIT() {
-            type() = TYPEID;
+            type() = typeId;
         }        
-        static const type_t::value_type TYPEID = 0x00u;
+        static const type_t::value_type typeId = 0x00u;
     };
         
     struct WLANSupportedRatesInfoElementParser
@@ -72,9 +72,9 @@ namespace senf {
         SENF_PARSER_FINALIZE ( WLANSupportedRatesInfoElementParser );
      
         SENF_PARSER_INIT() {
-            type() = TYPEID;
+            type() = typeId;
         }        
-        static const type_t::value_type TYPEID = 0x01u;
+        static const type_t::value_type typeId = 0x01u;
     };
         
     struct WLANPowerConstraintInfoElementParser
@@ -86,10 +86,10 @@ namespace senf {
         SENF_PARSER_FINALIZE ( WLANPowerConstraintInfoElementParser );
      
         SENF_PARSER_INIT() {
-            type() = TYPEID;
+            type() = typeId;
             length() = 1;
         }        
-        static const type_t::value_type TYPEID = 0x20u;
+        static const type_t::value_type typeId = 0x20u;
     };
 }
 
index d38d2ad..13dce87 100644 (file)
@@ -71,7 +71,7 @@ BOOST_AUTO_UNIT_TEST(WLANBeaconPacket_parse)
     BOOST_CHECK_EQUAL( i->type(), 0x07); //Country information
     ++i;
     //power constraint
-    BOOST_CHECK_EQUAL( i->type(), senf::WLANPowerConstraintInfoElementParser::TYPEID+0);
+    BOOST_CHECK_EQUAL( i->type(), senf::WLANPowerConstraintInfoElementParser::typeId+0);
     BOOST_CHECK( i->is<senf::WLANPowerConstraintInfoElementParser>());
     senf::WLANPowerConstraintInfoElementParser ie ( i->as<senf::WLANPowerConstraintInfoElementParser>());
     BOOST_CHECK_EQUAL( ie.value(), 0x42);
index 110b3ed..9c36431 100644 (file)
 //#include "GenericTLV.ih"
 
 // Custom includes
+#include <boost/io/ios_state.hpp>
+#include <senf/Utils/hexdump.hh>
+#include <senf/Utils/TypeInfo.hh>
+#include <senf/Utils/Format.hh>
 
 #define prefix_
 ///////////////////////////////ct.p////////////////////////////////////////
 
+///////////////////////////////////////////////////////////////////////////
+// senf::GenericTLVParserBase<Base>
+
 template <class Base>
 template <class Parser>
 prefix_ Parser senf::GenericTLVParserBase<Base>::init()
@@ -53,6 +60,18 @@ prefix_  senf::PacketInterpreterBase::range senf::GenericTLVParserBase<Base>::va
 }
 
 template <class Base>
+prefix_  void senf::GenericTLVParserBase<Base>::dump(std::ostream & os)
+    const 
+{
+    boost::io::ios_all_saver ias(os);
+    os << "GenericTLVParser<" << prettyName(typeid(Base)) << ">\n"
+       << "  type:   " << senf::format::dumpint(this->type()) << "\n"
+       << "  length: " << senf::format::dumpint(this->length()) << "\n"
+       << "  value:\n";
+    hexdump(value().begin(), value().end(), os);
+}
+
+template <class Base>
 template <class ForwardReadableRange>
 prefix_ void senf::GenericTLVParserBase<Base>::value_(ForwardReadableRange const &range)
 {
@@ -65,6 +84,32 @@ prefix_ void senf::GenericTLVParserBase<Base>::value_(ForwardReadableRange const
     this->length_() = rangeSize;
 }
 
+
+///////////////////////////////////////////////////////////////////////////
+// senf::GenericTLVParserRegistry<BaseParser>
+
+template <class BaseParser>
+template <typename Parser>
+prefix_ void senf::GenericTLVParserRegistry<BaseParser>::registerParser()
+{
+    typename Map::iterator i (map_.find( Parser::typeId ));
+    if (i == map_.end() ) {
+        typename BaseParser::type_t::value_type k (Parser::typeId);
+        map_.insert(k , new detail::GenericTLVParserRegistry_Entry<BaseParser, Parser>() );
+    }
+}
+
+template <class BaseParser>
+prefix_ void senf::GenericTLVParserRegistry<BaseParser>::dump(
+        std::ostream & os, GenericTLVParserBase<BaseParser> const & parser)
+{
+    typename Map::iterator i (map_.find( parser.type()));
+    if (i == map_.end())
+        parser.dump(os);
+    else
+        (i->second)->dump(os, parser);
+}
+
 ///////////////////////////////ct.e////////////////////////////////////////
 #undef prefix_
 
index a5d39b5..82adea3 100644 (file)
@@ -30,6 +30,9 @@
 #define prefix_ inline
 ///////////////////////////////cti.p///////////////////////////////////////
 
+///////////////////////////////////////////////////////////////////////////
+// senf::GenericTLVParserBase<Base>
+
 template <class Base>
 prefix_ senf::PacketParserBase::size_type senf::GenericTLVParserBase<Base>::bytes()
 {
@@ -56,7 +59,7 @@ template <class Parser>
 prefix_ bool senf::GenericTLVParserBase<Base>::is()
     const
 {
-    return this->type().value() == Parser::TYPEID;
+    return this->type().value() == Parser::typeId;
 }
 
 template <class Base>
@@ -104,6 +107,17 @@ prefix_ void senf::GenericTLVParserBase<Base>::value(
 
 #endif
 
+
+///////////////////////////////////////////////////////////////////////////
+// senf::detail:GenericTLVParserRegistry_Entry<BaseParser, Parser>
+
+template <class BaseParser, class Parser>
+prefix_ void senf::detail::GenericTLVParserRegistry_Entry<BaseParser, Parser>::dump(
+        std::ostream & os, GenericTLVParserBase<BaseParser> const & parser)
+{
+    (parser.template as<Parser>()).dump(os);
+}
+
 ///////////////////////////////cti.e///////////////////////////////////////
 #undef prefix_
 
index 6f89e82..e8e1bb5 100644 (file)
 #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////////////////////////////////////////
@@ -53,7 +55,7 @@ namespace senf {
         \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
         {
@@ -63,10 +65,10 @@ namespace senf {
             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
        
@@ -89,7 +91,7 @@ namespace senf {
         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
         {
@@ -147,6 +149,8 @@ namespace senf {
 
         senf::PacketInterpreterBase::range value() const;
         
+        void dump(std::ostream & os) const;
+        
 #ifndef DOXYGEN
         template<class ForwardReadableRange>
         void value(ForwardReadableRange const & val,
@@ -174,6 +178,41 @@ namespace senf {
         Base & self();
         Base const & self() const;
     };
+    
+    
+    namespace detail {
+        template <class BaseParser>
+        struct GenericTLVParserRegistry_EntryBase {
+            virtual void dump(std::ostream & os, GenericTLVParserBase<BaseParser> const & parser) = 0;
+        };
+    
+        template <class BaseParser, class Parser>
+        struct GenericTLVParserRegistry_Entry
+            : GenericTLVParserRegistry_EntryBase<BaseParser>
+        {
+            virtual void dump(std::ostream & os, GenericTLVParserBase<BaseParser> const & parser);
+        };
+    }
+    
+    template <class BaseParser>
+    class GenericTLVParserRegistry
+        : public senf::singleton<GenericTLVParserRegistry<BaseParser> >
+    {
+        typedef boost::ptr_map<
+            typename BaseParser::type_t::value_type, 
+            detail::GenericTLVParserRegistry_EntryBase<BaseParser> > Map;
+        Map map_;
+        
+        GenericTLVParserRegistry() {};
+    public:
+        using senf::singleton<GenericTLVParserRegistry<BaseParser> >::instance;
+        friend class senf::singleton<GenericTLVParserRegistry<BaseParser> >;
+        
+        template <typename Parser>
+        void registerParser();
+        
+        void dump(std::ostream & os, GenericTLVParserBase<BaseParser> const & parser);
+    };
 }
 
 
index 84be10c..d35523c 100644 (file)
@@ -59,11 +59,20 @@ namespace {
        SENF_PARSER_FINALIZE ( MyConcreteTLVParser         );
     
        SENF_PARSER_INIT() {
-           type() = TYPEID;
+           type() = typeId;
            length_() = 4;
-       }        
-       static const type_t::value_type TYPEID = 0x42;
+       }
+       static type_t::value_type const typeId;
+       
+       void dump(std::ostream & os) const {
+           boost::io::ios_all_saver ias(os);
+           os << "MyConcreteTLVParser\n"
+              << "  type:   " << senf::format::dumpint(type()) << "\n"
+              << "  length: " << senf::format::dumpint(length()) << "\n"
+              << "  value:  " << senf::format::dumpint(myValue()) << "\n";
+       }
    };
+   MyConcreteTLVParser::type_t::value_type const MyConcreteTLVParser::typeId = 0x42;
         
     class MyTestPacketParser
         : public senf::PacketParserBase
@@ -141,6 +150,29 @@ BOOST_AUTO_UNIT_TEST(GenericTLV_packet)
 }
 
 
+BOOST_AUTO_UNIT_TEST(GenericTLV_registry)
+{
+    MyTestPacket p ( MyTestPacket::create());
+    MyTestPacket::Parser::tlv_list_t::container tlvContainer (p->tlv_list() );
+    MyConcreteTLVParser conreteTLVParser ( 
+            tlvContainer.push_back_space().init<MyConcreteTLVParser>());
+    conreteTLVParser.myValue() << 0xffff;
+    p.finalizeThis();
+        
+    typedef senf::GenericTLVParserRegistry<MyTLVParserBase> MyTLVParserRegistry;
+    
+    std::stringstream ss;
+    MyTLVParserRegistry::instance().dump(ss, *tlvContainer.begin());
+    BOOST_CHECK_EQUAL( ss.str().substr(0,56), "GenericTLVParser<(anonymous namespace)::MyTLVParserBase>" );
+    
+    MyTLVParserRegistry::instance().registerParser<MyConcreteTLVParser>();
+    ss.str(""); ss.clear();
+    
+    MyTLVParserRegistry::instance().dump(ss, *tlvContainer.begin());
+    BOOST_CHECK_EQUAL( ss.str().substr(0,19), "MyConcreteTLVParser" );
+}
+
+
 ///////////////////////////////cc.e////////////////////////////////////////
 #undef prefix_
 
index 3eb5d6a..ea2d64f 100644 (file)
@@ -299,9 +299,6 @@ namespace senf {
             ParserProtector( PacketParserBase const * parser);
             ParserProtector(ParserProtector const & other_);
             ~ParserProtector();
-            
-            template <class _>
-            void operator()(_ const &) const {}
         };
     protected:
         ParserProtector protect() const;
index 41b8ab4..7ce91f4 100644 (file)
@@ -44,6 +44,20 @@ senf::format::dumpint(T const & v, typename boost::enable_if<boost::is_unsigned<
    return detail::dumpintUnsigned(v, std::numeric_limits<T>::digits); 
 }
 
+template <class T>
+prefix_ std::string 
+senf::format::dumpint(T const & v, typename boost::enable_if<boost::is_signed<typename T::value_type> >::type *)
+{ 
+   return detail::dumpintSigned(v.value(), std::numeric_limits<typename T::value_type>::digits);
+}
+
+template <class T>
+prefix_ std::string
+senf::format::dumpint(T const & v, typename boost::enable_if<boost::is_unsigned<typename T::value_type> >::type *)
+{
+   return detail::dumpintUnsigned(v.value(), std::numeric_limits<typename T::value_type>::digits); 
+}
+
 ///////////////////////////////cti.e///////////////////////////////////////
 #undef prefix_
 
index 7e0b364..7c6e424 100644 (file)
@@ -193,6 +193,14 @@ namespace format {
     template <class T> 
     std::string dumpint(T const & v, 
                         typename boost::enable_if<boost::is_unsigned<T> >::type * = 0);
+    
+    template <class T> 
+    std::string dumpint(T const & v, 
+                        typename boost::enable_if<boost::is_signed<typename T::value_type> >::type * = 0);
+
+    template <class T> 
+    std::string dumpint(T const & v, 
+                        typename boost::enable_if<boost::is_unsigned<typename T::value_type> >::type * = 0);
 
 #endif