Ref T557 Metaclass flag to preserve measurement unit when marshalling PQ's in flight plans.

This commit is contained in:
Mat Sutcliffe
2019-03-04 01:14:09 +00:00
parent 567a55503f
commit 83dec5408b
10 changed files with 114 additions and 31 deletions

View File

@@ -45,6 +45,7 @@ namespace BlackMisc
public Mixin::CompareByMetaClass<CAltitude>, public Mixin::CompareByMetaClass<CAltitude>,
public Mixin::HashByMetaClass<CAltitude>, public Mixin::HashByMetaClass<CAltitude>,
public Mixin::DBusByMetaClass<CAltitude>, public Mixin::DBusByMetaClass<CAltitude>,
public Mixin::DBusByMetaClass<CAltitude, LosslessTag>,
public Mixin::JsonByMetaClass<CAltitude>, public Mixin::JsonByMetaClass<CAltitude>,
public Mixin::String<CAltitude>, public Mixin::String<CAltitude>,
public Mixin::Icon<CAltitude>, public Mixin::Icon<CAltitude>,
@@ -57,6 +58,7 @@ namespace BlackMisc
BLACKMISC_DECLARE_USING_MIXIN_METATYPE(CAltitude) BLACKMISC_DECLARE_USING_MIXIN_METATYPE(CAltitude)
BLACKMISC_DECLARE_USING_MIXIN_STRING(CAltitude) BLACKMISC_DECLARE_USING_MIXIN_STRING(CAltitude)
BLACKMISC_DECLARE_USING_MIXIN_DBUS(CAltitude) BLACKMISC_DECLARE_USING_MIXIN_DBUS(CAltitude)
BLACKMISC_DECLARE_USING_MIXIN_DBUS(CAltitude, LosslessTag)
BLACKMISC_DECLARE_USING_MIXIN_JSON(CAltitude) BLACKMISC_DECLARE_USING_MIXIN_JSON(CAltitude)
BLACKMISC_DECLARE_USING_MIXIN_ICON(CAltitude) BLACKMISC_DECLARE_USING_MIXIN_ICON(CAltitude)
BLACKMISC_DECLARE_USING_MIXIN_INDEX(CAltitude) BLACKMISC_DECLARE_USING_MIXIN_INDEX(CAltitude)

View File

@@ -449,11 +449,11 @@ namespace BlackMisc
BLACK_METAMEMBER(alternateAirportIcao), BLACK_METAMEMBER(alternateAirportIcao),
BLACK_METAMEMBER(takeoffTimePlanned), BLACK_METAMEMBER(takeoffTimePlanned),
BLACK_METAMEMBER(takeoffTimeActual), BLACK_METAMEMBER(takeoffTimeActual),
BLACK_METAMEMBER(enrouteTime), BLACK_METAMEMBER(enrouteTime, 0, LosslessMarshalling),
BLACK_METAMEMBER(fuelTime), BLACK_METAMEMBER(fuelTime, 0, LosslessMarshalling),
BLACK_METAMEMBER(cruiseAltitude), BLACK_METAMEMBER(cruiseAltitude, 0, LosslessMarshalling),
BLACK_METAMEMBER(cruiseAltitudeString), BLACK_METAMEMBER(cruiseAltitudeString),
BLACK_METAMEMBER(cruiseTrueAirspeed), BLACK_METAMEMBER(cruiseTrueAirspeed, 0, LosslessMarshalling),
BLACK_METAMEMBER(flightRules), BLACK_METAMEMBER(flightRules),
BLACK_METAMEMBER(route), BLACK_METAMEMBER(route),
BLACK_METAMEMBER(remarks), BLACK_METAMEMBER(remarks),

View File

@@ -22,20 +22,27 @@ namespace BlackMisc
{ {
class CEmpty; class CEmpty;
/*!
* Tag type signifying overloaded marshalling methods that preserve data at the expense of size.
*/
class LosslessTag {};
namespace Private namespace Private
{ {
//! \cond PRIVATE //! \cond PRIVATE
template <class T, std::enable_if_t<THasMarshallMethods<T>::value, int> = 0> template <class T, std::enable_if_t<THasMarshallMethods<T>::value, int> = 0>
void marshallMember(QDBusArgument &arg, const T &value) { value.marshallToDbus(arg); } void marshallMember(QDBusArgument &arg, const T &value, std::false_type) { value.marshallToDbus(arg); }
template <class T, std::enable_if_t<THasMarshallMethods<T>::value, int> = 0>
void marshallMember(QDBusArgument &arg, const T &value, std::true_type) { value.marshallToDbus(arg, LosslessTag()); }
template <class T, std::enable_if_t<!THasMarshallMethods<T>::value, int> = 0> template <class T, std::enable_if_t<!THasMarshallMethods<T>::value, int> = 0>
void marshallMember(QDBusArgument &arg, const T &value) { arg << value; } void marshallMember(QDBusArgument &arg, const T &value, std::false_type) { arg << value; }
template <class T, std::enable_if_t<THasMarshallMethods<T>::value, int> = 0> template <class T, std::enable_if_t<THasMarshallMethods<T>::value, int> = 0>
void unmarshallMember(const QDBusArgument &arg, T &value) { value.unmarshallFromDbus(arg); } void unmarshallMember(const QDBusArgument &arg, T &value, std::false_type) { value.unmarshallFromDbus(arg); }
template <class T, std::enable_if_t<THasMarshallMethods<T>::value, int> = 0>
void unmarshallMember(const QDBusArgument &arg, T &value, std::true_type) { value.unmarshallFromDbus(arg, LosslessTag()); }
template <class T, std::enable_if_t<!THasMarshallMethods<T>::value, int> = 0> template <class T, std::enable_if_t<!THasMarshallMethods<T>::value, int> = 0>
void unmarshallMember(const QDBusArgument &arg, T &value) { arg >> value; } void unmarshallMember(const QDBusArgument &arg, T &value, std::false_type) { arg >> value; }
//! \endcond //! \endcond
} }
@@ -46,7 +53,7 @@ namespace BlackMisc
* *
* \tparam Derived Must implement public methods void marshallToDbus(QDBusArgument &arg) const and void unmarshallFromDbus(const QDBusArgument &arg). * \tparam Derived Must implement public methods void marshallToDbus(QDBusArgument &arg) const and void unmarshallFromDbus(const QDBusArgument &arg).
*/ */
template <class Derived> template <class Derived, class...>
class DBusOperators class DBusOperators
{ {
public: public:
@@ -68,38 +75,48 @@ namespace BlackMisc
return arg; return arg;
} }
}; };
template <class Derived>
class DBusOperators<Derived, LosslessTag> {};
/*! /*!
* CRTP class template from which a derived class can inherit common methods dealing with marshalling instances by metaclass. * CRTP class template from which a derived class can inherit common methods dealing with marshalling instances by metaclass.
* *
* \see BLACKMISC_DECLARE_USING_MIXIN_DBUS * \see BLACKMISC_DECLARE_USING_MIXIN_DBUS
*/ */
template <class Derived> template <class Derived, class... Tags>
class DBusByMetaClass : public DBusOperators<Derived> class DBusByMetaClass : public DBusOperators<Derived, Tags...>
{ {
public: public:
//! Marshall without begin/endStructure, for when composed within another object //! Marshall without begin/endStructure, for when composed within another object
void marshallToDbus(QDBusArgument &arg) const void marshallToDbus(QDBusArgument &arg, Tags...) const
{ {
baseMarshall(static_cast<const TBaseOfT<Derived> *>(derived()), arg); baseMarshall(static_cast<const TBaseOfT<Derived> *>(derived()), arg);
auto meta = introspect<Derived>().without(MetaFlags<DisabledForMarshalling>()); auto meta = introspect<Derived>().without(MetaFlags<DisabledForMarshalling>());
meta.forEachMember([ &, this ](auto member) { Private::marshallMember(arg, member.in(*this->derived())); }); meta.forEachMember([ &, this ](auto member)
{
using lossless = std::integral_constant<bool, member.has(MetaFlags<LosslessMarshalling>())>;
Private::marshallMember(arg, member.in(*this->derived()), lossless());
});
} }
//! Unmarshall without begin/endStructure, for when composed within another object //! Unmarshall without begin/endStructure, for when composed within another object
void unmarshallFromDbus(const QDBusArgument &arg) void unmarshallFromDbus(const QDBusArgument &arg, Tags...)
{ {
baseUnmarshall(static_cast<TBaseOfT<Derived> *>(derived()), arg); baseUnmarshall(static_cast<TBaseOfT<Derived> *>(derived()), arg);
auto meta = introspect<Derived>().without(MetaFlags<DisabledForMarshalling>()); auto meta = introspect<Derived>().without(MetaFlags<DisabledForMarshalling>());
meta.forEachMember([ &, this ](auto member) { Private::unmarshallMember(arg, member.in(*this->derived())); }); meta.forEachMember([ &, this ](auto member)
{
using lossless = std::integral_constant<bool, member.has(MetaFlags<LosslessMarshalling>())>;
Private::unmarshallMember(arg, member.in(*this->derived()), lossless());
});
} }
private: private:
const Derived *derived() const { return static_cast<const Derived *>(this); } const Derived *derived() const { return static_cast<const Derived *>(this); }
Derived *derived() { return static_cast<Derived *>(this); } Derived *derived() { return static_cast<Derived *>(this); }
template <typename T> static void baseMarshall(const T *base, QDBusArgument &arg) { base->marshallToDbus(arg); } template <typename T> static void baseMarshall(const T *base, QDBusArgument &arg) { base->marshallToDbus(arg, Tags()...); }
template <typename T> static void baseUnmarshall(T *base, const QDBusArgument &arg) { base->unmarshallFromDbus(arg); } template <typename T> static void baseUnmarshall(T *base, const QDBusArgument &arg) { base->unmarshallFromDbus(arg, Tags()...); }
static void baseMarshall(const void *, QDBusArgument &) {} static void baseMarshall(const void *, QDBusArgument &) {}
static void baseUnmarshall(void *, const QDBusArgument &) {} static void baseUnmarshall(void *, const QDBusArgument &) {}
static void baseMarshall(const CEmpty *, QDBusArgument &) {} static void baseMarshall(const CEmpty *, QDBusArgument &) {}
@@ -110,9 +127,9 @@ namespace BlackMisc
* When a derived class and a base class both inherit from Mixin::DBusByTuple, * When a derived class and a base class both inherit from Mixin::DBusByTuple,
* the derived class uses this macro to disambiguate the inherited members. * the derived class uses this macro to disambiguate the inherited members.
*/ */
# define BLACKMISC_DECLARE_USING_MIXIN_DBUS(DERIVED) \ # define BLACKMISC_DECLARE_USING_MIXIN_DBUS(DERIVED, ...) \
using ::BlackMisc::Mixin::DBusByMetaClass<DERIVED>::marshallToDbus; \ using ::BlackMisc::Mixin::DBusByMetaClass<DERIVED BLACK_TRAILING_VA_ARGS(__VA_ARGS__)>::marshallToDbus; \
using ::BlackMisc::Mixin::DBusByMetaClass<DERIVED>::unmarshallFromDbus; using ::BlackMisc::Mixin::DBusByMetaClass<DERIVED BLACK_TRAILING_VA_ARGS(__VA_ARGS__)>::unmarshallFromDbus;
} // Mixin } // Mixin
} // BlackMisc } // BlackMisc

View File

@@ -186,7 +186,8 @@ namespace BlackMisc
DisabledForDebugging = 1 << 2, //!< Element will be ignored when streaming to QDebug DisabledForDebugging = 1 << 2, //!< Element will be ignored when streaming to QDebug
DisabledForHashing = 1 << 3, //!< Element will be ignored by qHash() DisabledForHashing = 1 << 3, //!< Element will be ignored by qHash()
DisabledForJson = 1 << 4, //!< Element will be ignored during JSON serialization DisabledForJson = 1 << 4, //!< Element will be ignored during JSON serialization
CaseInsensitiveComparison = 1 << 5 //!< Element will be compared case insensitively (must be a QString) CaseInsensitiveComparison = 1 << 5, //!< Element will be compared case insensitively (must be a QString)
LosslessMarshalling = 1 << 6 //!< Element marshalling will preserve data at the expense of size
}; };
/*! /*!
@@ -205,6 +206,7 @@ namespace BlackMisc
constexpr static MetaFlags<MetaFlag::DisabledForHashing> DisabledForHashing {}; constexpr static MetaFlags<MetaFlag::DisabledForHashing> DisabledForHashing {};
constexpr static MetaFlags<MetaFlag::DisabledForJson> DisabledForJson {}; constexpr static MetaFlags<MetaFlag::DisabledForJson> DisabledForJson {};
constexpr static MetaFlags<MetaFlag::CaseInsensitiveComparison> CaseInsensitiveComparison {}; constexpr static MetaFlags<MetaFlag::CaseInsensitiveComparison> CaseInsensitiveComparison {};
constexpr static MetaFlags<MetaFlag::LosslessMarshalling> LosslessMarshalling {};
//! @} //! @}
//! Return a CMetaMemberList of type deduced from the types of the meta members. //! Return a CMetaMemberList of type deduced from the types of the meta members.

View File

@@ -183,8 +183,6 @@ namespace BlackMisc
{ {
constexpr double NaN = std::numeric_limits<double>::quiet_NaN(); constexpr double NaN = std::numeric_limits<double>::quiet_NaN();
argument << (this->isNull() ? NaN : this->value(UnitClass::defaultUnit())); argument << (this->isNull() ? NaN : this->value(UnitClass::defaultUnit()));
// argument << m_value;
// argument << m_unit;
} }
template <class MU, class PQ> template <class MU, class PQ>
@@ -196,8 +194,20 @@ namespace BlackMisc
{ {
this->setNull(); this->setNull();
} }
// argument >> m_value; }
// argument >> m_unit;
template <class MU, class PQ>
void CPhysicalQuantity<MU, PQ>::marshallToDbus(QDBusArgument &argument, LosslessTag) const
{
argument << m_value;
argument << m_unit;
}
template <class MU, class PQ>
void CPhysicalQuantity<MU, PQ>::unmarshallFromDbus(const QDBusArgument &argument, LosslessTag)
{
argument >> m_value;
argument >> m_unit;
} }
template <class MU, class PQ> template <class MU, class PQ>

View File

@@ -213,6 +213,12 @@ namespace BlackMisc
//! \copydoc BlackMisc::Mixin::DBusByMetaClass::unmarshallFromDbus //! \copydoc BlackMisc::Mixin::DBusByMetaClass::unmarshallFromDbus
void unmarshallFromDbus(const QDBusArgument &argument); void unmarshallFromDbus(const QDBusArgument &argument);
//! Marshal to DBus, preserving the measurement unit
void marshallToDbus(QDBusArgument &argument, LosslessTag) const;
//! Unmarshal from DBus, with preserved measurement unit
void unmarshallFromDbus(const QDBusArgument &argument, LosslessTag);
//! \copydoc BlackMisc::Mixin::HashByMetaClass::qHash //! \copydoc BlackMisc::Mixin::HashByMetaClass::qHash
uint getValueHash() const; uint getValueHash() const;

View File

@@ -327,6 +327,12 @@ namespace BlackMisc
return variant; return variant;
} }
BlackMisc::Aviation::CFlightPlan CTestService::pingFlightPlan(const BlackMisc::Aviation::CFlightPlan &flightPlan) const
{
if (m_verbose) out() << "Pid: " << CTestService::getPid() << " info: " << flightPlan << endl;
return flightPlan;
}
CAtcStationList CTestService::getAtcStationList(int n) const CAtcStationList CTestService::getAtcStationList(int n) const
{ {
if (m_verbose) out() << "Pid: " << CTestService::getPid() << " getAtcStationList" << endl; if (m_verbose) out() << "Pid: " << CTestService::getPid() << " getAtcStationList" << endl;

View File

@@ -21,6 +21,7 @@
#include "blackmisc/aviation/altitude.h" #include "blackmisc/aviation/altitude.h"
#include "blackmisc/aviation/atcstation.h" #include "blackmisc/aviation/atcstation.h"
#include "blackmisc/aviation/atcstationlist.h" #include "blackmisc/aviation/atcstationlist.h"
#include "blackmisc/aviation/flightplan.h"
#include "blackmisc/aviation/transponder.h" #include "blackmisc/aviation/transponder.h"
#include "blackmisc/geo/coordinategeodetic.h" #include "blackmisc/geo/coordinategeodetic.h"
#include "blackmisc/network/client.h" #include "blackmisc/network/client.h"
@@ -216,6 +217,9 @@ namespace BlackMisc
//! Ping ICAO data object //! Ping ICAO data object
BlackMisc::Aviation::CAircraftIcaoCode pingAircraftIcaoData(const BlackMisc::Aviation::CAircraftIcaoCode &icao) const; BlackMisc::Aviation::CAircraftIcaoCode pingAircraftIcaoData(const BlackMisc::Aviation::CAircraftIcaoCode &icao) const;
//! Ping flight plan
BlackMisc::Aviation::CFlightPlan pingFlightPlan(const BlackMisc::Aviation::CFlightPlan &flightPlan) const;
//! Ping CVariant //! Ping CVariant
BlackMisc::CVariant pingCVariant(const BlackMisc::CVariant &variant) const; BlackMisc::CVariant pingCVariant(const BlackMisc::CVariant &variant) const;

View File

@@ -10,6 +10,7 @@
#include "testservice.h" #include "testservice.h"
#include "testing.h" #include "testing.h"
#include "blackmisc/test/testdata.h" #include "blackmisc/test/testdata.h"
#include "blackmisc/aviation/flightplan.h"
#include <QTextStream> #include <QTextStream>
class QDBusConnection; class QDBusConnection;
@@ -141,6 +142,15 @@ namespace BlackMisc
ok = pingCompare(clients, clientsPing, out, verbose, errors); ok = pingCompare(clients, clientsPing, out, verbose, errors);
if (verbose) { out << "Pinged client list via interface" << errorInfo(ok) << endl; } if (verbose) { out << "Pinged client list via interface" << errorInfo(ok) << endl; }
CFlightPlan flightPlan;
flightPlan.setEnrouteTime(CTime(4, CTimeUnit::h()));
flightPlan.setFuelTime(CTime(5, CTimeUnit::h()));
flightPlan.setCruiseAltitude(CAltitude(10, CAltitude::FlightLevel, CLengthUnit::km()));
flightPlan.setCruiseTrueAirspeed(CSpeed(500, CSpeedUnit::km_h()));
const CFlightPlan flightPlanPing = testServiceInterface.pingFlightPlan(flightPlan);
ok = pingCompare(flightPlan, flightPlanPing, out, verbose, errors);
if (verbose) { out << "Pinged flight plan via interface" << errorInfo(ok) << endl; }
const CVariant cv = CVariant::fromValue(clients); const CVariant cv = CVariant::fromValue(clients);
const CVariant cvPing = testServiceInterface.pingCVariant(cv); const CVariant cvPing = testServiceInterface.pingCVariant(cv);
ok = pingCompare(cv.value<CClientList>(), cvPing.value<CClientList>(), out, verbose, errors); ok = pingCompare(cv.value<CClientList>(), cvPing.value<CClientList>(), out, verbose, errors);

View File

@@ -20,6 +20,7 @@
#include "blackmisc/aviation/atcstationlist.h" #include "blackmisc/aviation/atcstationlist.h"
#include "blackmisc/aviation/callsign.h" #include "blackmisc/aviation/callsign.h"
#include "blackmisc/aviation/comsystem.h" #include "blackmisc/aviation/comsystem.h"
#include "blackmisc/aviation/flightplan.h"
#include "blackmisc/aviation/track.h" #include "blackmisc/aviation/track.h"
#include "blackmisc/aviation/transponder.h" #include "blackmisc/aviation/transponder.h"
#include "blackmisc/geo/coordinategeodetic.h" #include "blackmisc/geo/coordinategeodetic.h"
@@ -264,6 +265,13 @@ namespace BlackMisc
return asyncCallWithArgumentList(QLatin1String("pingIndexVariantMap"), argumentList); return asyncCallWithArgumentList(QLatin1String("pingIndexVariantMap"), argumentList);
} }
QDBusPendingReply<BlackMisc::Aviation::CFlightPlan> pingFlightPlan(const Aviation::CFlightPlan &flightPlan)
{
QList<QVariant> argumentList;
argumentList << QVariant::fromValue(flightPlan);
return asyncCallWithArgumentList(QLatin1String("pingFlightPlan"), argumentList);
}
QDBusPendingReply<BlackMisc::Aviation::CAltitude> receiveAltitude(const BlackMisc::Aviation::CAltitude &altitude) QDBusPendingReply<BlackMisc::Aviation::CAltitude> receiveAltitude(const BlackMisc::Aviation::CAltitude &altitude)
{ {
QList<QVariant> argumentList; QList<QVariant> argumentList;
@@ -382,13 +390,31 @@ namespace BlackMisc
template<class ValueObject> template<class ValueObject>
static bool pingCompare(const ValueObject &in, const ValueObject &out, QTextStream &ts, bool verbose, int &errors) static bool pingCompare(const ValueObject &in, const ValueObject &out, QTextStream &ts, bool verbose, int &errors)
{ {
const bool equal = (in == out); const bool equal = (in == out && extraCompare(in, out));
if (!equal) { errors++; } if (!equal)
if (equal && !verbose) { return true; } {
ts << "I: " << in.toQString() << endl << "O: " << out.toQString() << endl; errors++;
if (verbose) { ts << "I: " << in.toQString() << endl << "O: " << out.toQString() << endl; }
}
return equal; return equal;
} }
//! Extra comparison step for some types
//! @{
template<class ValueObject>
static bool extraCompare(const ValueObject &, const ValueObject &) { return true; }
static bool extraCompare(const BlackMisc::Aviation::CFlightPlan &in, const BlackMisc::Aviation::CFlightPlan &out)
{
// flight plan: check units are preserved
if (in.getEnrouteTime().getUnit() != out.getEnrouteTime().getUnit()) { return false; }
if (in.getFuelTime().getUnit() != out.getFuelTime().getUnit()) { return false; }
if (in.getCruiseAltitude().getUnit() != out.getCruiseAltitude().getUnit()) { return false; }
if (in.getCruiseTrueAirspeed().getUnit() != out.getCruiseTrueAirspeed().getUnit()) { return false; }
return true;
}
//! @}
//! Error info string //! Error info string
static const QString &errorInfo(bool ok); static const QString &errorInfo(bool ok);
}; };