Files
unison/src/core/model/pair.h
Jared Dulmage d244597a2b 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.
2020-09-20 15:33:38 -07:00

345 lines
9.8 KiB
C++

/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*- */
/*
* Copyright (c) 2018 Caliola Engineering, LLC.
*
* 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: Jared Dulmage <jared.dulmage@caliola.com>
*/
#ifndef PAIR_H
#define PAIR_H
#include <ns3/attribute-helper.h>
#include <ns3/string.h>
#include <sstream>
#include <typeinfo> // typeid
#include <type_traits>
#include <utility>
namespace ns3 {
template <class A, class B>
std::ostream &
operator << (std::ostream &os, const std::pair<A, B> &p)
{
os << "(" << p.first << "," << p.second << ")";
return os;
}
// Doxygen for this class is auto-generated by
// utils/print-introspected-doxygen.h
/** Hold objects of type std::pair<A, B>. */
template <class A, class B>
class PairValue : public AttributeValue
{
public:
/** Type of value stored in the PairValue. */
typedef std::pair<Ptr<A>, Ptr<B> > value_type;
/** Type of abscissa (first entry of pair). */
typedef typename std::result_of<decltype(&A::Get)(A)>::type first_type;
/** Type of ordinal (second entry of pair). */
typedef typename std::result_of<decltype(&B::Get)(B)>::type second_type;
/** Type returned by Get or passed in Set. */
typedef typename std::pair<first_type, second_type> result_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<AttributeValue> Copy (void) const;
bool DeserializeFromString (std::string value, Ptr<const AttributeChecker> checker);
std::string SerializeToString (Ptr<const AttributeChecker> 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<AV> where AV is a class derived from AttributeValue.
* \return stored value as std::pair<A, B>.
*/
result_type Get (void) const;
/**
* Set the stored value.
* \param[in] value std::pair<A, B> to be stored.
*/
void Set (const result_type &value);
template <typename T>
bool GetAccessor (T &value) const;
private:
value_type m_value;
};
class PairChecker : public AttributeChecker
{
public:
typedef std::pair<Ptr<const AttributeChecker>, Ptr<const AttributeChecker> > 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<const AttributeChecker> firstchecker, Ptr<const AttributeChecker> 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 <class A, class B>
Ptr<AttributeChecker>
MakePairChecker (const PairValue<A, B> &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 <class A, class B>
Ptr<const AttributeChecker>
MakePairChecker (Ptr<const AttributeChecker> firstchecker, Ptr<const AttributeChecker> secondchecker);
/**
* Make a PairChecker without abscissa and ordinate AttributeCheckers.
*
* \return Pointer to PairChecker instance.
*/
template <class A, class B>
Ptr<AttributeChecker> MakePairChecker (void);
template <typename A, typename B, typename T1>
Ptr<const AttributeAccessor> MakePairAccessor (T1 a1);
} // namespace ns3
/*****************************************************************************
* Implementation below
*****************************************************************************/
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 A, class B>
class PairChecker : public ns3::PairChecker
{
public:
PairChecker (void);
PairChecker (Ptr<const AttributeChecker> firstchecker, Ptr<const AttributeChecker> secondchecker);
void SetCheckers (Ptr<const AttributeChecker> firstchecker, Ptr<const AttributeChecker> secondchecker);
typename ns3::PairChecker::checker_pair_type GetCheckers (void) const;
private:
Ptr<const AttributeChecker> m_firstchecker;
Ptr<const AttributeChecker> m_secondchecker;
};
template <class A, class B>
PairChecker<A, B>::PairChecker (void)
: m_firstchecker (0),
m_secondchecker (0)
{}
template <class A, class B>
PairChecker<A, B>::PairChecker (Ptr<const AttributeChecker> firstchecker, Ptr<const AttributeChecker> secondchecker)
: m_firstchecker (firstchecker),
m_secondchecker (secondchecker)
{}
template <class A, class B>
void
PairChecker<A, B>::SetCheckers (Ptr<const AttributeChecker> firstchecker, Ptr<const AttributeChecker> secondchecker)
{
m_firstchecker = firstchecker;
m_secondchecker = secondchecker;
}
template <class A, class B>
typename ns3::PairChecker::checker_pair_type
PairChecker<A, B>::GetCheckers (void) const
{
return std::make_pair (m_firstchecker, m_secondchecker);
}
} // namespace internal
template <class A, class B>
Ptr<AttributeChecker>
MakePairChecker (const PairValue<A, B> &value)
{
return MakePairChecker <A, B> ();
}
template <class A, class B>
Ptr<const AttributeChecker>
MakePairChecker (Ptr<const AttributeChecker> firstchecker, Ptr<const AttributeChecker> secondchecker)
{
auto checker = MakePairChecker <A, B> ();
auto acchecker = DynamicCast<PairChecker> (checker);
acchecker->SetCheckers (firstchecker, secondchecker);
return checker;
}
template <class A, class B>
Ptr<AttributeChecker>
MakePairChecker (void)
{
std::string pairName;
std::string underlyingType;
typedef PairValue<A, B> 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 ();
{
std::ostringstream oss;
oss << "ns3::PairValue<" << first_type_name << ", " << second_type_name << ">";
pairName = oss.str ();
}
{
std::ostringstream oss;
oss << typeid (typename T::value_type).name ();
underlyingType = oss.str ();
}
return MakeSimpleAttributeChecker<T, internal::PairChecker<A, B> > (pairName, underlyingType);
}
template <class A, class B>
PairValue<A, B>::PairValue ()
: m_value (std::make_pair (Create <A> (), Create <B> ()))
{}
template <class A, class B>
PairValue<A, B>::PairValue (const typename PairValue<A, B>::result_type &value)
{
Set (value);
}
template <class A, class B>
Ptr<AttributeValue>
PairValue<A, B>::Copy (void) const
{
auto p = Create <PairValue <A, B> > ();
// deep copy if non-null
if (m_value.first)
p->m_value = std::make_pair (DynamicCast<A> (m_value.first->Copy ()),
DynamicCast<B> (m_value.second->Copy ()));
return p;
}
template <class A, class B>
bool
PairValue<A, B>::DeserializeFromString (std::string value, Ptr<const AttributeChecker> checker)
{
auto pchecker = DynamicCast<const PairChecker> (checker);
if (!pchecker) return false;
std::istringstream iss (value); // copies value
iss >> value;
auto first = pchecker->GetCheckers ().first->CreateValidValue (StringValue (value));
if (!first) return false;
auto firstattr = DynamicCast <A> (first);
if (!firstattr) return false;
iss >> value;
auto second = pchecker->GetCheckers ().second->CreateValidValue (StringValue (value));
if (!second) return false;
auto secondattr = DynamicCast <B> (second);
if (!secondattr) return false;
m_value = std::make_pair (firstattr, secondattr);
return true;
}
template <class A, class B>
std::string
PairValue<A, B>::SerializeToString (Ptr<const AttributeChecker> checker) const
{
std::ostringstream oss;
oss << m_value.first->SerializeToString (checker);
oss << " ";
oss << m_value.second->SerializeToString (checker);
return oss.str ();
}
template <class A, class B>
typename PairValue<A, B>::result_type
PairValue<A, B>::Get (void) const
{
return std::make_pair (m_value.first->Get (), m_value.second->Get ());
}
template <class A, class B>
void
PairValue<A, B>::Set (const typename PairValue<A, B>::result_type &value)
{
m_value = std::make_pair (Create <A> (value.first), Create <B> (value.second));
}
template <class A, class B>
template <typename T>
bool
PairValue<A, B>::GetAccessor (T &value) const
{
value = T (Get ());
return true;
}
template <typename A, typename B, typename T1>
Ptr<const AttributeAccessor> MakePairAccessor (T1 a1)
{
return MakeAccessorHelper<PairValue<A, B> > (a1);
}
} // namespace ns3
#endif // PAIR_H