Fixed bug 1352 (Object attribute map / vector issue)

This commit is contained in:
Jaume Nin
2012-05-09 12:03:54 +02:00
parent d04597e168
commit a479c64051
7 changed files with 110 additions and 38 deletions

View File

@@ -51,6 +51,8 @@ Bugs fixed
- bug 1391 - .ns3rc does not allow comments as expected
- bug 1392 - Modules built report does not clarify C++ or Python
- bug 1395 - AODV DeferredRouteOutputTag missing constructor
- bug 1352 - Fixed MapAttributes, previously was mapped to a vector in ObjectPtrContainer
and (and key information was dropped). Now the container is a map.
Known issues
------------

View File

@@ -222,18 +222,20 @@ AttributeIterator::DoIterate (Ptr<Object> object)
}
continue;
}
// attempt to cast to an object vector.
// attempt to cast to an object container
const ObjectPtrContainerChecker *vectorChecker = dynamic_cast<const ObjectPtrContainerChecker *> (PeekPointer (info.checker));
if (vectorChecker != 0)
{
NS_LOG_DEBUG ("vector attribute " << info.name);
NS_LOG_DEBUG ("ObjectPtrContainer attribute " << info.name);
ObjectPtrContainerValue vector;
object->GetAttribute (info.name, vector);
StartVisitArrayAttribute (object, info.name, vector);
for (uint32_t j = 0; j < vector.GetN (); ++j)
ObjectPtrContainerValue::Iterator it;
for (it = vector.Begin (); it != vector.End (); ++it)
{
NS_LOG_DEBUG ("vector attribute item " << j);
Ptr<Object> tmp = vector.Get (j);
uint32_t j = (*it).first;
NS_LOG_DEBUG ("ObjectPtrContainer attribute item " << j);
Ptr<Object> tmp = (*it).second;
StartVisitArrayItem (vector, j, tmp);
m_examined.push_back (object);
DoIterate (tmp);

View File

@@ -20,7 +20,6 @@
#ifndef OBJECT_MAP_H
#define OBJECT_MAP_H
#include <vector>
#include "object.h"
#include "ptr.h"
#include "attribute.h"
@@ -39,17 +38,13 @@ Ptr<const AttributeChecker> MakeObjectMapChecker (void);
template <typename T, typename U, typename INDEX>
Ptr<const AttributeAccessor>
MakeObjectVectorAccessor (Ptr<U> (T::*get)(INDEX) const,
MakeObjectMapAccessor (Ptr<U> (T::*get)(INDEX) const,
INDEX (T::*getN)(void) const);
template <typename T, typename U, typename INDEX>
Ptr<const AttributeAccessor>
MakeObjectVectorAccessor (INDEX (T::*getN)(void) const,
Ptr<U> (T::*get)(INDEX) const);
} // namespace ns3
namespace ns3 {
MakeObjectMapAccessor (INDEX (T::*getN)(void) const,
Ptr<U> (T::*get)(INDEX) const);
template <typename T, typename U>
Ptr<const AttributeAccessor>
@@ -66,7 +61,7 @@ MakeObjectMapAccessor (U T::*memberVector)
*n = (obj->*m_memberVector).size ();
return true;
}
virtual Ptr<Object> DoGet (const ObjectBase *object, uint32_t i) const {
virtual Ptr<Object> DoGet (const ObjectBase *object, uint32_t i, uint32_t *index) const {
const T *obj = static_cast<const T *> (object);
typename U::const_iterator begin = (obj->*m_memberVector).begin ();
typename U::const_iterator end = (obj->*m_memberVector).end ();
@@ -75,6 +70,7 @@ MakeObjectMapAccessor (U T::*memberVector)
{
if (k == i)
{
*index = (*j).first;
return (*j).second;
break;
}
@@ -111,8 +107,6 @@ MakeObjectMapAccessor (INDEX (T::*getN)(void) const,
return MakeObjectPtrContainerAccessor<T,U,INDEX>(get, getN);
}
} // namespace ns3
#endif /* OBJECT_MAP_H */

View File

@@ -43,7 +43,7 @@ ObjectPtrContainerValue::GetN (void) const
Ptr<Object>
ObjectPtrContainerValue::Get (uint32_t i) const
{
return m_objects[i];
return m_objects.find (i)->second;
}
Ptr<AttributeValue>
@@ -55,10 +55,11 @@ std::string
ObjectPtrContainerValue::SerializeToString (Ptr<const AttributeChecker> checker) const
{
std::ostringstream oss;
for (uint32_t i = 0; i < m_objects.size (); ++i)
Iterator it;
for (it = Begin (); it != End (); ++it)
{
oss << m_objects[i];
if (i != m_objects.size () - 1)
oss << (*it).second;
if (it != End ())
{
oss << " ";
}
@@ -68,7 +69,7 @@ ObjectPtrContainerValue::SerializeToString (Ptr<const AttributeChecker> checker)
bool
ObjectPtrContainerValue::DeserializeFromString (std::string value, Ptr<const AttributeChecker> checker)
{
NS_FATAL_ERROR ("cannot deserialize a vector of object pointers.");
NS_FATAL_ERROR ("cannot deserialize a set of object pointers.");
return true;
}
@@ -95,8 +96,9 @@ ObjectPtrContainerAccessor::Get (const ObjectBase * object, AttributeValue &valu
}
for (uint32_t i = 0; i < n; i++)
{
Ptr<Object> o = DoGet (object, i);
v->m_objects.push_back (o);
uint32_t index;
Ptr<Object> o = DoGet (object, i, &index);
v->m_objects.insert (std::pair <uint32_t, Ptr<Object> > (index, o));
}
return true;
}

View File

@@ -20,7 +20,7 @@
#ifndef OBJECT_PTR_CONTAINER_H
#define OBJECT_PTR_CONTAINER_H
#include <vector>
#include <map>
#include "object.h"
#include "ptr.h"
#include "attribute.h"
@@ -30,7 +30,7 @@ namespace ns3 {
/**
* \ingroup object
*
* \brief contain a vector of ns3::Object pointers.
* \brief contain a set of ns3::Object pointers.
*
* This class it used to get attribute access to an array of
* ns3::Object pointers.
@@ -38,20 +38,20 @@ namespace ns3 {
class ObjectPtrContainerValue : public AttributeValue
{
public:
typedef std::vector<Ptr<Object> >::const_iterator Iterator;
typedef std::map<uint32_t, Ptr<Object> >::const_iterator Iterator;
ObjectPtrContainerValue ();
/**
* \returns an iterator to the first object contained in this vector
* \returns an iterator to the first object contained in this set
*/
Iterator Begin (void) const;
/**
* \returns an iterator to the last object contained in this vector
* \returns an iterator to the last object contained in this set
*/
Iterator End (void) const;
/**
* \returns the number of objects contained in this vector.
* \returns the number of objects contained in this set.
*/
uint32_t GetN (void) const;
/**
@@ -66,7 +66,7 @@ public:
private:
friend class ObjectPtrContainerAccessor;
std::vector<Ptr<Object> > m_objects;
std::map<uint32_t, Ptr<Object> > m_objects;
};
@@ -141,7 +141,7 @@ public:
virtual bool HasSetter (void) const;
private:
virtual bool DoGetN (const ObjectBase *object, uint32_t *n) const = 0;
virtual Ptr<Object> DoGet (const ObjectBase *object, uint32_t i) const = 0;
virtual Ptr<Object> DoGet (const ObjectBase *object, uint32_t i, uint32_t *index) const = 0;
};
template <typename T, typename U, typename INDEX>
@@ -160,8 +160,9 @@ MakeObjectPtrContainerAccessor (Ptr<U> (T::*get)(INDEX) const,
*n = (obj->*m_getN)();
return true;
}
virtual Ptr<Object> DoGet (const ObjectBase *object, uint32_t i) const {
virtual Ptr<Object> DoGet (const ObjectBase *object, uint32_t i, uint32_t *index) const {
const T *obj = static_cast<const T *> (object);
*index = i;
return (obj->*m_get)(i);
}
Ptr<U> (T::*m_get)(INDEX) const;

View File

@@ -20,7 +20,6 @@
#ifndef OBJECT_VECTOR_H
#define OBJECT_VECTOR_H
#include <vector>
#include "object.h"
#include "ptr.h"
#include "attribute.h"
@@ -47,10 +46,6 @@ Ptr<const AttributeAccessor>
MakeObjectVectorAccessor (INDEX (T::*getN)(void) const,
Ptr<U> (T::*get)(INDEX) const);
} // namespace ns3
namespace ns3 {
template <typename T, typename U>
Ptr<const AttributeAccessor>
MakeObjectVectorAccessor (U T::*memberVector)
@@ -66,7 +61,7 @@ MakeObjectVectorAccessor (U T::*memberVector)
*n = (obj->*m_memberVector).size ();
return true;
}
virtual Ptr<Object> DoGet (const ObjectBase *object, uint32_t i) const {
virtual Ptr<Object> DoGet (const ObjectBase *object, uint32_t i, uint32_t *index) const {
const T *obj = static_cast<const T *> (object);
typename U::const_iterator begin = (obj->*m_memberVector).begin ();
typename U::const_iterator end = (obj->*m_memberVector).end ();
@@ -75,6 +70,7 @@ MakeObjectVectorAccessor (U T::*memberVector)
{
if (k == i)
{
*index = k;
return *j;
break;
}

View File

@@ -27,6 +27,7 @@
#include "ns3/random-variable.h"
#include "ns3/double.h"
#include "ns3/object-vector.h"
#include "ns3/object-map.h"
#include "ns3/traced-value.h"
#include "ns3/callback.h"
#include "ns3/trace-source-accessor.h"
@@ -134,6 +135,10 @@ public:
MakeObjectVectorAccessor (&AttributeObjectTest::DoGetVectorN,
&AttributeObjectTest::DoGetVector),
MakeObjectVectorChecker<Derived> ())
.AddAttribute ("TestMap1", "help text",
ObjectMapValue (),
MakeObjectMapAccessor (&AttributeObjectTest::m_map1),
MakeObjectMapChecker<Derived> ())
.AddAttribute ("IntegerTraceSource1", "help text",
IntegerValue (-2),
MakeIntegerAccessor (&AttributeObjectTest::m_intSrc1),
@@ -192,6 +197,9 @@ public:
void AddToVector1 (void) { m_vector1.push_back (CreateObject<Derived> ()); }
void AddToVector2 (void) { m_vector2.push_back (CreateObject<Derived> ()); }
void AddToMap1 (uint32_t i) { m_map1.insert (std::pair <uint32_t, Ptr<Derived> > (i, CreateObject<Derived> ())); }
void InvokeCb (double a, int b, float c) { m_cb (a,b,c); }
void InvokeCbValue (int8_t a)
@@ -222,6 +230,7 @@ private:
RandomVariable m_random;
std::vector<Ptr<Derived> > m_vector1;
std::vector<Ptr<Derived> > m_vector2;
std::map <uint32_t, Ptr<Derived> > m_map1;
Callback<void,int8_t> m_cbValue;
TracedValue<int8_t> m_intSrc1;
TracedValue<int8_t> m_intSrc2;
@@ -722,6 +731,71 @@ ObjectVectorAttributeTestCase::DoRun (void)
NS_TEST_ASSERT_MSG_EQ (vector.GetN (), 2, "ObjectVectorValue \"TestVector1\" should be incremented");
}
// ===========================================================================
// Test case for Object Map Attributes.
// ===========================================================================
class ObjectMapAttributeTestCase : public TestCase
{
public:
ObjectMapAttributeTestCase (std::string description);
virtual ~ObjectMapAttributeTestCase () {}
private:
virtual void DoRun (void);
};
ObjectMapAttributeTestCase::ObjectMapAttributeTestCase (std::string description)
: TestCase (description)
{
}
void
ObjectMapAttributeTestCase::DoRun (void)
{
Ptr<AttributeObjectTest> p;
ObjectMapValue map;
p = CreateObject<AttributeObjectTest> ();
NS_TEST_ASSERT_MSG_NE (p, 0, "Unable to CreateObject");
//
// When the object is first created, the Attribute should have no items in
// the vector.
//
p->GetAttribute ("TestMap1", map);
NS_TEST_ASSERT_MSG_EQ (map.GetN (), 0, "Initial count of ObjectVectorValue \"TestMap1\" should be zero");
//
// Adding to the attribute shouldn't affect the value we already have.
//
p->AddToMap1 (1);
NS_TEST_ASSERT_MSG_EQ (map.GetN (), 0, "Initial count of ObjectVectorValue \"TestMap1\" should still be zero");
//
// Getting the attribute again should update the value.
//
p->GetAttribute ("TestMap1", map);
NS_TEST_ASSERT_MSG_EQ (map.GetN (), 1, "ObjectVectorValue \"TestMap1\" should be incremented");
//
// Get the Object pointer from the value.
//
Ptr<Object> a = map.Get (0);
NS_TEST_ASSERT_MSG_NE (a, 0, "Ptr<Object> from VectorValue \"TestMap1\" is zero");
//
// Adding to the attribute shouldn't affect the value we already have.
//
p->AddToMap1 (2);
NS_TEST_ASSERT_MSG_EQ (map.GetN (), 1, "Count of ObjectVectorValue \"TestMap1\" should still be one");
//
// Getting the attribute again should update the value.
//
p->GetAttribute ("TestMap1", map);
NS_TEST_ASSERT_MSG_EQ (map.GetN (), 2, "ObjectVectorValue \"TestMap1\" should be incremented");
}
// ===========================================================================
// Trace sources with value semantics can be used like Attributes. Make sure
// we can use them that way.
@@ -1172,6 +1246,7 @@ AttributesTestSuite::AttributesTestSuite ()
AddTestCase (new AttributeTestCase<EnumValue> ("Check Attributes of type EnumValue"));
AddTestCase (new AttributeTestCase<RandomVariableValue> ("Check Attributes of type RandomVariableValue"));
AddTestCase (new ObjectVectorAttributeTestCase ("Check Attributes of type ObjectVectorValue"));
AddTestCase (new ObjectMapAttributeTestCase ("Check Attributes of type ObjectMapValue"));
AddTestCase (new IntegerTraceSourceAttributeTestCase ("Ensure TracedValue<uint8_t> can be set like IntegerValue"));
AddTestCase (new IntegerTraceSourceTestCase ("Ensure TracedValue<uint8_t> also works as trace source"));
AddTestCase (new TracedCallbackTestCase ("Ensure TracedCallback<double, int, float> works as trace source"));