Packets: Add annotations to packet dump
g0dil [Fri, 3 Jul 2009 09:20:04 +0000 (09:20 +0000)]
git-svn-id: https://svn.berlios.de/svnroot/repos/senf/trunk@1254 270642c3-0616-0410-b53a-bc976706d245

Packets/Packet.test.cc
Packets/PacketImpl.cc
Packets/PacketImpl.cci
Packets/PacketImpl.cti
Packets/PacketImpl.hh
Packets/PacketInterpreter.cc

index 18b8fe9..6aecfbe 100644 (file)
@@ -90,8 +90,8 @@ namespace {
         using mixin::init;
         static void dump(packet p, std::ostream & os) {
             os << "BarPacket:\n"
-               << "type: " << p->type() << "\n"
-               << "length: " << p->length() << "\n";
+               << "  type: " << p->type() << "\n"
+               << "  length: " << p->length() << "\n";
         }
         static void finalize(packet p) {
             if (p.next(senf::nothrow))
@@ -113,25 +113,41 @@ namespace {
     struct IntAnnotation {
         unsigned value;
     };
+
+    std::ostream & operator<<(std::ostream & os, IntAnnotation const & v)
+    { os << v.value; return os; }
     
     struct LargeAnnotation {
         char value[32];
     };
 
+    std::ostream & operator<<(std::ostream & os, LargeAnnotation const & v)
+    { os << v.value; return os; }
+
     struct ComplexAnnotation : senf::ComplexAnnotation
     {
+        ComplexAnnotation() : s(), i() {}
         std::string s;
         int i;
     };
 
+    std::ostream & operator<<(std::ostream & os, ComplexAnnotation const & v)
+    { os << "('" << v.s << "' " << v.i << ')'; return os; }
+
     struct ComplexEmptyAnnotation : senf::ComplexAnnotation
     {};
 
+    std::ostream & operator<<(std::ostream & os, ComplexEmptyAnnotation const & v)
+    { os << "(empty)"; return os; }
+
     struct InvalidAnnotation
     {
         std::string value;
     };
 
+    std::ostream & operator<<(std::ostream & os, InvalidAnnotation const & v)
+    { os << v.value; return os; }
+
 }
 
 BOOST_AUTO_UNIT_TEST(packet)
@@ -180,7 +196,13 @@ BOOST_AUTO_UNIT_TEST(packet)
     
     std::stringstream s;
     packet.dump(s);
-    BOOST_CHECK_EQUAL( s.str(), "BarPacket:\ntype: 0\nlength: 0\n" );
+    BOOST_CHECK_EQUAL( s.str(), 
+                       "Annotations:\n"
+                       "  (anonymous namespace)::ComplexAnnotation: no value\n"
+                       "  (anonymous namespace)::IntAnnotation: 0\n"
+                       "BarPacket:\n"
+                       "  type: 0\n"
+                       "  length: 0\n" );
     
     packet.finalizeAll();
     BOOST_CHECK_EQUAL( packet.last().as<BarPacket>()->type(), 
index 647d37f..5b0ad43 100644 (file)
 #define prefix_
 ///////////////////////////////cc.p////////////////////////////////////////
 
+///////////////////////////////////////////////////////////////////////////
+// senf::detail::AnnotationIndexerBase
+
 unsigned senf::detail::AnnotationIndexerBase::maxAnnotations (0);
 
+prefix_ void senf::detail::AnnotationIndexerBase::dump(PacketImpl * p, std::ostream & os)
+{
+    for(std::vector<AnnotationIndexerBase*>::const_iterator 
+            i (registry().begin()), i_end (registry().end());
+        i != i_end; ++i)
+        (*i)->v_dump(p,os);
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::detail::PacketImpl
 
index e3c532e..3c6cce0 100644 (file)
 ///////////////////////////////////////////////////////////////////////////
 // senf::detail::AnnotationIndexerBase
 
+prefix_ senf::detail::AnnotationIndexerBase::~AnnotationIndexerBase()
+{}
+
 prefix_ std::vector<bool> & senf::detail::AnnotationIndexerBase::small()
 {
     static std::vector<bool> smalls;
     return smalls;
 }
 
+prefix_ std::vector<senf::detail::AnnotationIndexerBase*> &
+senf::detail::AnnotationIndexerBase::registry()
+{
+    static std::vector<AnnotationIndexerBase*> reg;
+    return reg;
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::detail::AnnotationP
 
@@ -186,6 +196,11 @@ prefix_ senf::detail::PacketImpl::size_type senf::detail::PacketImpl::capacity()
     return data_.capacity();
 }
 
+prefix_ void senf::detail::PacketImpl::dumpAnnotations(std::ostream & os)
+{
+    AnnotationIndexerBase::dump(this, os);
+}
+
 // This function has a problem being inlined. Somehow, often when calling this, the size of the 
 // resulting inlined code would be huge?
 
index 1f2d79a..e3ec1ea 100644 (file)
@@ -38,6 +38,21 @@ prefix_ senf::detail::AnnotationIndexer<Annotation>::AnnotationIndexer()
     : index_ (maxAnnotations++)
 {
     small().push_back(Small);
+    registry().push_back(this);
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::detail::AnnotationIndexer<Annotation>
+
+
+template <class Annotation>
+prefix_ void senf::detail::AnnotationIndexer<Annotation>::v_dump(PacketImpl * p,
+                                                                 std::ostream & os)
+{
+
+    os << "  " << senf::prettyName(typeid(Annotation)) << ": ";
+    p->dumpAnnotation<Annotation>(os);
+    os << "\n";
 }
 
 template <class Annotation>
@@ -57,12 +72,27 @@ prefix_ Annotation & senf::detail::GetAnnotation<Annotation,Small>::get(Annotati
     return static_cast< TAnnotationP<Annotation>* >(e.p)->annotation;
 }
 
+template <class Annotation, bool Small>
+prefix_ void senf::detail::GetAnnotation<Annotation,Small>::dump(AnnotationEntry & e,
+                                                                 std::ostream & os)
+{
+    if (!e.p) os << "no value";
+    else      os << get(e);
+}
+
 template <class Annotation>
 prefix_ Annotation & senf::detail::GetAnnotation<Annotation, true>::get(AnnotationEntry & e)
 {
     return * static_cast<Annotation*>(static_cast<void*>(& e.i));
 }
 
+template <class Annotation>
+prefix_ void senf::detail::GetAnnotation<Annotation, true>::dump(AnnotationEntry & e,
+                                                                 std::ostream & os)
+{
+    os << get(e);
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // senf::detail::PacketImpl
 
@@ -91,6 +121,13 @@ prefix_ Annotation & senf::detail::PacketImpl::annotation()
         annotations_[AnnotationIndexer<Annotation>::index()]);
 }
 
+template <class Annotation>
+prefix_ void senf::detail::PacketImpl::dumpAnnotation(std::ostream & os)
+{
+    GetAnnotation<Annotation>::dump(
+        annotations_[AnnotationIndexer<Annotation>::index()], os);
+}
+
 ///////////////////////////////cti.e///////////////////////////////////////
 #undef prefix_
 
index 32ae5a1..0ad1e77 100644 (file)
@@ -82,8 +82,13 @@ namespace detail {
 
     struct AnnotationIndexerBase
     {
+        virtual ~AnnotationIndexerBase();
+        virtual void v_dump(PacketImpl * p, std::ostream & os) = 0;
+
         static unsigned maxAnnotations;
         static std::vector<bool> & small();
+        static std::vector<AnnotationIndexerBase*> & registry();
+        static void dump(PacketImpl * p, std::ostream & os);
     };
 
     template <class Annotation>
@@ -92,6 +97,7 @@ namespace detail {
           public AnnotationIndexerBase
     {
         AnnotationIndexer();
+        virtual void v_dump(PacketImpl * p, std::ostream & os);
         unsigned index_;
         static unsigned index();
         static bool const Complex = boost::is_base_of<ComplexAnnotation, Annotation>::value;
@@ -112,12 +118,14 @@ namespace detail {
     struct GetAnnotation
     {
         static Annotation & get(AnnotationEntry & e);
+        static void dump(AnnotationEntry & e, std::ostream & os);
     };
 
     template <class Annotation>
     struct GetAnnotation<Annotation, true>
     {
         static Annotation & get(AnnotationEntry & e);
+        static void dump(AnnotationEntry & e, std::ostream & os);
     };
 
     /** \brief Internal: Packet data storage
@@ -191,6 +199,9 @@ namespace detail {
         // Annotations
         template <class Annotation>
         Annotation & annotation();
+        void dumpAnnotations(std::ostream & os);
+        template <class Annotation>
+        void dumpAnnotation(std::ostream & os);
 
         /** \brief Internal: Keep PacketImpl instance alive
 
index 466ba1f..fcd6783 100644 (file)
@@ -74,6 +74,10 @@ prefix_ senf::PacketInterpreterBase::ptr senf::PacketInterpreterBase::append(ptr
 
 prefix_ void senf::PacketInterpreterBase::dump(std::ostream & os)
 {
+    if (detail::AnnotationIndexerBase::maxAnnotations > 0) {
+        os << "Annotations:\n";
+        impl().dumpAnnotations(os);
+    }
     v_dump(os);
     for (ptr i (next()); i; i = i->next())
         i->v_dump(os);