--- a/samples/main-packet.cc Fri Aug 03 10:39:55 2007 +0200
+++ b/samples/main-packet.cc Fri Aug 03 13:00:38 2007 +0200
@@ -80,13 +80,18 @@
/* A sample Tag implementation
*/
-struct MyTag {
+class MyTag
+{
+public:
+ static const char *GetUid (void) {return "MyTag.test.nsnam.org";}
+ void Print (std::ostream &os) const {}
+ uint32_t GetSerializedSize (void) const {return 0;}
+ void Serialize (Buffer::Iterator i) const {}
+ uint32_t Deserialize (Buffer::Iterator i) {return 0;}
+
uint16_t m_streamId;
};
-static TagRegistration<struct MyTag> g_MyTagRegistration ("ns3::MyTag", 0);
-
-
static void
Receive (Packet p)
{
--- a/src/common/tags.cc Fri Aug 03 10:39:55 2007 +0200
+++ b/src/common/tags.cc Fri Aug 03 13:00:38 2007 +0200
@@ -23,80 +23,43 @@
namespace ns3 {
-TagRegistry *
-TagRegistry::GetInstance (void)
+Tag::TagInfoVector *
+Tag::GetInfo (void)
{
- static TagRegistry registry;
- return ®istry;
+ static Tag::TagInfoVector vector;
+ return &vector;
}
-TagRegistry::TagRegistry ()
- : m_sorted (false)
-{}
-
-
void
-TagRegistry::Record (std::string uuid, PrettyPrinter prettyPrinter, Destructor destructor)
+Tag::Destruct (uint32_t uid, uint8_t data[Tags::SIZE])
+{
+ TagInfo info = (*GetInfo ())[uid - 1];
+ info.destruct (data);
+}
+void
+Tag::Print (uint32_t uid, uint8_t data[Tags::SIZE], std::ostream &os)
{
- NS_ASSERT (!m_sorted);
- struct TagInfoItem item;
- item.uuid = uuid;
- item.printer = prettyPrinter;
- item.destructor = destructor;
- m_registry.push_back (item);
+ TagInfo info = (*GetInfo ())[uid - 1];
+ info.print (data, os);
}
-bool
-TagRegistry::CompareItem (const struct TagInfoItem &a, const struct TagInfoItem &b)
+uint32_t
+Tag::GetSerializedSize (uint32_t uid, uint8_t data[Tags::SIZE])
{
- return a.uuid < b.uuid;
+ TagInfo info = (*GetInfo ())[uid - 1];
+ return info.getSerializedSize (data);
+}
+void
+Tag::Serialize (uint32_t uid, uint8_t data[Tags::SIZE], Buffer::Iterator start)
+{
+ TagInfo info = (*GetInfo ())[uid - 1];
+ info.serialize (data, start);
}
uint32_t
-TagRegistry::LookupUid (std::string uuid)
+Tag::Deserialize (uint32_t uid, uint8_t data[Tags::SIZE], Buffer::Iterator start)
{
- if (!m_sorted)
- {
- std::sort (m_registry.begin (), m_registry.end (), &TagRegistry::CompareItem);
- m_sorted = true;
- }
- NS_ASSERT (m_sorted);
- uint32_t uid = 1;
- for (TagsDataCI i = m_registry.begin (); i != m_registry.end (); i++)
- {
- if (i->uuid == uuid)
- {
- return uid;
- }
- uid++;
- }
- // someone asked for a uid for an unregistered uuid.
- NS_ASSERT (!"You tried to use unregistered tag: make sure you create an instance of type TagRegistration<YouTagType>.");
- // quiet compiler
- return 0;
+ TagInfo info = (*GetInfo ())[uid - 1];
+ return info.deserialize (data, start);
}
-void
-TagRegistry::PrettyPrint (uint32_t uid, uint8_t buf[Tags::SIZE], std::ostream &os)
-{
- NS_ASSERT (uid > 0);
- uint32_t index = uid - 1;
- NS_ASSERT (m_registry.size () > index);
- PrettyPrinter prettyPrinter = m_registry[index].printer;
- if (prettyPrinter != 0)
- {
- prettyPrinter (buf, os);
- }
-}
-void
-TagRegistry::Destruct (uint32_t uid, uint8_t buf[Tags::SIZE])
-{
- NS_ASSERT (uid > 0);
- uint32_t index = uid - 1;
- NS_ASSERT (m_registry.size () > index);
- Destructor destructor = m_registry[index].destructor;
- NS_ASSERT (destructor != 0);
- destructor (buf);
-}
-
-
#ifdef USE_FREE_LIST
@@ -197,7 +160,7 @@
{
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next)
{
- TagRegistry::GetInstance ()->PrettyPrint (cur->m_id, cur->m_data, os);
+ Tag::Print (cur->m_id, cur->m_data, os);
}
}
@@ -224,25 +187,65 @@
virtual bool RunTests (void);
};
-struct myTagA {
+class myTagA
+{
+public:
+ static const char *GetUid (void) {return "myTagA.test.nsnam.org";}
+ void Print (std::ostream &os) const {g_a = true;}
+ uint32_t GetSerializedSize (void) const {return 0;}
+ void Serialize (Buffer::Iterator i) const {}
+ uint32_t Deserialize (Buffer::Iterator i) {return 0;}
+
uint8_t a;
};
-struct myTagB {
+class myTagB
+{
+public:
+ static const char *GetUid (void) {return "myTagB.test.nsnam.org";}
+ void Print (std::ostream &os) const {g_b = true;}
+ uint32_t GetSerializedSize (void) const {return 0;}
+ void Serialize (Buffer::Iterator i) const {}
+ uint32_t Deserialize (Buffer::Iterator i) {return 0;}
+
uint32_t b;
};
-struct myTagC {
+class myTagC
+{
+public:
+ static const char *GetUid (void) {return "myTagC.test.nsnam.org";}
+ void Print (std::ostream &os) const {g_c = true;}
+ uint32_t GetSerializedSize (void) const {return 0;}
+ void Serialize (Buffer::Iterator i) const {}
+ uint32_t Deserialize (Buffer::Iterator i) {return 0;}
uint8_t c [Tags::SIZE];
};
-struct myInvalidTag {
+class myInvalidTag
+{
+public:
+ static const char *GetUid (void) {return "myInvalidTag.test.nsnam.org";}
+ void Print (std::ostream &os) const {}
+ uint32_t GetSerializedSize (void) const {return 0;}
+ void Serialize (Buffer::Iterator i) const {}
+ uint32_t Deserialize (Buffer::Iterator i) {return 0;}
+
uint8_t invalid [Tags::SIZE+1];
};
-struct myTagZ {
+class myTagZ
+{
+public:
+ static const char *GetUid (void) {return "myTagZ.test.nsnam.org";}
+ void Print (std::ostream &os) const {g_z = true;}
+ uint32_t GetSerializedSize (void) const {return 0;}
+ void Serialize (Buffer::Iterator i) const {}
+ uint32_t Deserialize (Buffer::Iterator i) {return 0;}
+
uint8_t z;
};
class MySmartTag
{
public:
+ static const char *GetUid (void) {return "mySmartTag.test.nsnam.org";}
MySmartTag ()
{
//std::cout << "construct" << std::endl;
@@ -260,43 +263,12 @@
//std::cout << "assign" << std::endl;
return *this;
}
- static void PrettyPrinterCb (const MySmartTag *a, std::ostream &os)
- {}
+ void Print (std::ostream &os) const {}
+ uint32_t GetSerializedSize (void) const {return 0;}
+ void Serialize (Buffer::Iterator i) const {}
+ uint32_t Deserialize (Buffer::Iterator i) {return 0;}
};
-static void
-myTagAPrettyPrinterCb (struct myTagA const*a, std::ostream &os)
-{
- //os << "struct myTagA, a="<<(uint32_t)a->a<<std::endl;
- g_a = true;
-}
-static void
-myTagBPrettyPrinterCb (struct myTagB const*b, std::ostream &os)
-{
- //os << "struct myTagB, b="<<b->b<<std::endl;
- g_b = true;
-}
-static void
-myTagCPrettyPrinterCb (struct myTagC const*c, std::ostream &os)
-{
- //os << "struct myTagC, c="<<(uint32_t)c->c[0]<<std::endl;
- g_c = true;
-}
-static void
-myTagZPrettyPrinterCb (struct myTagZ const*z, std::ostream &os)
-{
- //os << "struct myTagZ" << std::endl;
- g_z = true;
-}
-
-
-static TagRegistration<struct myTagA> gMyTagARegistration ("A", &myTagAPrettyPrinterCb);
-static TagRegistration<struct myTagB> gMyTagBRegistration ("B", &myTagBPrettyPrinterCb);
-static TagRegistration<struct myTagC> gMyTagCRegistration ("C", &myTagCPrettyPrinterCb);
-static TagRegistration<struct myTagZ> g_myTagZRegistration ("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ",
- &myTagZPrettyPrinterCb);
-static TagRegistration<MySmartTag> g_myTagSmartRegistration ("SmartTag", &MySmartTag::PrettyPrinterCb);
-
TagsTest::TagsTest ()
: Test ("Tags")
@@ -311,7 +283,7 @@
// build initial tag.
Tags tags;
- struct myTagA a;
+ myTagA a;
a.a = 10;
tags.Add (a);
a.a = 0;
@@ -326,7 +298,7 @@
{
ok = false;
}
- struct myTagB b;
+ myTagB b;
b.b = 0xff;
tags.Add (b);
b.b = 0;
@@ -358,14 +330,14 @@
{
ok = false;
}
- struct myTagA oA;
+ myTagA oA;
oA.a = 0;
other.Peek (oA);
if (oA.a != 10)
{
ok = false;
}
- struct myTagB oB;
+ myTagB oB;
oB.b = 1;
other.Peek (oB);
if (oB.b != 0xff)
@@ -401,7 +373,7 @@
other = tags;
Tags another = other;
- struct myTagC c;
+ myTagC c;
memset (c.c, 0x66, 16);
another.Add (c);
c.c[0] = 0;
@@ -421,7 +393,7 @@
//struct myInvalidTag invalid;
//tags.add (&invalid);
- struct myTagZ tagZ;
+ myTagZ tagZ;
Tags testLastTag;
tagZ.z = 0;
testLastTag.Add (tagZ);
--- a/src/common/tags.h Fri Aug 03 10:39:55 2007 +0200
+++ b/src/common/tags.h Fri Aug 03 13:00:38 2007 +0200
@@ -24,6 +24,7 @@
#include <stdint.h>
#include <ostream>
#include <vector>
+#include "buffer.h"
namespace ns3 {
@@ -79,31 +80,7 @@
struct TagData *m_next;
};
-/**
- * \brief pretty print packet tags
- *
- * This class is used to register a pretty-printer
- * callback function to print in a nice user-friendly
- * way the content of the target type. To register
- * such a type, all you need to do is instantiate
- * an instance of this type as a static variable.
- */
-template <typename T>
-class TagRegistration {
-public:
- /**
- * \param uuid a uuid generated with uuidgen
- * \param fn a function which can pretty-print an instance
- * of type T in the output stream.
- */
- TagRegistration<T> (std::string uuid, void(*fn) (T const*, std::ostream &));
-private:
- static void PrettyPrinterCb (uint8_t *buf, std::ostream &os);
- static void DestructorCb (uint8_t *buf);
- static void(*m_prettyPrinter) (T const*, std::ostream &);
-};
-
-}; // namespace ns3
+} // namespace ns3
@@ -115,110 +92,118 @@
namespace ns3 {
-class TagRegistry {
+class Tag
+{
public:
- typedef void (*PrettyPrinter) (uint8_t [Tags::SIZE], std::ostream &);
- typedef void (*Destructor) (uint8_t [Tags::SIZE]);
- void Record (std::string uuid, PrettyPrinter prettyPrinter, Destructor destructor);
- /**
- * returns a numeric integer which uniquely identifies the input string.
- * that integer cannot be zero which is a reserved value.
- */
- uint32_t LookupUid (std::string uuid);
- void PrettyPrint (uint32_t uid, uint8_t buf[Tags::SIZE], std::ostream &os);
- void Destruct (uint32_t uid, uint8_t buf[Tags::SIZE]);
-
- static TagRegistry *GetInstance (void);
+ template <typename T>
+ static uint32_t GetUid (void);
+ static void Destruct (uint32_t uid, uint8_t data[Tags::SIZE]);
+ static void Print (uint32_t uid, uint8_t data[Tags::SIZE], std::ostream &os);
+ static uint32_t GetSerializedSize (uint32_t uid, uint8_t data[Tags::SIZE]);
+ static void Serialize (uint32_t uid, uint8_t data[Tags::SIZE], Buffer::Iterator start);
+ static uint32_t Deserialize (uint32_t uid, uint8_t data[Tags::SIZE], Buffer::Iterator start);
private:
- TagRegistry ();
- struct TagInfoItem
+ typedef void (*DestructCb) (uint8_t [Tags::SIZE]);
+ typedef void (*PrintCb) (uint8_t [Tags::SIZE], std::ostream &);
+ typedef uint32_t (*GetSerializedSizeCb) (uint8_t [Tags::SIZE]);
+ typedef void (*SerializeCb) (uint8_t [Tags::SIZE], Buffer::Iterator);
+ typedef uint32_t (*DeserializeCb) (uint8_t [Tags::SIZE], Buffer::Iterator);
+ struct TagInfo
{
- std::string uuid;
- PrettyPrinter printer;
- Destructor destructor;
+ std::string uidString;
+ DestructCb destruct;
+ PrintCb print;
+ GetSerializedSizeCb getSerializedSize;
+ SerializeCb serialize;
+ DeserializeCb deserialize;
};
- typedef std::vector<struct TagInfoItem> TagsData;
- typedef std::vector<struct TagInfoItem>::const_iterator TagsDataCI;
- static bool CompareItem (const struct TagInfoItem &a, const struct TagInfoItem &b);
- bool m_sorted;
- TagsData m_registry;
-};
-/**
- * The TypeUid class is used to create a mapping Type --> uid
- * Note that we use a static getUuid function which contains a
- * static std::string variable rather than a simpler static
- * member std::string variable to ensure the proper order
- * of initialization when these methods are invoked
- * from the constructor of another static variable.
- */
-template <typename T>
-class TypeUid {
-public:
- static void Record (std::string uuid);
- static const uint32_t GetUid (void);
-private:
- static std::string *GetUuid (void);
- T m_realType;
+ typedef std::vector<struct TagInfo> TagInfoVector;
+
+ template <typename T>
+ static void DoDestruct (uint8_t data[Tags::SIZE]);
+ template <typename T>
+ static void DoPrint (uint8_t data[Tags::SIZE], std::ostream &os);
+ template <typename T>
+ static uint32_t DoGetSerializedSize (uint8_t data[Tags::SIZE]);
+ template <typename T>
+ static void DoSerialize (uint8_t data[Tags::SIZE], Buffer::Iterator start);
+ template <typename T>
+ static uint32_t DoDeserialize (uint8_t data[Tags::SIZE], Buffer::Iterator start);
+ template <typename T>
+ static uint32_t AllocateUid (void);
+
+ static TagInfoVector *GetInfo (void);
};
template <typename T>
-void TypeUid<T>::Record (std::string uuid)
+void
+Tag::DoDestruct (uint8_t data[Tags::SIZE])
+{
+ T *tag = reinterpret_cast<T *> (data);
+ tag->~T ();
+}
+template <typename T>
+void
+Tag::DoPrint (uint8_t data[Tags::SIZE], std::ostream &os)
+{
+ T *tag = reinterpret_cast<T *> (data);
+ tag->Print (os);
+}
+template <typename T>
+uint32_t
+Tag::DoGetSerializedSize (uint8_t data[Tags::SIZE])
{
- *(GetUuid ()) = uuid;
+ T *tag = reinterpret_cast<T *> (data);
+ return tag->GetSerializedSize ();
+}
+template <typename T>
+void
+Tag::DoSerialize (uint8_t data[Tags::SIZE], Buffer::Iterator start)
+{
+ T *tag = reinterpret_cast<T *> (data);
+ tag->Serialize (start);
+}
+template <typename T>
+uint32_t
+Tag::DoDeserialize (uint8_t data[Tags::SIZE], Buffer::Iterator start)
+{
+ T *tag = reinterpret_cast<T *> (data);
+ return tag->Deserialize (start);
}
template <typename T>
-const uint32_t TypeUid<T>::GetUid (void)
+uint32_t
+Tag::GetUid (void)
{
- static const uint32_t uid = TagRegistry::GetInstance ()->
- LookupUid (*(GetUuid ()));
+ static uint32_t uid = AllocateUid<T> ();
return uid;
}
template <typename T>
-std::string *TypeUid<T>::GetUuid (void)
-{
- static std::string uuid;
- return &uuid;
-}
-
-
-
-/**
- * Implementation of the TagRegistration registration class.
- * It records a callback with the TagRegistry
- * This callback performs type conversion before forwarding
- * the call to the user-provided function.
- */
-template <typename T>
-TagRegistration<T>::TagRegistration (std::string uuid, void (*prettyPrinter) (T const*, std::ostream &))
+uint32_t
+Tag::AllocateUid (void)
{
- NS_ASSERT (sizeof (T) <= Tags::SIZE);
- m_prettyPrinter = prettyPrinter;
- TagRegistry::GetInstance ()->
- Record (uuid, &TagRegistration<T>::PrettyPrinterCb, &TagRegistration<T>::DestructorCb);
- TypeUid<T>::Record (uuid);
+ TagInfoVector *vec = GetInfo ();
+ uint32_t j = 0;
+ for (TagInfoVector::iterator i = vec->begin (); i != vec->end (); i++)
+ {
+ if (i->uidString == T::GetUid ())
+ {
+ return j;
+ }
+ j++;
+ }
+ TagInfo info;
+ info.uidString = T::GetUid ();
+ info.destruct = &Tag::DoDestruct<T>;
+ info.print = &Tag::DoPrint<T>;
+ info.getSerializedSize = &Tag::DoGetSerializedSize<T>;
+ info.serialize = &Tag::DoSerialize<T>;
+ info.deserialize = &Tag::DoDeserialize<T>;
+ vec->push_back (info);
+ uint32_t uid = vec->size ();
+ return uid;
}
-template <typename T>
-void
-TagRegistration<T>::PrettyPrinterCb (uint8_t *buf, std::ostream &os)
-{
- NS_ASSERT (sizeof (T) <= Tags::SIZE);
- T *tag = reinterpret_cast<T *> (buf);
- (*m_prettyPrinter) (tag, os);
-}
-template <typename T>
-void
-TagRegistration<T>::DestructorCb (uint8_t *buf)
-{
- T *tag = reinterpret_cast<T *> (buf);
- tag->~T ();
-}
-template <typename T>
-void (*TagRegistration<T>::m_prettyPrinter) (T const*, std::ostream &) = 0;
-
-
-
template <typename T>
void
@@ -228,12 +213,12 @@
// ensure this id was not yet added
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next)
{
- NS_ASSERT (cur->m_id != TypeUid<T>::GetUid ());
+ NS_ASSERT (cur->m_id != Tag::GetUid<T> ());
}
struct TagData *newStart = AllocData ();
newStart->m_count = 1;
newStart->m_next = 0;
- newStart->m_id = TypeUid<T>::GetUid ();
+ newStart->m_id = Tag::GetUid<T> ();
void *buf = &newStart->m_data;
new (buf) T (tag);
newStart->m_next = m_next;
@@ -245,7 +230,7 @@
Tags::Remove (T &tag)
{
NS_ASSERT (sizeof (T) <= Tags::SIZE);
- return Remove (TypeUid<T>::GetUid ());
+ return Remove (Tag::GetUid<T> ());
}
template <typename T>
@@ -255,7 +240,7 @@
NS_ASSERT (sizeof (T) <= Tags::SIZE);
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next)
{
- if (cur->m_id == TypeUid<T>::GetUid ())
+ if (cur->m_id == Tag::GetUid<T> ())
{
/* found tag */
T *data = reinterpret_cast<T *> (&cur->m_data);
@@ -315,16 +300,14 @@
}
if (prev != 0)
{
- TagRegistry::GetInstance ()->
- Destruct (prev->m_id, prev->m_data);
+ Tag::Destruct (prev->m_id, prev->m_data);
FreeData (prev);
}
prev = cur;
}
if (prev != 0)
{
- TagRegistry::GetInstance ()->
- Destruct (prev->m_id, prev->m_data);
+ Tag::Destruct (prev->m_id, prev->m_data);
FreeData (prev);
}
m_next = 0;