diff --git a/src/core/model/attribute-container.h b/src/core/model/attribute-container.h index 7505ab92c..999efdf51 100644 --- a/src/core/model/attribute-container.h +++ b/src/core/model/attribute-container.h @@ -21,7 +21,7 @@ #ifndef ATTRIBUTE_CONTAINER_H #define ATTRIBUTE_CONTAINER_H -#include +#include #include #include @@ -37,62 +37,151 @@ namespace ns3 { class AttributeChecker; // A = attribute value type, C = container type to return +/** + * A container for one type of attribute. + * + * The container uses \ref A to parse items into elements. + * Internally the container is always a list but an instance + * can return the items in a container specified by \ref C. + * + * @tparam A AttributeValue type to be contained. + * @tparam C Possibly templated container class returned by Get. + */ template class C=std::list> class AttributeContainerValue : public AttributeValue { public: + /** AttributeValue (element) type. */ typedef A attribute_type; + /** Type actually stored within the container. */ typedef Ptr value_type; + /** Internal container type. */ typedef std::list container_type; + /** stl-style Const iterator type. */ typedef typename container_type::const_iterator const_iterator; + /** stl-style Non-const iterator type. */ typedef typename container_type::iterator iterator; + /** Size type for container. */ typedef typename container_type::size_type size_type; + /** NS3 style iterator type. */ typedef typename AttributeContainerValue::const_iterator Iterator; // NS3 type // use underlying AttributeValue to get return element type + /** Item type of container returned by Get. */ typedef typename std::result_of::type item_type; + /** Type of container returned. */ typedef C result_type; + /** + * Default constructor. + * \param[in] sep Character separator between elements for parsing. + */ AttributeContainerValue (char sep = ','); + /** + * Construct from another container. + * @tparam CONTAINER[deduced] type of container passed for initialization. + * \param c Instance of CONTAINER with which to initialize AttributeContainerValue. + */ template AttributeContainerValue (const CONTAINER &c); + /** + * Construct from iterators. + * @tparam ITER[deduced] type of iterator. + * \param[in] begin Iterator that points to first initialization item. + * \param[in] end Iterator that points ones past last initialization item. + */ template AttributeContainerValue (const ITER begin, const ITER end); + /** Destructor. */ ~AttributeContainerValue (); + // Inherited Ptr Copy (void) const; - - bool DeserializeFromString (std::string value, Ptr checker); + bool DeserializeFromString (std::string value, Ptr checker); std::string SerializeToString (Ptr checker) const; // defacto pure virtuals to integrate with built-in accessor code + /** + * Return a container of items. + * \return Container of items. + */ result_type Get (void) const; + /** + * Copy items from container c. + * + * This method assumes \ref c has stl-style begin and end methods. + * The AttributeContainerValue value is cleared before copying from \ref c. + * @tparam T type of container. + * \param c Container from which to copy items. + */ template void Set (const T &c); // NS3 interface + /** + * NS3-style Number of items. + * \return Number of items in container. + */ size_type GetN (void) const; + /** + * NS3-style beginning of container. + * \return Iterator pointing to first time in container. + */ Iterator Begin (void); + /** + * NS3-style ending of container. + * \return Iterator pointing one past last item of container. + */ Iterator End (void); + // STL-interface + /** + * STL-style number of items in container + * \return number of items in container. + */ size_type size (void) const; + /** + * STL-style beginning of container. + * \return Iterator pointing to first item in container. + */ iterator begin (void); + /** + * STL-style end of container. + * \return Iterator pointing to one past last item in container. + */ iterator end (void); + /** + * STL-style const beginning of container. + * \return Const iterator pointing to first item in container. + */ const_iterator begin (void) const; + /** + * STL-style const end of container. + * \return Const iterator pointing to one past last item in container. + */ const_iterator end (void) const; private: + /** + * Copy items from \ref begin to \ref end. + * + * The internal container is cleared before values are copied + * using the push_back method. + * @tparam ITER[deduced] iterator type + * \param[in] begin Points to first item to copy + * \param[in] end Points to one after last item to copy + * \return This object with items copied. + */ template Ptr > CopyFrom (const ITER begin, const ITER end); - char m_sep; - container_type m_container; + char m_sep; //!< Item separator + container_type m_container; //!< Internal container }; -template class C> class AttributeContainerChecker : public AttributeChecker { public: @@ -101,22 +190,35 @@ public: }; /** - * Return checker using attribute value to provide types + * Make AttributeContainerChecker from AttributeContainerValue. + * @tparam A[deduced] AttributeValue type in container. + * @tparam C[deduced] Container type returned by Get. + * \param value[in] AttributeContainerValue from which to deduce types. + * \return AttributeContainerChecker for \ref value. */ template class C> -Ptr > +Ptr MakeAttributeContainerChecker (const AttributeContainerValue &value); /** - * Return checker give types explicitly, defaults same - * as AttributeContainerValue defaults + * Make AttributeContainerChecker using explicit types, initialize item checker. + * @tparam A AttributeValue type in container. + * @tparam C Container type returned by Get. + * \param itemchecker[in] AttributeChecker used for each item in the container. + * \return AttributeContainerChecker. */ template class C=std::list> -Ptr > +Ptr MakeAttributeContainerChecker (Ptr itemchecker); +/** + * Make unitialized AttributeContainerChecker using explicit types. + * @tparam A AttributeValue type in container. + * @tparam C Container type returned by Get. + * \return AttributeContainerChecker. + */ template class C=std::list> -Ptr > MakeAttributeContainerChecker (void); +Ptr MakeAttributeContainerChecker (void); template class C=std::list, typename T1> Ptr MakeAttributeContainerAccessor (T1 a1); @@ -129,10 +231,14 @@ Ptr MakeAttributeContainerAccessor (T1 a1); namespace ns3 { +// This internal class defines templated AttributeContainerChecker class that is instantiated +// in MakeAttributeContainerChecker. The non-templated base ns3::AttributeContainerChecker +// is returned from that function. This is the same pattern as ObjectPtrContainer. + namespace internal { template class C> -class AttributeContainerChecker : public ns3::AttributeContainerChecker +class AttributeContainerChecker : public ns3::AttributeContainerChecker { public: AttributeContainerChecker (void); @@ -171,32 +277,34 @@ AttributeContainerChecker::GetItemChecker (void) const } // namespace internal template class C> -Ptr > +Ptr MakeAttributeContainerChecker (const AttributeContainerValue &value) { return MakeAttributeContainerChecker (); } template class C> -Ptr > +Ptr MakeAttributeContainerChecker (Ptr itemchecker) { auto checker = MakeAttributeContainerChecker (); - checker->SetItemChecker (itemchecker); + auto acchecker = DynamicCast (checker); + acchecker->SetItemChecker (itemchecker); return checker; } template class C> -Ptr > +Ptr MakeAttributeContainerChecker (void) { - std::string typeName, underlyingType; + std::string containerType; + std::string underlyingType; typedef AttributeContainerValue T; { std::ostringstream oss; oss << "ns3::AttributeContainerValue<" << typeid (typename T::attribute_type).name () << ", " << typeid (typename T::container_type).name () << ">"; - typeName = oss.str (); + containerType = oss.str (); } { @@ -205,9 +313,7 @@ MakeAttributeContainerChecker (void) underlyingType = oss.str (); } - return DynamicCast > ( - MakeSimpleAttributeChecker > (typeName, underlyingType) - ); + return MakeSimpleAttributeChecker > (containerType, underlyingType); } template class C> @@ -253,7 +359,7 @@ template class C> bool AttributeContainerValue::DeserializeFromString (std::string value, Ptr checker) { - auto acchecker = DynamicCast > (checker); + auto acchecker = DynamicCast (checker); if (!acchecker) return false; std::istringstream iss (value); // copies value diff --git a/src/core/model/pair.h b/src/core/model/pair.h index 309e6f20d..0084e2faa 100644 --- a/src/core/model/pair.h +++ b/src/core/model/pair.h @@ -21,8 +21,7 @@ #ifndef PAIR_H #define PAIR_H -#include -#include +#include #include #include @@ -32,9 +31,6 @@ namespace ns3 { -class AttributeChecker; - -// TODO: useful to maybe define some kind of configurable formatter? template std::ostream & operator << (std::ostream &os, const std::pair &p) @@ -43,26 +39,49 @@ operator << (std::ostream &os, const std::pair &p) return os; } -// A = attribute value type, C = container type to return +// Doxygen for this class is auto-generated by +// utils/print-introspected-doxygen.h + +/** Hold objects of type std::pair. */ template class PairValue : public AttributeValue { public: + /** Type of value stored in the PairValue. */ typedef std::pair, Ptr > value_type; + /** Type of abscissa (first entry of pair). */ typedef typename std::result_of::type first_type; + /** Type of ordinal (second entry of pair). */ typedef typename std::result_of::type second_type; + /** Type returned by Get or passed in Set. */ typedef typename std::pair result_type; - typedef typename std::pair map_value_type; PairValue (); + + /** + * Construct this PairValue from a std::pair + * + * \param [in] value Value with which to construct. + */ PairValue (const result_type &value); // "import" constructor + // Inherited Ptr Copy (void) const; - bool DeserializeFromString (std::string value, Ptr checker); std::string SerializeToString (Ptr checker) const; + /** + * Get the stored value as a std::pair. + * + * This differs from the actual value stored in the object which is + * a pair of Ptr where AV is a class derived from AttributeValue. + * \return stored value as std::pair. + */ result_type Get (void) const; + /** + * Set the stored value. + * \param[in] value std::pair to be stored. + */ void Set (const result_type &value); template @@ -72,26 +91,60 @@ private: value_type m_value; }; -template class PairChecker : public AttributeChecker { public: typedef std::pair, Ptr > checker_pair_type; + /** + * Set the individual AttributeChecker for each pair entry. + * + * \param[in] firstchecker AttributeChecker for abscissa. + * \param[in] secondchecker AttributeChecker for ordinate. + */ virtual void SetCheckers (Ptr firstchecker, Ptr secondchecker) = 0; + + /** + * Get the pair of checkers for each pair entry. + * + * \return std::pair with AttributeChecker for each of abscissa and ordinate. + */ virtual checker_pair_type GetCheckers (void) const = 0; }; +/** + * Make a PairChecker from a PairValue. + * + * This function returns a Pointer to a non-const instance to + * allow subsequent setting of the underlying AttributeCheckers. + * \param[in] value PairValue from which to derive abscissa and ordinate types. + * \return Pointer to PairChecker instance. + */ template -Ptr > +Ptr MakePairChecker (const PairValue &value); +/** + * Make a PairChecker from abscissa and ordinate AttributeCheckers. + * + * This function returns a Pointer to a const instance since both + * underlying AttributeCheckers are set. + * + * \param[in] firstchecker AttributeChecker for abscissa. + * \param[in] secondchecker AttributeChecker for ordinate. + * \return Pointer to PairChecker instance. + */ template -Ptr > +Ptr MakePairChecker (Ptr firstchecker, Ptr secondchecker); +/** + * Make a PairChecker without abscissa and ordinate AttributeCheckers. + * + * \return Pointer to PairChecker instance. + */ template -Ptr > MakePairChecker (void); +Ptr MakePairChecker (void); template Ptr MakePairAccessor (T1 a1); @@ -104,16 +157,23 @@ Ptr MakePairAccessor (T1 a1); namespace ns3 { +// This internal class defines templated PairChecker class that is instantiated +// in MakePairChecker. The non-templated base ns3::PairChecker is returned in that +// function. This is the same pattern as ObjectPtrContainer. namespace internal { +/** + * Internal checker class templated to each AttributeChecker + * for each entry in the pair. + */ template -class PairChecker : public ns3::PairChecker +class PairChecker : public ns3::PairChecker { public: PairChecker (void); PairChecker (Ptr firstchecker, Ptr secondchecker); void SetCheckers (Ptr firstchecker, Ptr secondchecker); - typename ns3::PairChecker::checker_pair_type GetCheckers (void) const; + typename ns3::PairChecker::checker_pair_type GetCheckers (void) const; private: Ptr m_firstchecker; @@ -141,7 +201,7 @@ PairChecker::SetCheckers (Ptr firstchecker, Ptr -typename ns3::PairChecker::checker_pair_type +typename ns3::PairChecker::checker_pair_type PairChecker::GetCheckers (void) const { return std::make_pair (m_firstchecker, m_secondchecker); @@ -150,26 +210,28 @@ PairChecker::GetCheckers (void) const } // namespace internal template -Ptr > +Ptr MakePairChecker (const PairValue &value) { return MakePairChecker (); } template -Ptr > +Ptr MakePairChecker (Ptr firstchecker, Ptr secondchecker) { auto checker = MakePairChecker (); - checker->SetCheckers (firstchecker, secondchecker); + auto acchecker = DynamicCast (checker); + acchecker->SetCheckers (firstchecker, secondchecker); return checker; } template -Ptr > +Ptr MakePairChecker (void) { - std::string pairName, underlyingType; + std::string pairName; + std::string underlyingType; typedef PairValue T; std::string first_type_name = typeid (typename T::value_type::first_type).name (); std::string second_type_name = typeid (typename T::value_type::second_type).name (); @@ -185,9 +247,7 @@ MakePairChecker (void) underlyingType = oss.str (); } - return DynamicCast > ( - MakeSimpleAttributeChecker > (pairName, underlyingType) - ); + return MakeSimpleAttributeChecker > (pairName, underlyingType); } template @@ -217,7 +277,7 @@ template bool PairValue::DeserializeFromString (std::string value, Ptr checker) { - auto pchecker = DynamicCast > (checker); + auto pchecker = DynamicCast (checker); if (!pchecker) return false; std::istringstream iss (value); // copies value diff --git a/src/core/test/attribute-container-test-suite.cc b/src/core/test/attribute-container-test-suite.cc index cc22f9147..974b2295e 100644 --- a/src/core/test/attribute-container-test-suite.cc +++ b/src/core/test/attribute-container-test-suite.cc @@ -258,8 +258,8 @@ AttributeContainerSerializationTestCase::DoRun (void) AttributeContainerValue attr; auto checker = MakeAttributeContainerChecker (attr); - //auto acchecker = DynamicCast > (checker); - checker->SetItemChecker (MakeDoubleChecker ()); + auto acchecker = DynamicCast (checker); + acchecker->SetItemChecker (MakeDoubleChecker ()); NS_TEST_ASSERT_MSG_EQ (attr.DeserializeFromString (doubles, checker), true, "Deserialize failed"); NS_TEST_ASSERT_MSG_EQ (attr.GetN (), 3, "Incorrect container size"); @@ -275,7 +275,8 @@ AttributeContainerSerializationTestCase::DoRun (void) AttributeContainerValue attr; auto checker = MakeAttributeContainerChecker (attr); - checker->SetItemChecker (MakeIntegerChecker ()); + auto acchecker = DynamicCast (checker); + acchecker->SetItemChecker (MakeIntegerChecker ()); NS_TEST_ASSERT_MSG_EQ (attr.DeserializeFromString (ints, checker), true, "Deserialize failed"); NS_TEST_ASSERT_MSG_EQ (attr.GetN (), 4, "Incorrect container size"); @@ -290,7 +291,8 @@ AttributeContainerSerializationTestCase::DoRun (void) AttributeContainerValue attr (' '); auto checker = MakeAttributeContainerChecker (attr); - checker->SetItemChecker (MakeStringChecker ()); + auto acchecker = DynamicCast (checker); + acchecker->SetItemChecker (MakeStringChecker ()); NS_TEST_ASSERT_MSG_EQ (attr.DeserializeFromString (strings, checker), true, "Deserialize failed"); NS_TEST_ASSERT_MSG_EQ (attr.GetN (), 6, "Incorrect container size"); @@ -303,7 +305,8 @@ AttributeContainerSerializationTestCase::DoRun (void) std::string pairs = "one 1,two 2,three 3"; AttributeContainerValue > attr; auto checker = MakeAttributeContainerChecker (attr); - checker->SetItemChecker (MakePairChecker ( + auto acchecker = DynamicCast (checker); + acchecker->SetItemChecker (MakePairChecker ( MakeStringChecker (), MakeIntegerChecker ())); NS_TEST_ASSERT_MSG_EQ (attr.DeserializeFromString (pairs, checker), true, "Deserialization failed"); NS_TEST_ASSERT_MSG_EQ (attr.GetN (), 3, "Incorrect container size"); diff --git a/src/core/test/pair-value-test-suite.cc b/src/core/test/pair-value-test-suite.cc index 4993db727..e8d83011e 100644 --- a/src/core/test/pair-value-test-suite.cc +++ b/src/core/test/pair-value-test-suite.cc @@ -155,9 +155,10 @@ PairValueSettingsTestCase::DoRun () p->SetAttribute ("StringPair", PairValue (std::make_pair ("hello", "world"))); p->SetAttribute ("AddressPair", PairValue (std::make_pair (addr, 31))); - std::ostringstream oss, ref; + std::ostringstream oss; oss << *p; - + + std::ostringstream ref; ref << "StringPair = { (hello,world) } AddressPair = { (" << addr << ",31) }"; NS_TEST_ASSERT_MSG_EQ ((oss.str ()), (ref.str ()), "Pairs not correctly set"); diff --git a/src/core/wscript b/src/core/wscript index 580d6cb2a..97a100e50 100644 --- a/src/core/wscript +++ b/src/core/wscript @@ -339,6 +339,7 @@ def build(bld): 'model/object-factory.h', 'model/attribute-helper.h', 'model/attribute-container.h', + 'model/attribute-container-accessor-helper.h', 'model/global-value.h', 'model/traced-callback.h', 'model/traced-value.h', diff --git a/utils/print-introspected-doxygen.cc b/utils/print-introspected-doxygen.cc index 795561c51..7dec135eb 100644 --- a/utils/print-introspected-doxygen.cc +++ b/utils/print-introspected-doxygen.cc @@ -1572,7 +1572,7 @@ PrintAttributeImplementations (std::ostream & os) PrintMakeChecker (os, "ObjectMap", "object-map.h"); PrintAttributeValueSection (os, "Pair", false); - PrintAttributeValueWithName (os, "Pair", "Pair", "pair.h"); + PrintAttributeValueWithName (os, "Pair", "std::pair", "pair.h"); PrintMakeChecker (os, "Pair", "pair.h"); PrintAttributeValueSection (os, "AttributeContainer", false);