using mixin::init;
static void dump(packet p, std::ostream & os) {
os << "BarPacket:\n"
- << " type: " << p->type() << "\n"
- << " length: " << p->length() << "\n";
+ << senf::fieldName("type") << p->type() << "\n"
+ << senf::fieldName("length") << p->length() << "\n";
}
static void finalize(packet p) {
if (p.next(senf::nothrow))
packet.dump(s);
BOOST_CHECK_EQUAL( s.str(),
"Annotations:\n"
- " (anonymous namespace)::ComplexAnnotation: no value\n"
- " (anonymous namespace)::IntAnnotation: 0\n"
+ " (anonymous namespace)::IntAnnotation : 0\n"
"BarPacket:\n"
- " type: 0\n"
- " length: 0\n" );
+ " type : 0\n"
+ " length : 0\n" );
packet.finalizeAll();
BOOST_CHECK_EQUAL( packet.last().as<BarPacket>()->type(),
SENF_AUTO_UNIT_TEST(packetAnnotation)
{
+ typedef senf::detail::AnnotationRegistry Reg;
+
senf::Packet packet (FooPacket::create());
BarPacket::createAfter(packet);
BOOST_CHECK_EQUAL( p2.annotation<ComplexAnnotation>().s, "dead beef" );
BOOST_CHECK_EQUAL( p2.annotation<ComplexAnnotation>().i, 0x12345678 );
- BOOST_CHECK( senf::detail::AnnotationIndexer<IntAnnotation>::Small );
- BOOST_CHECK( ! senf::detail::AnnotationIndexer<LargeAnnotation>::Small );
- BOOST_CHECK( ! senf::detail::AnnotationIndexer<ComplexAnnotation>::Small );
- BOOST_CHECK( ! senf::detail::AnnotationIndexer<ComplexEmptyAnnotation>::Small );
+ BOOST_CHECK( Reg::lookup<IntAnnotation>() >= 0 );
+ BOOST_CHECK( Reg::lookup<LargeAnnotation>() < 0 );
+ BOOST_CHECK( Reg::lookup<ComplexAnnotation>() < 0 );
+ BOOST_CHECK( Reg::lookup<ComplexEmptyAnnotation>() < 0 );
+
+ std::stringstream ss;
+
+ senf::dumpPacketAnnotationRegistry(ss);
+ BOOST_CHECK_EQUAL(
+ ss.str(),
+ "SENF_PACKET_ANNOTATION_SLOTS = 8\n"
+ "SENF_PACKET_ANNOTATION_SLOTSIZE = 16\n"
+ "SLOT TYPE COMPLEX SIZE\n"
+ " (anonymous namespace)::ComplexEmptyAnnotation yes 1\n"
+ " (anonymous namespace)::ComplexAnnotation yes 8\n"
+ " (anonymous namespace)::LargeAnnotation no 32\n"
+ " 0 (anonymous namespace)::IntAnnotation no 4\n" );
}
#ifdef COMPILE_CHECK
/** \file
\brief PacketImpl non-inline non-template implementation */
-//#include "PacketImpl.ih"
+#include "PacketImpl.ih"
// Custom includes
#include <iterator>
+#include <boost/format.hpp>
+#include <senf/Utils/String.hh>
#include "Packets.hh"
//#include "PacketImpl.mpp"
///////////////////////////////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
prefix_ senf::detail::PacketImpl::~PacketImpl()
// We increment refcount_ to ensure, release() won't call delete again
++refcount_;
eraseInterpreters(interpreters_.begin(), interpreters_.end());
- Annotations::const_iterator i (annotations_.begin());
- Annotations::const_iterator const i_end (annotations_.end());
- std::vector<bool>::iterator small (AnnotationIndexerBase::small().begin());
- for (; i != i_end; ++i, ++small)
- if (! *small && i->p)
- delete i->p;
}
// interpreter chain
// else pos is after the packet and we don't need to change anything ...
}
-///////////////////////////////cc.e////////////////////////////////////////
+// Annotations
+
+prefix_ void senf::detail::PacketImpl::dumpAnnotations(std::ostream & os)
+{
+ for (AnnotationRegistry::key_t key (AnnotationRegistry::instance().keyBegin());
+ key != AnnotationRegistry::instance().keyEnd(); ++key) {
+ void * antn (annotation(key));
+ if (antn)
+ AnnotationRegistry::instance().dump(key, os, antn);
+ }
+}
+
+prefix_ void * senf::detail::PacketImpl::complexAnnotation(AnnotationRegistry::key_t key)
+{
+ SENF_ASSERT( key<0, "complexAnnotation called with invalid key");
+#ifdef SENF_PACKET_NO_COMPLEX_ANNOTATIONS
+ return 0;
+#else
+ while (complexAnnotations_.size() < ComplexAnnotations::size_type(-key))
+ complexAnnotations_.push_back(0);
+ if (complexAnnotations_.is_null(-key-1))
+ return 0;
+ return complexAnnotations_[-key-1].get();
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////
+// senf::detail::AnnotationRegistry
+
+prefix_ void senf::detail::AnnotationRegistry::dumpRegistrations(std::ostream & os)
+{
+#ifdef SENF_DEBUG
+ boost::format fmt ("%4.4s %-56.56s %-7.7s %5d\n");
+ os << "SENF_PACKET_ANNOTATION_SLOTS = " << SENF_PACKET_ANNOTATION_SLOTS << "\n"
+ << "SENF_PACKET_ANNOTATION_SLOTSIZE = " << SENF_PACKET_ANNOTATION_SLOTSIZE << "\n";
+ os << fmt % "SLOT" % "TYPE" % "COMPLEX" % "SIZE";
+ for (key_t key (keyBegin()); key != keyEnd(); ++key) {
+ std::string nm (name(key));
+ if (nm.size() > 56) nm.erase(nm.begin(), nm.begin()+nm.size()-32);
+ os << fmt
+ % (key >= 0 ? senf::str(key) : "")
+ % nm
+ % (isComplex(key) ? "yes" : "no")
+ % size(key);
+ }
+#endif
+}
+
+prefix_ void senf::dumpPacketAnnotationRegistry(std::ostream & os)
+{
+ senf::detail::AnnotationRegistry::instance().dumpRegistrations(os);
+}
+
+/////////////////////////////cc.e////////////////////////////////////////
#undef prefix_
//#include "PacketImpl.mpp"
///////////////////////////////cci.p///////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
-// senf::detail::AnnotationIndexerBase
+// senf::detail::AnnotationRegistry
-prefix_ senf::detail::AnnotationIndexerBase::~AnnotationIndexerBase()
-{}
+prefix_ void senf::detail::AnnotationRegistry::dump(key_t key, std::ostream & os,
+ void * annotation)
+ const
+{
+ Registry::const_iterator i (registry_.find(key));
+ if (i != registry_.end()) {
+ os << fieldName(i->second->v_name());
+ i->second->v_dump(os, annotation);
+ os << "\n";
+ }
+}
-prefix_ std::vector<bool> & senf::detail::AnnotationIndexerBase::small()
+prefix_ std::string senf::detail::AnnotationRegistry::name(key_t key)
+ const
{
- static std::vector<bool> smalls;
- return smalls;
+ Registry::const_iterator i (registry_.find(key));
+ return i == registry_.end() ? "" : i->second->v_name();
}
-prefix_ std::vector<senf::detail::AnnotationIndexerBase*> &
-senf::detail::AnnotationIndexerBase::registry()
+prefix_ bool senf::detail::AnnotationRegistry::isComplex(key_t key)
+ const
{
- static std::vector<AnnotationIndexerBase*> reg;
- return reg;
+ Registry::const_iterator i (registry_.find(key));
+ return i != registry_.end() && i->second->v_isComplex();
}
-///////////////////////////////////////////////////////////////////////////
-// senf::detail::AnnotationP
+prefix_ unsigned senf::detail::AnnotationRegistry::size(key_t key)
+ const
+{
+ Registry::const_iterator i (registry_.find(key));
+ return i == registry_.end() ? 0 : i->second->v_size();
+}
-prefix_ senf::detail::AnnotationP::~AnnotationP()
+prefix_ senf::detail::AnnotationRegistry::AnnotationRegistry()
+ : simpleAnnotationCount_ (0), complexAnnotationCount_ (0)
{}
+///////////////////////////////////////////////////////////////////////////
+
// Memory management:
//
// * The PacketImpl destructor will *explicitly* clean-up the interpreters_ list by removing
// senf::detail::PacketImpl
prefix_ senf::detail::PacketImpl::PacketImpl()
- : refcount_(0), annotations_(AnnotationIndexerBase::maxAnnotations)
-{}
+ : refcount_(0)
+{
+ ::memset(simpleAnnotations_, 0, sizeof(simpleAnnotations_));
+}
prefix_ senf::detail::PacketImpl::PacketImpl(size_type size, byte initValue)
- : refcount_(0), data_(size,initValue), annotations_(AnnotationIndexerBase::maxAnnotations)
-{}
+ : refcount_(0), data_(size,initValue)
+{
+ ::memset(simpleAnnotations_, 0, sizeof(simpleAnnotations_));
+}
// reference/memory management
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?
refcount_ -= n;
}
+// Annotations
+
+prefix_ void * senf::detail::PacketImpl::annotation(AnnotationRegistry::key_t key)
+{
+ return key >= 0 ? & simpleAnnotations_[key] : complexAnnotation(key);
+}
///////////////////////////////////////////////////////////////////////////
// senf::detail::PacketImpl::Guard
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2010
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief PacketImpl non-inline template implementation */
+
+#include "PacketImpl.ih"
+
+// Custom includes
+
+#define prefix_
+///////////////////////////////ct.p////////////////////////////////////////
+
+template <class Annotation>
+senf::detail::AnnotationRegistry::RegistrationProxy<Annotation>
+ senf::detail::AnnotationRegistry::Entry<Annotation>::proxy_;
+
+template <class Annotation>
+senf::detail::AnnotationRegistry::key_t
+ senf::detail::AnnotationRegistry::Entry<Annotation>::key_;
+
+template <class Annotation>
+prefix_ void * senf::detail::PacketImpl::complexAnnotation()
+{
+ AnnotationRegistry::key_t key (AnnotationRegistry::lookup<Annotation>());
+ void * rv (complexAnnotation(key));
+#ifndef SENF_PACKET_NO_COMPLEX_ANNOTATIONS
+ if (! rv) {
+ complexAnnotations_.replace(-key-1, new AnnotationRegistry::Entry<Annotation>());
+ rv = complexAnnotations_[-key-1].get();
+ }
+#endif
+ return rv;
+}
+
+///////////////////////////////ct.e////////////////////////////////////////
+#undef prefix_
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
/** \file
\brief PacketImpl inline template implementation */
-//#include "PacketImpl.ih"
+#include "PacketImpl.ih"
// Custom includes
///////////////////////////////cti.p///////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
-// senf::detail::AnnotationIndexer<Annotation>
+// senf::detail::AnnotationRegistry
template <class Annotation>
-prefix_ senf::detail::AnnotationIndexer<Annotation>::AnnotationIndexer()
- : index_ (maxAnnotations++)
+prefix_ key_t senf::detail::AnnotationRegistry::registerAnnotation()
{
- 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";
+ key_t key (simpleAnnotationCount_ >= SENF_PACKET_ANNOTATION_SLOTS
+ || IsComplexAnnotation<Annotation>::value
+ ? - ++complexAnnotationCount_
+ : simpleAnnotationCount_ ++);
+ registry_.insert(key, new Registration<Annotation>());
+ std::cerr << ">> allocated key " << key
+ << " for " << prettyName(typeid(Annotation))
+ << "(complex: " << IsComplexAnnotation<Annotation>::value
+ << ", convertible: " << boost::is_convertible<Annotation*, ComplexAnnotation*>::value
+ << ", size: " << sizeof(Annotation)
+ << ", max: " << SENF_PACKET_ANNOTATION_SLOTSIZE << ")" << std::endl;
+ return key;
}
template <class Annotation>
-prefix_ unsigned senf::detail::AnnotationIndexer<Annotation>::index()
-{
- return AnnotationIndexer::instance().index_;
-}
-
-///////////////////////////////////////////////////////////////////////////
-// senf::detail::GetAnnotation<Annotation,Small>
-
-template <class Annotation, bool Small>
-prefix_ Annotation & senf::detail::GetAnnotation<Annotation,Small>::get(AnnotationEntry & e)
-{
- if (!e.p)
- e.p = new TAnnotationP<Annotation>();
- 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)
+prefix_ key_t senf::detail::AnnotationRegistry::lookup()
{
- if (!e.p) os << "no value";
- else os << get(e);
+ SENF_ASSERT( instance().keyBegin() <= AnnotationRegistry::Entry<Annotation>::key()
+ && AnnotationRegistry::Entry<Annotation>::key() < instance().keyEnd(),
+ "internal error: annotation key not registered" );
+ SENF_ASSERT( AnnotationRegistry::Entry<Annotation>::key() < 0
+ || ! IsComplexAnnotation<Annotation>::value,
+ "internal error: complex annotation registered with invalid key" );
+ SENF_ASSERT( AnnotationRegistry::Entry<Annotation>::key() < SENF_PACKET_ANNOTATION_SLOTS,
+ "internal error: annotation key out of valid range" );
+ return AnnotationRegistry::Entry<Annotation>::key();
}
-template <class Annotation>
-prefix_ Annotation & senf::detail::GetAnnotation<Annotation, true>::get(AnnotationEntry & e)
+prefix_ key_t senf::detail::AnnotationRegistry::keyBegin()
+ const
{
- return * static_cast<Annotation*>(static_cast<void*>(& e.i));
+ return -complexAnnotationCount_;
}
-template <class Annotation>
-prefix_ void senf::detail::GetAnnotation<Annotation, true>::dump(AnnotationEntry & e,
- std::ostream & os)
+prefix_ key_t senf::detail::AnnotationRegistry::keyEnd()
+ const
{
- os << get(e);
+ return simpleAnnotationCount_;
}
///////////////////////////////////////////////////////////////////////////
template <class InputIterator>
prefix_ senf::detail::PacketImpl::PacketImpl(InputIterator first, InputIterator last)
- : refcount_(0), data_(first,last), annotations_(AnnotationIndexerBase::maxAnnotations)
-{}
+ : refcount_(0), data_(first,last)
+{
+ ::memset(simpleAnnotations_, 0, sizeof(simpleAnnotations_));
+}
// Annotations
template <class Annotation>
prefix_ Annotation & senf::detail::PacketImpl::annotation()
{
- return GetAnnotation<Annotation>::get(
- annotations_[AnnotationIndexer<Annotation>::index()]);
-}
-
-template <class Annotation>
-prefix_ void senf::detail::PacketImpl::dumpAnnotation(std::ostream & os)
-{
- GetAnnotation<Annotation>::dump(
- annotations_[AnnotationIndexer<Annotation>::index()], os);
+ AnnotationRegistry::key_t key (AnnotationRegistry::lookup<Annotation>());
+ void * antn (key >= 0 ? & simpleAnnotations_[key] : complexAnnotation<Annotation>());
+ SENF_ASSERT( antn, "internal error: null annotation pointer" );
+ return * static_cast<Annotation*>(antn);
}
///////////////////////////////cti.e///////////////////////////////////////
#include <memory>
#include <vector>
#include <boost/utility.hpp>
-#include <boost/type_traits/is_base_of.hpp>
-#include <boost/type_traits/has_trivial_constructor.hpp>
-#include <boost/type_traits/has_trivial_destructor.hpp>
#include <boost/static_assert.hpp>
+#include <boost/ptr_container/ptr_vector.hpp>
#include <senf/Utils/pool_alloc_mixin.hh>
#include <senf/Utils/singleton.hh>
//#include "PacketImpl.mpp"
+#include "PacketImpl.ih"
///////////////////////////////hh.p////////////////////////////////////////
namespace senf {
namespace detail {
- struct AnnotationP
- {
- virtual ~AnnotationP();
- };
-
- template <class Annotation>
- struct TAnnotationP
- : public AnnotationP
- {
- Annotation annotation;
- };
-
- union AnnotationEntry {
- AnnotationP * p;
- unsigned long long i;
- };
-
- 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>
- struct AnnotationIndexer
- : public senf::singleton< AnnotationIndexer<Annotation> >,
- 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;
- static bool const Small = (sizeof(Annotation) <= sizeof(AnnotationEntry) && ! Complex);
-
-# if 0 // The test is difficult since it does not work with user-defined trivial constructors
-# ifdef BOOST_HAS_TYPE_TRAITS_INTRINSICS
-
- BOOST_STATIC_ASSERT(( (boost::has_trivial_constructor<Annotation>::value
- && boost::has_trivial_destructor<Annotation>::value)
- || Complex ));
-
-# endif
-# endif
- };
-
- template <class Annotation, bool Small = AnnotationIndexer<Annotation>::Small>
- 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
\internal
// 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
};
private:
+ void eraseInterpreters(interpreter_list::iterator b, interpreter_list::iterator e);
+ void updateIterators(PacketData * self, difference_type pos, difference_type n);
+
+ void * annotation(AnnotationRegistry::key_t key); // may return 0 !
+ void * complexAnnotation(AnnotationRegistry::key_t key); // may return 0 !
+ template <class Annotation>
+ void * complexAnnotation();
+
refcount_t refcount_;
raw_container data_;
interpreter_list interpreters_;
- typedef std::vector<AnnotationEntry> Annotations;
- Annotations annotations_;
+ union SimpleAnnotationSlot
+ {
+ unsigned char _ [SENF_PACKET_ANNOTATION_SLOTSIZE];
+ };
- void eraseInterpreters(interpreter_list::iterator b, interpreter_list::iterator e);
- void updateIterators(PacketData * self, difference_type pos, difference_type n);
+ typedef boost::ptr_vector< boost::nullable<AnnotationRegistry::EntryBase> >
+ ComplexAnnotations;
+# ifndef SENF_PACKET_NO_COMPLEX_ANNOTATIONS
+ ComplexAnnotations complexAnnotations_;
+# endif
+
+ SimpleAnnotationSlot simpleAnnotations_[SENF_PACKET_ANNOTATION_SLOTS];
};
}}
#if !defined(HH_SENF_Packets_Packets__decls_) && !defined(HH_SENF_Packets_PacketImpl_i_)
#define HH_SENF_Packets_PacketImpl_i_
#include "PacketImpl.cci"
-//#include "PacketImpl.ct"
+#include "PacketImpl.ct"
#include "PacketImpl.cti"
#endif
// compile-command: "scons -u test"
// comment-column: 40
// End:
-
--- /dev/null
+// $Id$
+//
+// Copyright (C) 2010
+// Fraunhofer Institute for Open Communication Systems (FOKUS)
+// Competence Center NETwork research (NET), St. Augustin, GERMANY
+// Stefan Bund <g0dil@berlios.de>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the
+// Free Software Foundation, Inc.,
+// 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+/** \file
+ \brief PacketImpl internal header */
+
+#ifndef IH_SENF_senf_Packets_PacketImpl_
+#define IH_SENF_senf_Packets_PacketImpl_ 1
+
+// Custom includes
+#include <iostream>
+#include <string>
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/mpl/sizeof.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/or.hpp>
+#include <boost/mpl/greater.hpp>
+#include <boost/ptr_container/ptr_map.hpp>
+#include <senf/Utils/TypeInfo.hh>
+#include <senf/Utils/singleton.hh>
+#include <senf/config.hh>
+#include <senf/Utils/IgnoreValue.hh>
+
+///////////////////////////////ih.p////////////////////////////////////////
+
+namespace senf {
+
+ struct ComplexAnnotation;
+ void dumpPacketAnnotationRegistry(std::ostream & os);
+
+namespace detail {
+
+ template <class Annotation>
+ struct IsComplexAnnotation
+ : public boost::mpl::or_< boost::is_convertible<Annotation*, ComplexAnnotation*>,
+ boost::mpl::greater<
+ boost::mpl::sizeof_<Annotation>,
+ boost::mpl::int_<SENF_PACKET_ANNOTATION_SLOTSIZE> > >
+ {};
+
+ class AnnotationRegistry
+ : public senf::singleton<AnnotationRegistry>
+ {
+ public:
+ typedef int key_t;
+
+ using senf::singleton<AnnotationRegistry>::instance;
+
+ template <class Annotation> class RegistrationProxy;
+
+ class EntryBase;
+ template <class Annotation> class Entry;
+
+ template <class Annotation>
+ key_t registerAnnotation();
+
+ void dump(key_t key, std::ostream & os, void * annotation) const;
+ std::string name(key_t key) const;
+ bool isComplex(key_t key) const;
+ unsigned size(key_t key) const;
+
+ template <class Annotation>
+ static key_t lookup();
+
+ key_t keyBegin() const;
+ key_t keyEnd() const;
+
+ void dumpRegistrations(std::ostream & os);
+
+ private:
+ AnnotationRegistry();
+
+ struct RegistrationBase
+ {
+ virtual ~RegistrationBase () {};
+ key_t key;
+ virtual void v_dump(std::ostream & os, void * annotation) const = 0;
+ virtual std::string v_name() const = 0;
+ virtual bool v_isComplex() const = 0;
+ virtual unsigned v_size() const = 0;
+ };
+
+ template <class Annotation>
+ struct Registration
+ : public RegistrationBase
+ {
+ void v_dump(std::ostream & os, void * annotation) const
+ { os << * static_cast<Annotation*>(annotation); }
+ std::string v_name() const
+ { return prettyName(typeid(Annotation)); }
+ bool v_isComplex() const
+ { return boost::is_convertible<Annotation*, ComplexAnnotation*>::value; }
+ unsigned v_size() const
+ { return sizeof(Annotation); }
+ };
+
+ key_t simpleAnnotationCount_;
+ key_t complexAnnotationCount_;
+
+ typedef boost::ptr_map<key_t, RegistrationBase> Registry;
+ Registry registry_;
+
+ friend class senf::singleton<AnnotationRegistry>;
+ };
+
+ template <class Annotation>
+ class AnnotationRegistry::RegistrationProxy
+ {
+ public:
+ RegistrationProxy()
+ {
+ AnnotationRegistry::Entry<Annotation>::key_ =
+ AnnotationRegistry::instance().registerAnnotation<Annotation>();
+ }
+ };
+
+ class AnnotationRegistry::EntryBase
+ {
+ public:
+ virtual ~EntryBase() {}
+
+ virtual void * get() = 0;
+ };
+
+ template <class Annotation>
+ class AnnotationRegistry::Entry
+ : public AnnotationRegistry::EntryBase
+ {
+ static RegistrationProxy<Annotation> proxy_;
+ static AnnotationRegistry::key_t key_;
+ public:
+ // We use this member to force instantiation of proxy_ ...
+ static AnnotationRegistry::key_t key()
+ { senf::IGNORE(&proxy_); return key_; }
+
+ virtual void * get() { return & annotation_; }
+
+ private:
+ Annotation annotation_;
+
+ friend class AnnotationRegistry::RegistrationProxy<Annotation>;
+ };
+
+}}
+
+///////////////////////////////ih.e////////////////////////////////////////
+#endif
+
+\f
+// Local Variables:
+// mode: c++
+// fill-column: 100
+// comment-column: 40
+// c-file-style: "senf"
+// indent-tabs-mode: nil
+// ispell-local-dictionary: "american"
+// compile-command: "scons -u test"
+// End:
#include "Packets.hh"
#include "main.test.hh"
+#include <sstream>
#include <senf/Utils/auto_unit_test.hh>
#include <boost/test/test_tools.hpp>
prefix_ void senf::PacketInterpreterBase::dump(std::ostream & os)
{
try {
- if (detail::AnnotationIndexerBase::maxAnnotations > 0) {
+ if (detail::AnnotationRegistry::instance().keyBegin()
+ != detail::AnnotationRegistry::instance().keyEnd()) {
os << "Annotations:\n";
impl().dumpAnnotations(os);
}
# define SENF_PACKET_ANNOTATION_SLOTS 8
# endif
#
+# ifndef SENF_PACKET_ANNOTATION_SLOTSIZE
+# define SENF_PACKET_ANNOTATION_SLOTSIZE 16
+# endif
+#
//# define SENF_PACKET_NO_COMPLEX_ANNOTATIONS
-
///////////////////////////////hh.e////////////////////////////////////////
#endif