From d244597a2b39213dd642a67f8ca1e8421264f606 Mon Sep 17 00:00:00 2001 From: Jared Dulmage Date: Thu, 10 Sep 2020 16:43:51 -0600 Subject: [PATCH] Documentation, better conformance to AttributeChecker conventions Both PairChecker and AttributeContainerChecker factory functions modified to return more generic AttributeCheckers similar to other attribute types. By removing the templated return type, the internal templated classes become necessary to define checkers for each templated type. This follows the pattern in PointerChecker and ObjectContainerChecker. The pair-value-test-suite and attribute-container-test-suite were amended to account for the changes in the checker factories. All tests continue to pass. Plenty of documentation was added to PairValue and AttributeContainerValue and I also removed some dead code. --- src/core/model/attribute-container.h | 152 +++++++++++++++--- src/core/model/pair.h | 108 ++++++++++--- .../test/attribute-container-test-suite.cc | 13 +- src/core/test/pair-value-test-suite.cc | 5 +- src/core/wscript | 1 + utils/print-introspected-doxygen.cc | 2 +- 6 files changed, 226 insertions(+), 55 deletions(-) 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);