update the Tag API to match the Header/Trailer API
This commit is contained in:
@@ -361,7 +361,7 @@ private:
|
||||
* {
|
||||
* // we really want to make sure that this
|
||||
* // string is unique in the universe.
|
||||
* static uint32_t uid = TagRegistry<MyTag> ("MyTag.unique.prefix");
|
||||
* static uint32_t uid = TagRegistry::Register<MyTag> ("MyTag.unique.prefix");
|
||||
* return uid;
|
||||
* }
|
||||
* \endcode
|
||||
|
||||
@@ -24,21 +24,21 @@
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
Tag::TagInfoVector *
|
||||
Tag::GetInfo (void)
|
||||
TagRegistry::TagInfoVector *
|
||||
TagRegistry::GetInfo (void)
|
||||
{
|
||||
static Tag::TagInfoVector vector;
|
||||
static TagRegistry::TagInfoVector vector;
|
||||
return &vector;
|
||||
}
|
||||
|
||||
std::string
|
||||
Tag::GetUidString (uint32_t uid)
|
||||
TagRegistry::GetUidString (uint32_t uid)
|
||||
{
|
||||
TagInfo info = (*GetInfo ())[uid - 1];
|
||||
return info.uidString;
|
||||
}
|
||||
uint32_t
|
||||
Tag::GetUidFromUidString (std::string uidString)
|
||||
TagRegistry::GetUidFromUidString (std::string uidString)
|
||||
{
|
||||
TagInfoVector *vec = GetInfo ();
|
||||
uint32_t uid = 1;
|
||||
@@ -55,31 +55,31 @@ Tag::GetUidFromUidString (std::string uidString)
|
||||
}
|
||||
|
||||
void
|
||||
Tag::Destruct (uint32_t uid, uint8_t data[Tags::SIZE])
|
||||
TagRegistry::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)
|
||||
TagRegistry::Print (uint32_t uid, uint8_t data[Tags::SIZE], std::ostream &os)
|
||||
{
|
||||
TagInfo info = (*GetInfo ())[uid - 1];
|
||||
info.print (data, os);
|
||||
}
|
||||
uint32_t
|
||||
Tag::GetSerializedSize (uint32_t uid, uint8_t data[Tags::SIZE])
|
||||
TagRegistry::GetSerializedSize (uint32_t uid, uint8_t data[Tags::SIZE])
|
||||
{
|
||||
TagInfo info = (*GetInfo ())[uid - 1];
|
||||
return info.getSerializedSize (data);
|
||||
}
|
||||
void
|
||||
Tag::Serialize (uint32_t uid, uint8_t data[Tags::SIZE], Buffer::Iterator start)
|
||||
TagRegistry::Serialize (uint32_t uid, uint8_t data[Tags::SIZE], Buffer::Iterator start)
|
||||
{
|
||||
TagInfo info = (*GetInfo ())[uid - 1];
|
||||
info.serialize (data, start);
|
||||
}
|
||||
uint32_t
|
||||
Tag::Deserialize (uint32_t uid, uint8_t data[Tags::SIZE], Buffer::Iterator start)
|
||||
TagRegistry::Deserialize (uint32_t uid, uint8_t data[Tags::SIZE], Buffer::Iterator start)
|
||||
{
|
||||
TagInfo info = (*GetInfo ())[uid - 1];
|
||||
return info.deserialize (data, start);
|
||||
@@ -184,7 +184,7 @@ Tags::Print (std::ostream &os) const
|
||||
{
|
||||
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next)
|
||||
{
|
||||
Tag::Print (cur->m_id, cur->m_data, os);
|
||||
TagRegistry::Print (cur->m_id, cur->m_data, os);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,10 +194,10 @@ Tags::GetSerializedSize (void) const
|
||||
uint32_t totalSize = 4; // reserve space for the size of the tag data.
|
||||
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next)
|
||||
{
|
||||
uint32_t size = Tag::GetSerializedSize (cur->m_id, cur->m_data);
|
||||
uint32_t size = TagRegistry::GetSerializedSize (cur->m_id, cur->m_data);
|
||||
if (size != 0)
|
||||
{
|
||||
std::string uidString = Tag::GetUidString (cur->m_id);
|
||||
std::string uidString = TagRegistry::GetUidString (cur->m_id);
|
||||
totalSize += 4; // for the size of the string itself.
|
||||
totalSize += uidString.size ();
|
||||
totalSize += size;
|
||||
@@ -212,14 +212,14 @@ Tags::Serialize (Buffer::Iterator i, uint32_t totalSize) const
|
||||
i.WriteU32 (totalSize);
|
||||
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next)
|
||||
{
|
||||
uint32_t size = Tag::GetSerializedSize (cur->m_id, cur->m_data);
|
||||
uint32_t size = TagRegistry::GetSerializedSize (cur->m_id, cur->m_data);
|
||||
if (size != 0)
|
||||
{
|
||||
std::string uidString = Tag::GetUidString (cur->m_id);
|
||||
std::string uidString = TagRegistry::GetUidString (cur->m_id);
|
||||
i.WriteU32 (uidString.size ());
|
||||
uint8_t *buf = (uint8_t *)uidString.c_str ();
|
||||
i.Write (buf, uidString.size ());
|
||||
Tag::Serialize (cur->m_id, cur->m_data, i);
|
||||
TagRegistry::Serialize (cur->m_id, cur->m_data, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -240,12 +240,12 @@ Tags::Deserialize (Buffer::Iterator i)
|
||||
uidString.push_back (c);
|
||||
}
|
||||
bytesRead += uidStringSize;
|
||||
uint32_t uid = Tag::GetUidFromUidString (uidString);
|
||||
uint32_t uid = TagRegistry::GetUidFromUidString (uidString);
|
||||
struct TagData *newStart = AllocData ();
|
||||
newStart->m_count = 1;
|
||||
newStart->m_next = 0;
|
||||
newStart->m_id = uid;
|
||||
bytesRead += Tag::Deserialize (uid, newStart->m_data, i);
|
||||
bytesRead += TagRegistry::Deserialize (uid, newStart->m_data, i);
|
||||
newStart->m_next = m_next;
|
||||
m_next = newStart;
|
||||
}
|
||||
@@ -299,7 +299,7 @@ public:
|
||||
class myTagA
|
||||
{
|
||||
public:
|
||||
static const char *GetUid (void) {return "myTagA.test.nsnam.org";}
|
||||
static uint32_t GetUid (void) {static uint32_t uid = TagRegistry::Register<myTagA> ("myTagA.test.nsnam.org"); return uid;}
|
||||
void Print (std::ostream &os) const {g_a = true;}
|
||||
uint32_t GetSerializedSize (void) const {return 1;}
|
||||
void Serialize (Buffer::Iterator i) const {i.WriteU8 (a);}
|
||||
@@ -310,7 +310,7 @@ public:
|
||||
class myTagB
|
||||
{
|
||||
public:
|
||||
static const char *GetUid (void) {return "myTagB.test.nsnam.org";}
|
||||
static uint32_t GetUid (void) {static uint32_t uid = TagRegistry::Register<myTagB> ("myTagB.test.nsnam.org"); return uid;}
|
||||
void Print (std::ostream &os) const {g_b = true;}
|
||||
uint32_t GetSerializedSize (void) const {return 4;}
|
||||
void Serialize (Buffer::Iterator i) const {i.WriteU32 (b);}
|
||||
@@ -321,7 +321,7 @@ public:
|
||||
class myTagC
|
||||
{
|
||||
public:
|
||||
static const char *GetUid (void) {return "myTagC.test.nsnam.org";}
|
||||
static uint32_t GetUid (void) {static uint32_t uid = TagRegistry::Register<myTagC> ("myTagC.test.nsnam.org"); return uid;}
|
||||
void Print (std::ostream &os) const {g_c = true;}
|
||||
uint32_t GetSerializedSize (void) const {return Tags::SIZE;}
|
||||
void Serialize (Buffer::Iterator i) const {i.Write (c, Tags::SIZE);}
|
||||
@@ -331,7 +331,8 @@ public:
|
||||
class myInvalidTag
|
||||
{
|
||||
public:
|
||||
static const char *GetUid (void) {return "myInvalidTag.test.nsnam.org";}
|
||||
static uint32_t GetUid (void)
|
||||
{static uint32_t uid = TagRegistry::Register<myInvalidTag> ("myinvalidTag.test.nsnam.org"); return uid;}
|
||||
void Print (std::ostream &os) const {}
|
||||
uint32_t GetSerializedSize (void) const {return 0;}
|
||||
void Serialize (Buffer::Iterator i) const {}
|
||||
@@ -342,7 +343,7 @@ public:
|
||||
class myTagZ
|
||||
{
|
||||
public:
|
||||
static const char *GetUid (void) {return "myTagZ.test.nsnam.org";}
|
||||
static uint32_t GetUid (void) {static uint32_t uid = TagRegistry::Register<myTagZ> ("myTagZ.test.nsnam.org"); return uid;}
|
||||
void Print (std::ostream &os) const {g_z = true;}
|
||||
uint32_t GetSerializedSize (void) const {return 0;}
|
||||
void Serialize (Buffer::Iterator i) const {}
|
||||
@@ -354,7 +355,8 @@ public:
|
||||
class MySmartTag
|
||||
{
|
||||
public:
|
||||
static const char *GetUid (void) {return "mySmartTag.test.nsnam.org";}
|
||||
static uint32_t GetUid (void)
|
||||
{static uint32_t uid = TagRegistry::Register<MySmartTag> ("MySmartTag.test.nsnam.org"); return uid;}
|
||||
MySmartTag ()
|
||||
{
|
||||
//std::cout << "construct" << std::endl;
|
||||
|
||||
@@ -26,6 +26,30 @@
|
||||
#include <vector>
|
||||
#include "buffer.h"
|
||||
|
||||
/**
|
||||
* \ingroup tag
|
||||
* \brief this macro should be instantiated exactly once for each
|
||||
* new type of Tag
|
||||
*
|
||||
* This macro will ensure that your new Tag type is registered
|
||||
* within the tag registry. In most cases, this macro
|
||||
* is not really needed but, for safety, please, use it all the
|
||||
* time.
|
||||
*
|
||||
* Note: This macro is _absolutely_ needed if you try to run a
|
||||
* distributed simulation.
|
||||
*/
|
||||
#define NS_TAG_ENSURE_REGISTERED(x) \
|
||||
namespace { \
|
||||
static class thisisaveryverylongclassname \
|
||||
{ \
|
||||
public: \
|
||||
thisisaveryverylongclassname () \
|
||||
{ uint32_t uid; uid = x::GetUid ();} \
|
||||
} g_thisisanotherveryveryverylongname; \
|
||||
}
|
||||
|
||||
|
||||
namespace ns3 {
|
||||
|
||||
template <typename T>
|
||||
@@ -96,30 +120,18 @@ private:
|
||||
namespace ns3 {
|
||||
|
||||
/**
|
||||
* \brief represent a single tag
|
||||
* \brief a registry of all existing tag types.
|
||||
* \internal
|
||||
*
|
||||
* This class is used to give polymorphic access to the methods
|
||||
* exported by a tag. It also is used to associate a single
|
||||
* reliable uid to each unique type. The tricky part here is
|
||||
* that we have to deal correctly with a single type
|
||||
* being registered multiple times in AllocateUid so,
|
||||
* AllocateUid must first check in the list of existing
|
||||
* types if there is already a type registered with the
|
||||
* same string returned by T::GetUid.
|
||||
*
|
||||
* It is important to note that, for example, this code
|
||||
* will never be triggered on ELF systems (linux, and
|
||||
* a lot of unixes) because the ELF runtime ensures that
|
||||
* there exist a single instance of a template instanciation
|
||||
* even if multiple instanciations of that template are
|
||||
* present in memory at runtime.
|
||||
* reliable uid to each unique type.
|
||||
*/
|
||||
class Tag
|
||||
class TagRegistry
|
||||
{
|
||||
public:
|
||||
template <typename T>
|
||||
static uint32_t GetUid (void);
|
||||
static uint32_t Register (std::string uidString);
|
||||
static std::string GetUidString (uint32_t uid);
|
||||
static uint32_t GetUidFromUidString (std::string uidString);
|
||||
static void Destruct (uint32_t uid, uint8_t data[Tags::SIZE]);
|
||||
@@ -154,43 +166,41 @@ private:
|
||||
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
|
||||
Tag::DoDestruct (uint8_t data[Tags::SIZE])
|
||||
TagRegistry::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)
|
||||
TagRegistry::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])
|
||||
TagRegistry::DoGetSerializedSize (uint8_t data[Tags::SIZE])
|
||||
{
|
||||
T *tag = reinterpret_cast<T *> (data);
|
||||
return tag->GetSerializedSize ();
|
||||
}
|
||||
template <typename T>
|
||||
void
|
||||
Tag::DoSerialize (uint8_t data[Tags::SIZE], Buffer::Iterator start)
|
||||
TagRegistry::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)
|
||||
TagRegistry::DoDeserialize (uint8_t data[Tags::SIZE], Buffer::Iterator start)
|
||||
{
|
||||
T *tag = reinterpret_cast<T *> (data);
|
||||
return tag->Deserialize (start);
|
||||
@@ -198,33 +208,25 @@ Tag::DoDeserialize (uint8_t data[Tags::SIZE], Buffer::Iterator start)
|
||||
|
||||
template <typename T>
|
||||
uint32_t
|
||||
Tag::GetUid (void)
|
||||
{
|
||||
static uint32_t uid = AllocateUid<T> ();
|
||||
return uid;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
uint32_t
|
||||
Tag::AllocateUid (void)
|
||||
TagRegistry::Register (std::string uidString)
|
||||
{
|
||||
TagInfoVector *vec = GetInfo ();
|
||||
uint32_t j = 0;
|
||||
for (TagInfoVector::iterator i = vec->begin (); i != vec->end (); i++)
|
||||
{
|
||||
if (i->uidString == T::GetUid ())
|
||||
if (i->uidString == uidString)
|
||||
{
|
||||
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>;
|
||||
info.uidString = uidString;
|
||||
info.destruct = &TagRegistry::DoDestruct<T>;
|
||||
info.print = &TagRegistry::DoPrint<T>;
|
||||
info.getSerializedSize = &TagRegistry::DoGetSerializedSize<T>;
|
||||
info.serialize = &TagRegistry::DoSerialize<T>;
|
||||
info.deserialize = &TagRegistry::DoDeserialize<T>;
|
||||
vec->push_back (info);
|
||||
uint32_t uid = vec->size ();
|
||||
return uid;
|
||||
@@ -238,12 +240,12 @@ Tags::Add (T const&tag)
|
||||
// ensure this id was not yet added
|
||||
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next)
|
||||
{
|
||||
NS_ASSERT (cur->m_id != Tag::GetUid<T> ());
|
||||
NS_ASSERT (cur->m_id != T::GetUid ());
|
||||
}
|
||||
struct TagData *newStart = AllocData ();
|
||||
newStart->m_count = 1;
|
||||
newStart->m_next = 0;
|
||||
newStart->m_id = Tag::GetUid<T> ();
|
||||
newStart->m_id = T::GetUid ();
|
||||
void *buf = &newStart->m_data;
|
||||
new (buf) T (tag);
|
||||
newStart->m_next = m_next;
|
||||
@@ -255,7 +257,7 @@ bool
|
||||
Tags::Remove (T &tag)
|
||||
{
|
||||
NS_ASSERT (sizeof (T) <= Tags::SIZE);
|
||||
return Remove (Tag::GetUid<T> ());
|
||||
return Remove (T::GetUid ());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -265,7 +267,7 @@ Tags::Peek (T &tag) const
|
||||
NS_ASSERT (sizeof (T) <= Tags::SIZE);
|
||||
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next)
|
||||
{
|
||||
if (cur->m_id == Tag::GetUid<T> ())
|
||||
if (cur->m_id == T::GetUid ())
|
||||
{
|
||||
/* found tag */
|
||||
T *data = reinterpret_cast<T *> (&cur->m_data);
|
||||
@@ -325,14 +327,14 @@ Tags::RemoveAll (void)
|
||||
}
|
||||
if (prev != 0)
|
||||
{
|
||||
Tag::Destruct (prev->m_id, prev->m_data);
|
||||
TagRegistry::Destruct (prev->m_id, prev->m_data);
|
||||
FreeData (prev);
|
||||
}
|
||||
prev = cur;
|
||||
}
|
||||
if (prev != 0)
|
||||
{
|
||||
Tag::Destruct (prev->m_id, prev->m_data);
|
||||
TagRegistry::Destruct (prev->m_id, prev->m_data);
|
||||
FreeData (prev);
|
||||
}
|
||||
m_next = 0;
|
||||
|
||||
Reference in New Issue
Block a user