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))
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)
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(),
#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
///////////////////////////////////////////////////////////////////////////
// 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
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_ (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>
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
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_
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>
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;
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
// 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
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);