remove now-unused Tags class

This commit is contained in:
Mathieu Lacage
2008-04-24 16:01:53 -07:00
parent 5c7b34db46
commit 96c43a7e26
8 changed files with 34 additions and 1242 deletions

View File

@@ -103,7 +103,6 @@ Packet::Copy (void) const
Packet::Packet ()
: m_buffer (),
m_tags (),
m_tagList (),
m_metadata (m_globalUid, 0),
m_refCount (1)
@@ -113,7 +112,6 @@ Packet::Packet ()
Packet::Packet (const Packet &o)
: m_buffer (o.m_buffer),
m_tags (o.m_tags),
m_tagList (o.m_tagList),
m_metadata (o.m_metadata),
m_refCount (1)
@@ -127,7 +125,6 @@ Packet::operator = (const Packet &o)
return *this;
}
m_buffer = o.m_buffer;
m_tags = o.m_tags;
m_tagList = o.m_tagList;
m_metadata = o.m_metadata;
return *this;
@@ -135,7 +132,6 @@ Packet::operator = (const Packet &o)
Packet::Packet (uint32_t size)
: m_buffer (size),
m_tags (),
m_tagList (),
m_metadata (m_globalUid, size),
m_refCount (1)
@@ -144,7 +140,6 @@ Packet::Packet (uint32_t size)
}
Packet::Packet (uint8_t const*buffer, uint32_t size)
: m_buffer (),
m_tags (),
m_tagList (),
m_metadata (m_globalUid, size),
m_refCount (1)
@@ -155,9 +150,8 @@ Packet::Packet (uint8_t const*buffer, uint32_t size)
i.Write (buffer, size);
}
Packet::Packet (const Buffer &buffer, const Tags &tags, const MtagList &tagList, const PacketMetadata &metadata)
Packet::Packet (const Buffer &buffer, const MtagList &tagList, const PacketMetadata &metadata)
: m_buffer (buffer),
m_tags (tags),
m_tagList (tagList),
m_metadata (metadata),
m_refCount (1)
@@ -172,7 +166,7 @@ Packet::CreateFragment (uint32_t start, uint32_t length) const
PacketMetadata metadata = m_metadata.CreateFragment (start, end);
// again, call the constructor directly rather than
// through Create because it is private.
return Ptr<Packet> (new Packet (buffer, m_tags, m_tagList, metadata), false);
return Ptr<Packet> (new Packet (buffer, m_tagList, metadata), false);
}
uint32_t
@@ -270,7 +264,6 @@ Packet::RemoveAtStart (uint32_t size)
void
Packet::RemoveAllTags (void)
{
m_tags.RemoveAll ();
m_tagList.RemoveAll ();
}
@@ -289,8 +282,8 @@ Packet::GetUid (void) const
void
Packet::PrintTags (std::ostream &os) const
{
m_tags.Print (os, " ");
// XXX: tagList.
// XXX:
//m_tagList.Print (os, " ");
}
void
@@ -434,20 +427,20 @@ Packet::Serialize (void) const
m_metadata.Serialize (buffer.Begin (), reserve);
// write tags
reserve = m_tags.GetSerializedSize ();
buffer.AddAtStart (reserve);
m_tags.Serialize (buffer.Begin (), reserve);
//XXX
//reserve = m_tags.GetSerializedSize ();
//buffer.AddAtStart (reserve);
//m_tags.Serialize (buffer.Begin (), reserve);
// aggregate byte buffer, metadata, and tags
Buffer tmp = m_buffer.CreateFullCopy ();
buffer.AddAtStart (tmp.GetSize ());
buffer.Begin ().Write (tmp.Begin (), tmp.End ());
tmp.AddAtEnd (buffer);
// write byte buffer size.
buffer.AddAtStart (4);
buffer.Begin ().WriteU32 (m_buffer.GetSize ());
tmp.AddAtStart (4);
tmp.Begin ().WriteU32 (m_buffer.GetSize ());
return buffer;
return tmp;
}
void
Packet::Deserialize (Buffer buffer)
@@ -460,11 +453,13 @@ Packet::Deserialize (Buffer buffer)
// read buffer.
buf.RemoveAtEnd (buf.GetSize () - packetSize);
m_buffer = buf;
buffer.RemoveAtStart (4 + packetSize);
// read tags
buffer.RemoveAtStart (4 + packetSize);
uint32_t tagsDeserialized = m_tags.Deserialize (buffer.Begin ());
buffer.RemoveAtStart (tagsDeserialized);
//XXX
//uint32_t tagsDeserialized = m_tags.Deserialize (buffer.Begin ());
//buffer.RemoveAtStart (tagsDeserialized);
// read metadata
uint32_t metadataDeserialized =

View File

@@ -24,9 +24,7 @@
#include "buffer.h"
#include "header.h"
#include "trailer.h"
#include "tags.h"
#include "packet-metadata.h"
#include "tag.h"
#include "mtag.h"
#include "mtag-list.h"
#include "ns3/callback.h"
@@ -215,63 +213,6 @@ public:
* \returns the number of bytes removed from the end of the packet.
*/
uint32_t RemoveTrailer (Trailer &trailer);
/**
* \param tag a pointer to the tag to attach to this packet.
*
* Attach a tag to this packet. The tag is fully copied
* in a packet-specific internal buffer. This operation
* is expected to be really fast. The copy constructor of the
* tag is invoked to copy it into the tag buffer.
*
* Note that adding a tag is a const operation which is pretty
* un-intuitive. The rationale is that the content and behavior of
* a packet is _not_ changed when a tag is added to a packet: any
* code which was not aware of the new tag is going to work just
* the same if the new tag is added. The real reason why adding a
* tag was made a const operation is to allow a trace sink which gets
* a packet to tag the packet, even if the packet is const (and most
* trace sources should use const packets because it would be
* totally evil to allow a trace sink to modify the content of a
* packet).
*
*/
template <typename T>
void AddTag (T const &tag) const;
/**
* Remove a tag from this packet. The data stored internally
* for this tag is copied in the input tag if an instance
* of this tag type is present in the internal buffer. If this
* tag type is not present, the input tag is not modified.
*
* This operation can be potentially slow and might trigger
* unexpectedly large memory allocations. It is thus
* usually a better idea to create a copy of this packet,
* and invoke removeAllTags on the copy to remove all
* tags rather than remove the tags one by one from a packet.
*
* \param tag a pointer to the tag to remove from this packet
* \returns true if an instance of this tag type is stored
* in this packet, false otherwise.
*/
template <typename T>
bool RemoveTag (T &tag);
/**
* Copy a tag stored internally to the input tag. If no instance
* of this tag is present internally, the input tag is not modified.
* The copy constructor of the tag is invoked to copy it into the
* input tag variable.
*
* \param tag a pointer to the tag to read from this packet
* \returns true if an instance of this tag type is stored
* in this packet, false otherwise.
*/
template <typename T>
bool PeekTag (T &tag) const;
/**
* Remove all the tags stored in this packet. This operation is
* much much faster than invoking removeTag n times.
*/
void RemoveAllTags (void);
/**
* \param os output stream in which the data should be printed.
*
@@ -400,6 +341,17 @@ public:
*
* Tag each byte included in this packet with the
* new tag.
*
* Note that adding a tag is a const operation which is pretty
* un-intuitive. The rationale is that the content and behavior of
* a packet is _not_ changed when a tag is added to a packet: any
* code which was not aware of the new tag is going to work just
* the same if the new tag is added. The real reason why adding a
* tag was made a const operation is to allow a trace sink which gets
* a packet to tag the packet, even if the packet is const (and most
* trace sources should use const packets because it would be
* totally evil to allow a trace sink to modify the content of a
* packet).
*/
void AddMtag (const Mtag &tag) const;
/**
@@ -415,12 +367,16 @@ public:
*/
bool FindFirstMatchingTag (Mtag &tag) const;
/**
* Remove all the tags stored in this packet.
*/
void RemoveAllTags (void);
private:
Packet (const Buffer &buffer, const Tags &tags, const MtagList &tagList, const PacketMetadata &metadata);
Packet (const Buffer &buffer, const MtagList &tagList, const PacketMetadata &metadata);
Packet (const Packet &o);
Packet &operator = (const Packet &o);
Buffer m_buffer;
Tags m_tags;
MtagList m_tagList;
PacketMetadata m_metadata;
mutable uint32_t m_refCount;
@@ -467,42 +423,4 @@ std::ostream& operator<< (std::ostream& os, const Packet &packet);
} // namespace ns3
/**************************************************
Start of implementation of templates defined
above
*************************************************/
namespace ns3 {
template <typename T>
void Packet::AddTag (T const& tag) const
{
const Tag *parent;
// if the following assignment fails, it is because the
// input to this function is not a subclass of the Tag class.
parent = &tag;
m_tags.Add (tag);
}
template <typename T>
bool Packet::RemoveTag (T & tag)
{
Tag *parent;
// if the following assignment fails, it is because the
// input to this function is not a subclass of the Tag class.
parent = &tag;
return m_tags.Remove (tag);
}
template <typename T>
bool Packet::PeekTag (T & tag) const
{
Tag *parent;
// if the following assignment fails, it is because the
// input to this function is not a subclass of the Tag class.
parent = &tag;
return m_tags.Peek (tag);
}
} // namespace ns3
#endif /* PACKET_H */

View File

@@ -1,86 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2006 INRIA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* 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
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "tag-registry.h"
#include "ns3/fatal-error.h"
namespace ns3 {
TagRegistry::TagInfoVector *
TagRegistry::GetInfo (void)
{
static TagRegistry::TagInfoVector vector;
return &vector;
}
std::string
TagRegistry::GetUidString (uint32_t uid)
{
TagInfo info = (*GetInfo ())[uid - 1];
return info.uidString;
}
uint32_t
TagRegistry::GetUidFromUidString (std::string uidString)
{
TagInfoVector *vec = GetInfo ();
uint32_t uid = 1;
for (TagInfoVector::iterator i = vec->begin (); i != vec->end (); i++)
{
if (i->uidString == uidString)
{
return uid;
}
uid++;
}
NS_FATAL_ERROR ("We are trying to deserialize an un-registered type. This can't work.");
return 0;
}
void
TagRegistry::Destruct (uint32_t uid, uint8_t *data)
{
TagInfo info = (*GetInfo ())[uid - 1];
info.destruct (data);
}
void
TagRegistry::Print (uint32_t uid, uint8_t *data, std::ostream &os)
{
TagInfo info = (*GetInfo ())[uid - 1];
info.print (data, os);
}
uint32_t
TagRegistry::GetSerializedSize (uint32_t uid, uint8_t *data)
{
TagInfo info = (*GetInfo ())[uid - 1];
return info.getSerializedSize (data);
}
void
TagRegistry::Serialize (uint32_t uid, uint8_t *data, Buffer::Iterator start)
{
TagInfo info = (*GetInfo ())[uid - 1];
info.serialize (data, start);
}
uint32_t
TagRegistry::Deserialize (uint32_t uid, uint8_t *data, Buffer::Iterator start)
{
TagInfo info = (*GetInfo ())[uid - 1];
return info.deserialize (data, start);
}
} // namespace ns3

View File

@@ -1,148 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2006 INRIA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* 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
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef TAG_REGISTRY_H
#define TAG_REGISTRY_H
#include <string>
#include <stdint.h>
#include "buffer.h"
namespace ns3 {
/**
* \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.
*/
class TagRegistry
{
public:
template <typename T>
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);
static void Print (uint32_t uid, uint8_t *data, std::ostream &os);
static uint32_t GetSerializedSize (uint32_t uid, uint8_t *data);
static void Serialize (uint32_t uid, uint8_t *data, Buffer::Iterator start);
static uint32_t Deserialize (uint32_t uid, uint8_t *data, Buffer::Iterator start);
private:
typedef void (*DestructCb) (uint8_t *);
typedef void (*PrintCb) (uint8_t *, std::ostream &);
typedef uint32_t (*GetSerializedSizeCb) (uint8_t *);
typedef void (*SerializeCb) (uint8_t *, Buffer::Iterator);
typedef uint32_t (*DeserializeCb) (uint8_t *, Buffer::Iterator);
struct TagInfo
{
std::string uidString;
DestructCb destruct;
PrintCb print;
GetSerializedSizeCb getSerializedSize;
SerializeCb serialize;
DeserializeCb deserialize;
};
typedef std::vector<struct TagInfo> TagInfoVector;
template <typename T>
static void DoDestruct (uint8_t *data);
template <typename T>
static void DoPrint (uint8_t *data, std::ostream &os);
template <typename T>
static uint32_t DoGetSerializedSize (uint8_t *data);
template <typename T>
static void DoSerialize (uint8_t *data, Buffer::Iterator start);
template <typename T>
static uint32_t DoDeserialize (uint8_t *data, Buffer::Iterator start);
static TagInfoVector *GetInfo (void);
};
} // namespace ns3
namespace ns3 {
template <typename T>
void
TagRegistry::DoDestruct (uint8_t *data)
{
T *tag = reinterpret_cast<T *> (data);
tag->~T ();
}
template <typename T>
void
TagRegistry::DoPrint (uint8_t *data, std::ostream &os)
{
T *tag = reinterpret_cast<T *> (data);
tag->Print (os);
}
template <typename T>
uint32_t
TagRegistry::DoGetSerializedSize (uint8_t *data)
{
T *tag = reinterpret_cast<T *> (data);
return tag->GetSerializedSize ();
}
template <typename T>
void
TagRegistry::DoSerialize (uint8_t *data, Buffer::Iterator start)
{
T *tag = reinterpret_cast<T *> (data);
tag->Serialize (start);
}
template <typename T>
uint32_t
TagRegistry::DoDeserialize (uint8_t *data, Buffer::Iterator start)
{
T *tag = reinterpret_cast<T *> (data);
return tag->Deserialize (start);
}
template <typename T>
uint32_t
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 == uidString)
{
return j;
}
j++;
}
TagInfo info;
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;
}
} // namespace ns3
#endif /* TAG_REGISTRY_H */

View File

@@ -1,125 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2006 INRIA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* 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
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef TAG_H
#define TAG_H
#include <stdint.h>
#include <string>
/**
* \relates ns3::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) \
static class thisisaveryverylongclassname ##x \
{ \
public: \
thisisaveryverylongclassname ##x () \
{ uint32_t uid; uid = x::GetUid ();} \
} g_thisisanotherveryveryverylongname ## x;
namespace ns3 {
/**
* \brief a tag can be stored in a packet.
*
* A tag is a blob of 16 bytes of data which can be stored in
* a packet: a packet can contain an arbitrary number of tags
* and these tags are considered as "on-the-side" per-packet
* data structures which are not taken into account when calculating
* the size of the payload of a packet. They exist solely as
* simulation-specific objects.
*
* Tags are typically used to:
* - implement per-packet cross-layer communication
* - implement packet coloring: you could store a "color" tag
* in a packet to mark various types of packet for
* simulation analysis
*
* To create a new type of tag, you must create a subclass
* of the Tag base class which defines:
* - a public default constructor: needed for implementation
* purposes of the Packet code.
* - a public copy constructor: needed to copy a tag into
* a packet tag buffer when the user invokes Packet::AddTag
* - a public destructor: needed to destroy the copy of a tag
* stored in a packet buffer when the user invokes Packet::RemoveTag
* or when the packet is destroyed and the last reference to
* a tag instance disapears.
* - a public static method named GetUid: needed to uniquely
* the type of each tag instance.
* - a public method named Print: needed to print the content
* of a tag when the user calls Packet::PrintTags
* - a public method named GetSerializedSize: needed to serialize
* the content of a tag to a byte buffer when a packet must
* be sent from one computing node to another in a parallel
* simulation. If this method returns 0, it means that the
* tag does not need to be transfered from computing node to
* computing node
* - a public method named Serialize: perform the serialization
* to a byte buffer upon transfer to a new computing node in a
* parallel simulation.
* - a public method named Deserialize: invert the serialization
* from a byte buffer after being transfered to a new computing
* node in a parallel simulation.
*
* A detailed example of what these methods should look like
* and how they should be implemented is described in samples/main-packet-tag.cc
*/
class Tag
{
protected:
/**
* \param name the unique name of the new type of tag
* \returns a newly-allocated uid
*
* This method should be used by subclasses to implement
* their static public GetUid method.
*/
template <typename T>
static uint32_t AllocateUid (std::string name);
};
} // namespace ns3
// implementation below.
#include "tag-registry.h"
namespace ns3 {
template <typename T>
uint32_t
Tag::AllocateUid (std::string name)
{
return TagRegistry::Register<T> (name);
}
} // namespace ns3
#endif /* TAG_H */

View File

@@ -1,529 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2006 INRIA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* 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
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#include "tags.h"
#include <string.h>
#include "ns3/fatal-error.h"
namespace ns3 {
#ifdef USE_FREE_LIST
struct Tags::TagData *Tags::gFree = 0;
uint32_t Tags::gN_free = 0;
struct Tags::TagData *
Tags::AllocData (void) const
{
struct Tags::TagData *retval;
if (gFree != 0)
{
retval = gFree;
gFree = gFree->m_next;
gN_free--;
}
else
{
retval = new struct Tags::TagData ();
}
return retval;
}
void
Tags::FreeData (struct TagData *data) const
{
if (gN_free > 1000)
{
delete data;
return;
}
gN_free++;
data->m_next = gFree;
data->m_id = 0;
gFree = data;
}
#else
struct Tags::TagData *
Tags::AllocData (void) const
{
struct Tags::TagData *retval;
retval = new struct Tags::TagData ();
return retval;
}
void
Tags::FreeData (struct TagData *data) const
{
delete data;
}
#endif
bool
Tags::Remove (uint32_t id)
{
bool found = false;
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next)
{
if (cur->m_id == id)
{
found = true;
}
}
if (!found)
{
return false;
}
struct TagData *start = 0;
struct TagData **prevNext = &start;
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next)
{
if (cur->m_id == id)
{
/**
* XXX
* Note: I believe that we could optimize this to
* avoid copying each TagData located after the target id
* and just link the already-copied list to the next tag.
*/
continue;
}
struct TagData *copy = AllocData ();
copy->m_id = cur->m_id;
copy->m_count = 1;
copy->m_next = 0;
memcpy (copy->m_data, cur->m_data, Tags::SIZE);
*prevNext = copy;
prevNext = &copy->m_next;
}
*prevNext = 0;
RemoveAll ();
m_next = start;
return true;
}
void
Tags::Print (std::ostream &os, std::string separator) const
{
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next)
{
TagRegistry::Print (cur->m_id, cur->m_data, os);
if (cur->m_next != 0)
{
os << separator;
}
}
}
uint32_t
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 = TagRegistry::GetSerializedSize (cur->m_id, cur->m_data);
if (size != 0)
{
std::string uidString = TagRegistry::GetUidString (cur->m_id);
totalSize += 4; // for the size of the string itself.
totalSize += uidString.size ();
totalSize += size;
}
}
return totalSize;
}
void
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 = TagRegistry::GetSerializedSize (cur->m_id, cur->m_data);
if (size != 0)
{
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 ());
TagRegistry::Serialize (cur->m_id, cur->m_data, i);
}
}
}
uint32_t
Tags::Deserialize (Buffer::Iterator i)
{
uint32_t totalSize = i.ReadU32 ();
uint32_t bytesRead = 4;
while (bytesRead < totalSize)
{
uint32_t uidStringSize = i.ReadU32 ();
bytesRead += 4;
std::string uidString;
uidString.reserve (uidStringSize);
for (uint32_t j = 0; j < uidStringSize; j++)
{
uint32_t c = i.ReadU8 ();
uidString.push_back (c);
}
bytesRead += uidStringSize;
uint32_t uid = TagRegistry::GetUidFromUidString (uidString);
struct TagData *newStart = AllocData ();
newStart->m_count = 1;
newStart->m_next = 0;
newStart->m_id = uid;
bytesRead += TagRegistry::Deserialize (uid, newStart->m_data, i);
newStart->m_next = m_next;
m_next = newStart;
}
NS_ASSERT (bytesRead == totalSize);
/**
* The process of serialization/deserialization
* results in an inverted linked-list after
* deserialization so, we invert the linked-list
* in-place here.
* Note: the algorithm below is pretty classic
* but whenever I get to code it, it makes my
* brain hurt :)
*/
struct TagData *prev = 0;
struct TagData *cur = m_next;
while (cur != 0)
{
struct TagData *next = cur->m_next;
cur->m_next = prev;
prev = cur;
cur = next;
}
m_next = prev;
return totalSize;
}
}; // namespace ns3
#ifdef RUN_SELF_TESTS
#include "ns3/test.h"
#include <iomanip>
#include <iostream>
namespace ns3 {
static bool g_a;
static bool g_b;
static bool g_c;
static bool g_z;
class TagsTest : Test {
public:
TagsTest ();
virtual ~TagsTest ();
virtual bool RunTests (void);
};
class myTagA : public Tag
{
public:
static uint32_t GetUid (void) {static uint32_t uid = AllocateUid<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);}
uint32_t Deserialize (Buffer::Iterator i) {a = i.ReadU8 (); return 1;}
uint8_t a;
};
class myTagB : public Tag
{
public:
static uint32_t GetUid (void) {static uint32_t uid = AllocateUid<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);}
uint32_t Deserialize (Buffer::Iterator i) {b = i.ReadU32 (); return 4;}
uint32_t b;
};
class myTagC : public Tag
{
public:
static uint32_t GetUid (void) {static uint32_t uid = AllocateUid<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);}
uint32_t Deserialize (Buffer::Iterator i) {i.Read (c, Tags::SIZE); return Tags::SIZE;}
uint8_t c [Tags::SIZE];
};
class myInvalidTag : public Tag
{
public:
static uint32_t GetUid (void)
{static uint32_t uid = AllocateUid<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 {}
uint32_t Deserialize (Buffer::Iterator i) {return 0;}
uint8_t invalid [Tags::SIZE+1];
};
class myTagZ : public Tag
{
public:
static uint32_t GetUid (void) {static uint32_t uid = AllocateUid<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 {}
uint32_t Deserialize (Buffer::Iterator i) {return 0;}
uint8_t z;
};
class MySmartTag : public Tag
{
public:
static uint32_t GetUid (void)
{static uint32_t uid = AllocateUid<MySmartTag> ("MySmartTag.test.nsnam.org"); return uid;}
MySmartTag ()
{
//std::cout << "construct" << std::endl;
}
MySmartTag (const MySmartTag &o)
{
//std::cout << "copy" << std::endl;
}
~MySmartTag ()
{
//std::cout << "destruct" << std::endl;
}
MySmartTag &operator = (const MySmartTag &o)
{
//std::cout << "assign" << std::endl;
return *this;
}
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;}
};
TagsTest::TagsTest ()
: Test ("Tags")
{}
TagsTest::~TagsTest ()
{}
bool
TagsTest::RunTests (void)
{
bool ok = true;
// build initial tag.
Tags tags;
myTagA a;
a.a = 10;
tags.Add (a);
a.a = 0;
tags.Peek (a);
if (a.a != 10)
{
ok = false;
}
g_a = false;
tags.Print (std::cout, "");
if (!g_a)
{
ok = false;
}
myTagB b;
b.b = 0xff;
tags.Add (b);
b.b = 0;
tags.Peek (b);
if (b.b != 0xff)
{
ok = false;
}
g_b = false;
g_a = false;
tags.Print (std::cout, "");
if (!g_a || !g_b)
{
ok = false;
}
// make sure copy contains copy.
Tags other = tags;
g_b = false;
g_a = false;
other.Print (std::cout, "");
if (!g_a || !g_b)
{
ok = false;
}
g_b = false;
g_a = false;
tags.Print (std::cout, "");
if (!g_a || !g_b)
{
ok = false;
}
myTagA oA;
oA.a = 0;
other.Peek (oA);
if (oA.a != 10)
{
ok = false;
}
myTagB oB;
oB.b = 1;
other.Peek (oB);
if (oB.b != 0xff)
{
ok = false;
}
// remove data.
other.Remove (oA);
if (other.Peek (oA))
{
ok = false;
}
g_b = false;
g_a = false;
other.Print (std::cout, "");
if (g_a || !g_b)
{
ok = false;
}
if (!tags.Peek (oA))
{
ok = false;
}
other.Remove (oB);
if (other.Peek (oB))
{
ok = false;
}
if (!tags.Peek (oB))
{
ok = false;
}
other = tags;
Tags another = other;
myTagC c;
memset (c.c, 0x66, 16);
another.Add (c);
c.c[0] = 0;
another.Peek (c);
if (!another.Peek (c))
{
ok = false;
}
if (tags.Peek (c))
{
ok = false;
}
other = other;
//other.prettyPrint (std::cout);
//struct myInvalidTag invalid;
//tags.add (&invalid);
myTagZ tagZ;
Tags testLastTag;
tagZ.z = 0;
testLastTag.Add (tagZ);
g_z = false;
testLastTag.Print (std::cout, "");
if (!g_z)
{
ok = false;
}
MySmartTag smartTag;
{
Tags tmp;
tmp.Add (smartTag);
tmp.Peek (smartTag);
tmp.Remove (smartTag);
}
{
Tags source;
myTagA aSource;
aSource.a = 0x66;
source.Add (aSource);
Buffer buffer;
uint32_t serialized = source.GetSerializedSize ();
buffer.AddAtStart (serialized);
source.Serialize (buffer.Begin (), serialized);
Tags dest;
dest.Deserialize (buffer.Begin ());
myTagA aDest;
aDest.a = 0x55;
dest.Peek (aDest);
if (aDest.a != 0x66)
{
ok = false;
}
}
{
Tags source;
myTagA aSource;
aSource.a = 0x66;
source.Add (aSource);
myTagZ zSource;
zSource.z = 0x77;
source.Add (zSource);
Buffer buffer;
uint32_t serialized = source.GetSerializedSize ();
buffer.AddAtStart (serialized);
source.Serialize (buffer.Begin (), serialized);
Tags dest;
dest.Deserialize (buffer.Begin ());
myTagA aDest;
aDest.a = 0x55;
dest.Peek (aDest);
if (aDest.a != 0x66)
{
ok = false;
}
myTagZ zDest;
zDest.z = 0x44;
dest.Peek (zDest);
if (zDest.z != 0x44)
{
ok = false;
}
}
return ok;
}
static TagsTest gTagsTest;
}; // namespace ns3
#endif /* RUN_SELF_TESTS */

View File

@@ -1,228 +0,0 @@
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2006 INRIA
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* 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
*
* Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
*/
#ifndef TAGS_H
#define TAGS_H
#include <stdint.h>
#include <ostream>
#include <vector>
#include "buffer.h"
namespace ns3 {
/**
* \ingroup constants
* \brief Tag maximum size
* The maximum size (in bytes) of a Tag is stored
* in this constant.
*/
#define TAGS_MAX_SIZE 16
class Tags {
public:
inline Tags ();
inline Tags (Tags const &o);
inline Tags &operator = (Tags const &o);
inline ~Tags ();
template <typename T>
void Add (T const&tag) const;
template <typename T>
bool Remove (T &tag);
template <typename T>
bool Peek (T &tag) const;
void Print (std::ostream &os, std::string separator) const;
uint32_t GetSerializedSize (void) const;
void Serialize (Buffer::Iterator i, uint32_t size) const;
uint32_t Deserialize (Buffer::Iterator i);
inline void RemoveAll (void);
enum {
SIZE = TAGS_MAX_SIZE
};
private:
struct TagData {
uint8_t m_data[Tags::SIZE];
struct TagData *m_next;
uint32_t m_id;
uint32_t m_count;
};
bool Remove (uint32_t id);
struct Tags::TagData *AllocData (void) const;
void FreeData (struct TagData *data) const;
static struct Tags::TagData *gFree;
static uint32_t gN_free;
struct TagData *m_next;
};
} // namespace ns3
/**************************************************************
An implementation of the templates defined above
*************************************************************/
#include "tag-registry.h"
#include "tag.h"
#include "ns3/assert.h"
#include <string>
namespace ns3 {
template <typename T>
void
Tags::Add (T const&tag) const
{
const Tag *parent;
// if the following assignment fails, it is because the
// input to this function is not a subclass of the Tag class.
parent = &tag;
NS_ASSERT (sizeof (T) <= Tags::SIZE);
// ensure this id was not yet added
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next)
{
NS_ASSERT (cur->m_id != T::GetUid ());
}
struct TagData *newStart = AllocData ();
newStart->m_count = 1;
newStart->m_next = 0;
newStart->m_id = T::GetUid ();
void *buf = &newStart->m_data;
new (buf) T (tag);
newStart->m_next = m_next;
const_cast<Tags *> (this)->m_next = newStart;
}
template <typename T>
bool
Tags::Remove (T &tag)
{
Tag *parent;
// if the following assignment fails, it is because the
// input to this function is not a subclass of the Tag class.
parent = &tag;
NS_ASSERT (sizeof (T) <= Tags::SIZE);
if (Peek (tag))
{
Remove (T::GetUid ());
return true;
}
else
{
return false;
}
}
template <typename T>
bool
Tags::Peek (T &tag) const
{
Tag *parent;
// if the following assignment fails, it is because the
// input to this function is not a subclass of the Tag class.
parent = &tag;
NS_ASSERT (sizeof (T) <= Tags::SIZE);
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next)
{
if (cur->m_id == T::GetUid ())
{
/* found tag */
T *data = reinterpret_cast<T *> (&cur->m_data);
tag = T (*data);
return true;
}
}
/* no tag found */
return false;
}
Tags::Tags ()
: m_next ()
{}
Tags::Tags (Tags const &o)
: m_next (o.m_next)
{
if (m_next != 0)
{
m_next->m_count++;
}
}
Tags &
Tags::operator = (Tags const &o)
{
// self assignment
if (m_next == o.m_next)
{
return *this;
}
RemoveAll ();
m_next = o.m_next;
if (m_next != 0)
{
m_next->m_count++;
}
return *this;
}
Tags::~Tags ()
{
RemoveAll ();
}
void
Tags::RemoveAll (void)
{
struct TagData *prev = 0;
for (struct TagData *cur = m_next; cur != 0; cur = cur->m_next)
{
cur->m_count--;
if (cur->m_count > 0)
{
break;
}
if (prev != 0)
{
TagRegistry::Destruct (prev->m_id, prev->m_data);
FreeData (prev);
}
prev = cur;
}
if (prev != 0)
{
TagRegistry::Destruct (prev->m_id, prev->m_data);
FreeData (prev);
}
m_next = 0;
}
}; // namespace ns3
#endif /* TAGS_H */

View File

@@ -7,8 +7,6 @@ def build(bld):
'packet-metadata.cc',
'packet-metadata-test.cc',
'packet.cc',
'tags.cc',
'tag-registry.cc',
'chunk.cc',
'header.cc',
'trailer.cc',
@@ -27,9 +25,6 @@ def build(bld):
'chunk.h',
'header.h',
'trailer.h',
'tags.h',
'tag-registry.h',
'tag.h',
'packet.h',
'packet-metadata.h',
'pcap-writer.h',