diff --git a/RELEASE_NOTES b/RELEASE_NOTES index 08b2faeab..f7c93b0cd 100644 --- a/RELEASE_NOTES +++ b/RELEASE_NOTES @@ -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 ------------ diff --git a/src/config-store/model/attribute-iterator.cc b/src/config-store/model/attribute-iterator.cc index f0559c5f3..7ee3dfda9 100644 --- a/src/config-store/model/attribute-iterator.cc +++ b/src/config-store/model/attribute-iterator.cc @@ -222,18 +222,20 @@ AttributeIterator::DoIterate (Ptr object) } continue; } - // attempt to cast to an object vector. + // attempt to cast to an object container const ObjectPtrContainerChecker *vectorChecker = dynamic_cast (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 tmp = vector.Get (j); + uint32_t j = (*it).first; + NS_LOG_DEBUG ("ObjectPtrContainer attribute item " << j); + Ptr tmp = (*it).second; StartVisitArrayItem (vector, j, tmp); m_examined.push_back (object); DoIterate (tmp); diff --git a/src/core/model/object-map.h b/src/core/model/object-map.h index dbf02fb7f..24524c7d2 100644 --- a/src/core/model/object-map.h +++ b/src/core/model/object-map.h @@ -20,7 +20,6 @@ #ifndef OBJECT_MAP_H #define OBJECT_MAP_H -#include #include "object.h" #include "ptr.h" #include "attribute.h" @@ -39,17 +38,13 @@ Ptr MakeObjectMapChecker (void); template Ptr -MakeObjectVectorAccessor (Ptr (T::*get)(INDEX) const, +MakeObjectMapAccessor (Ptr (T::*get)(INDEX) const, INDEX (T::*getN)(void) const); template Ptr -MakeObjectVectorAccessor (INDEX (T::*getN)(void) const, - Ptr (T::*get)(INDEX) const); - -} // namespace ns3 - -namespace ns3 { +MakeObjectMapAccessor (INDEX (T::*getN)(void) const, + Ptr (T::*get)(INDEX) const); template Ptr @@ -66,7 +61,7 @@ MakeObjectMapAccessor (U T::*memberVector) *n = (obj->*m_memberVector).size (); return true; } - virtual Ptr DoGet (const ObjectBase *object, uint32_t i) const { + virtual Ptr DoGet (const ObjectBase *object, uint32_t i, uint32_t *index) const { const T *obj = static_cast (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(get, getN); } - - } // namespace ns3 #endif /* OBJECT_MAP_H */ diff --git a/src/core/model/object-ptr-container.cc b/src/core/model/object-ptr-container.cc index e8660f4ae..d7afc1e6d 100644 --- a/src/core/model/object-ptr-container.cc +++ b/src/core/model/object-ptr-container.cc @@ -43,7 +43,7 @@ ObjectPtrContainerValue::GetN (void) const Ptr ObjectPtrContainerValue::Get (uint32_t i) const { - return m_objects[i]; + return m_objects.find (i)->second; } Ptr @@ -55,10 +55,11 @@ std::string ObjectPtrContainerValue::SerializeToString (Ptr 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 checker) bool ObjectPtrContainerValue::DeserializeFromString (std::string value, Ptr 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 o = DoGet (object, i); - v->m_objects.push_back (o); + uint32_t index; + Ptr o = DoGet (object, i, &index); + v->m_objects.insert (std::pair > (index, o)); } return true; } diff --git a/src/core/model/object-ptr-container.h b/src/core/model/object-ptr-container.h index c16944539..215a4056a 100644 --- a/src/core/model/object-ptr-container.h +++ b/src/core/model/object-ptr-container.h @@ -20,7 +20,7 @@ #ifndef OBJECT_PTR_CONTAINER_H #define OBJECT_PTR_CONTAINER_H -#include +#include #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 >::const_iterator Iterator; + typedef std::map >::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 > m_objects; + std::map > 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 DoGet (const ObjectBase *object, uint32_t i) const = 0; + virtual Ptr DoGet (const ObjectBase *object, uint32_t i, uint32_t *index) const = 0; }; template @@ -160,8 +160,9 @@ MakeObjectPtrContainerAccessor (Ptr (T::*get)(INDEX) const, *n = (obj->*m_getN)(); return true; } - virtual Ptr DoGet (const ObjectBase *object, uint32_t i) const { + virtual Ptr DoGet (const ObjectBase *object, uint32_t i, uint32_t *index) const { const T *obj = static_cast (object); + *index = i; return (obj->*m_get)(i); } Ptr (T::*m_get)(INDEX) const; diff --git a/src/core/model/object-vector.h b/src/core/model/object-vector.h index 953c21545..969e2228a 100644 --- a/src/core/model/object-vector.h +++ b/src/core/model/object-vector.h @@ -20,7 +20,6 @@ #ifndef OBJECT_VECTOR_H #define OBJECT_VECTOR_H -#include #include "object.h" #include "ptr.h" #include "attribute.h" @@ -47,10 +46,6 @@ Ptr MakeObjectVectorAccessor (INDEX (T::*getN)(void) const, Ptr (T::*get)(INDEX) const); -} // namespace ns3 - -namespace ns3 { - template Ptr MakeObjectVectorAccessor (U T::*memberVector) @@ -66,7 +61,7 @@ MakeObjectVectorAccessor (U T::*memberVector) *n = (obj->*m_memberVector).size (); return true; } - virtual Ptr DoGet (const ObjectBase *object, uint32_t i) const { + virtual Ptr DoGet (const ObjectBase *object, uint32_t i, uint32_t *index) const { const T *obj = static_cast (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; } diff --git a/src/core/test/attribute-test-suite.cc b/src/core/test/attribute-test-suite.cc index a5e45c1aa..876b21201 100644 --- a/src/core/test/attribute-test-suite.cc +++ b/src/core/test/attribute-test-suite.cc @@ -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 ()) + .AddAttribute ("TestMap1", "help text", + ObjectMapValue (), + MakeObjectMapAccessor (&AttributeObjectTest::m_map1), + MakeObjectMapChecker ()) .AddAttribute ("IntegerTraceSource1", "help text", IntegerValue (-2), MakeIntegerAccessor (&AttributeObjectTest::m_intSrc1), @@ -192,6 +197,9 @@ public: void AddToVector1 (void) { m_vector1.push_back (CreateObject ()); } void AddToVector2 (void) { m_vector2.push_back (CreateObject ()); } + + void AddToMap1 (uint32_t i) { m_map1.insert (std::pair > (i, CreateObject ())); } + 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 > m_vector1; std::vector > m_vector2; + std::map > m_map1; Callback m_cbValue; TracedValue m_intSrc1; TracedValue 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 p; + ObjectMapValue map; + + p = CreateObject (); + 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 a = map.Get (0); + NS_TEST_ASSERT_MSG_NE (a, 0, "Ptr 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 ("Check Attributes of type EnumValue")); AddTestCase (new AttributeTestCase ("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 can be set like IntegerValue")); AddTestCase (new IntegerTraceSourceTestCase ("Ensure TracedValue also works as trace source")); AddTestCase (new TracedCallbackTestCase ("Ensure TracedCallback works as trace source"));