From 83dec5408bbfa1d1b010b851778c265ed19f63c9 Mon Sep 17 00:00:00 2001 From: Mat Sutcliffe Date: Mon, 4 Mar 2019 01:14:09 +0000 Subject: [PATCH] Ref T557 Metaclass flag to preserve measurement unit when marshalling PQ's in flight plans. --- src/blackmisc/aviation/altitude.h | 2 + src/blackmisc/aviation/flightplan.h | 8 ++-- src/blackmisc/dbus.h | 53 ++++++++++++++------- src/blackmisc/metaclass.h | 4 +- src/blackmisc/pq/physicalquantity.cpp | 18 +++++-- src/blackmisc/pq/physicalquantity.h | 6 +++ src/blackmisc/test/testservice.cpp | 6 +++ src/blackmisc/test/testservice.h | 4 ++ src/blackmisc/test/testserviceinterface.cpp | 10 ++++ src/blackmisc/test/testserviceinterface.h | 34 +++++++++++-- 10 files changed, 114 insertions(+), 31 deletions(-) diff --git a/src/blackmisc/aviation/altitude.h b/src/blackmisc/aviation/altitude.h index be8425074..64bd42231 100644 --- a/src/blackmisc/aviation/altitude.h +++ b/src/blackmisc/aviation/altitude.h @@ -45,6 +45,7 @@ namespace BlackMisc public Mixin::CompareByMetaClass, public Mixin::HashByMetaClass, public Mixin::DBusByMetaClass, + public Mixin::DBusByMetaClass, public Mixin::JsonByMetaClass, public Mixin::String, public Mixin::Icon, @@ -57,6 +58,7 @@ namespace BlackMisc BLACKMISC_DECLARE_USING_MIXIN_METATYPE(CAltitude) BLACKMISC_DECLARE_USING_MIXIN_STRING(CAltitude) BLACKMISC_DECLARE_USING_MIXIN_DBUS(CAltitude) + BLACKMISC_DECLARE_USING_MIXIN_DBUS(CAltitude, LosslessTag) BLACKMISC_DECLARE_USING_MIXIN_JSON(CAltitude) BLACKMISC_DECLARE_USING_MIXIN_ICON(CAltitude) BLACKMISC_DECLARE_USING_MIXIN_INDEX(CAltitude) diff --git a/src/blackmisc/aviation/flightplan.h b/src/blackmisc/aviation/flightplan.h index 737585c4f..e2a58659f 100644 --- a/src/blackmisc/aviation/flightplan.h +++ b/src/blackmisc/aviation/flightplan.h @@ -449,11 +449,11 @@ namespace BlackMisc BLACK_METAMEMBER(alternateAirportIcao), BLACK_METAMEMBER(takeoffTimePlanned), BLACK_METAMEMBER(takeoffTimeActual), - BLACK_METAMEMBER(enrouteTime), - BLACK_METAMEMBER(fuelTime), - BLACK_METAMEMBER(cruiseAltitude), + BLACK_METAMEMBER(enrouteTime, 0, LosslessMarshalling), + BLACK_METAMEMBER(fuelTime, 0, LosslessMarshalling), + BLACK_METAMEMBER(cruiseAltitude, 0, LosslessMarshalling), BLACK_METAMEMBER(cruiseAltitudeString), - BLACK_METAMEMBER(cruiseTrueAirspeed), + BLACK_METAMEMBER(cruiseTrueAirspeed, 0, LosslessMarshalling), BLACK_METAMEMBER(flightRules), BLACK_METAMEMBER(route), BLACK_METAMEMBER(remarks), diff --git a/src/blackmisc/dbus.h b/src/blackmisc/dbus.h index 8baca3cd1..94533f396 100644 --- a/src/blackmisc/dbus.h +++ b/src/blackmisc/dbus.h @@ -22,20 +22,27 @@ namespace BlackMisc { class CEmpty; + /*! + * Tag type signifying overloaded marshalling methods that preserve data at the expense of size. + */ + class LosslessTag {}; + namespace Private { //! \cond PRIVATE template ::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 ::value, int> = 0> + void marshallMember(QDBusArgument &arg, const T &value, std::true_type) { value.marshallToDbus(arg, LosslessTag()); } template ::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 ::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 ::value, int> = 0> + void unmarshallMember(const QDBusArgument &arg, T &value, std::true_type) { value.unmarshallFromDbus(arg, LosslessTag()); } template ::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 } @@ -46,7 +53,7 @@ namespace BlackMisc * * \tparam Derived Must implement public methods void marshallToDbus(QDBusArgument &arg) const and void unmarshallFromDbus(const QDBusArgument &arg). */ - template + template class DBusOperators { public: @@ -68,38 +75,48 @@ namespace BlackMisc return arg; } }; + template + class DBusOperators {}; /*! * CRTP class template from which a derived class can inherit common methods dealing with marshalling instances by metaclass. * * \see BLACKMISC_DECLARE_USING_MIXIN_DBUS */ - template - class DBusByMetaClass : public DBusOperators + template + class DBusByMetaClass : public DBusOperators { public: //! Marshall without begin/endStructure, for when composed within another object - void marshallToDbus(QDBusArgument &arg) const + void marshallToDbus(QDBusArgument &arg, Tags...) const { baseMarshall(static_cast *>(derived()), arg); auto meta = introspect().without(MetaFlags()); - meta.forEachMember([ &, this ](auto member) { Private::marshallMember(arg, member.in(*this->derived())); }); + meta.forEachMember([ &, this ](auto member) + { + using lossless = std::integral_constant())>; + Private::marshallMember(arg, member.in(*this->derived()), lossless()); + }); } //! Unmarshall without begin/endStructure, for when composed within another object - void unmarshallFromDbus(const QDBusArgument &arg) + void unmarshallFromDbus(const QDBusArgument &arg, Tags...) { baseUnmarshall(static_cast *>(derived()), arg); auto meta = introspect().without(MetaFlags()); - meta.forEachMember([ &, this ](auto member) { Private::unmarshallMember(arg, member.in(*this->derived())); }); + meta.forEachMember([ &, this ](auto member) + { + using lossless = std::integral_constant())>; + Private::unmarshallMember(arg, member.in(*this->derived()), lossless()); + }); } private: const Derived *derived() const { return static_cast(this); } Derived *derived() { return static_cast(this); } - template static void baseMarshall(const T *base, QDBusArgument &arg) { base->marshallToDbus(arg); } - template static void baseUnmarshall(T *base, const QDBusArgument &arg) { base->unmarshallFromDbus(arg); } + template static void baseMarshall(const T *base, QDBusArgument &arg) { base->marshallToDbus(arg, Tags()...); } + template static void baseUnmarshall(T *base, const QDBusArgument &arg) { base->unmarshallFromDbus(arg, Tags()...); } static void baseMarshall(const void *, QDBusArgument &) {} static void baseUnmarshall(void *, const 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, * the derived class uses this macro to disambiguate the inherited members. */ -# define BLACKMISC_DECLARE_USING_MIXIN_DBUS(DERIVED) \ - using ::BlackMisc::Mixin::DBusByMetaClass::marshallToDbus; \ - using ::BlackMisc::Mixin::DBusByMetaClass::unmarshallFromDbus; +# define BLACKMISC_DECLARE_USING_MIXIN_DBUS(DERIVED, ...) \ + using ::BlackMisc::Mixin::DBusByMetaClass::marshallToDbus; \ + using ::BlackMisc::Mixin::DBusByMetaClass::unmarshallFromDbus; } // Mixin } // BlackMisc diff --git a/src/blackmisc/metaclass.h b/src/blackmisc/metaclass.h index a3d5e6d6d..ad3e30241 100644 --- a/src/blackmisc/metaclass.h +++ b/src/blackmisc/metaclass.h @@ -186,7 +186,8 @@ namespace BlackMisc DisabledForDebugging = 1 << 2, //!< Element will be ignored when streaming to QDebug DisabledForHashing = 1 << 3, //!< Element will be ignored by qHash() 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 DisabledForHashing {}; constexpr static MetaFlags DisabledForJson {}; constexpr static MetaFlags CaseInsensitiveComparison {}; + constexpr static MetaFlags LosslessMarshalling {}; //! @} //! Return a CMetaMemberList of type deduced from the types of the meta members. diff --git a/src/blackmisc/pq/physicalquantity.cpp b/src/blackmisc/pq/physicalquantity.cpp index 3cc1a2164..4b08e8aa6 100644 --- a/src/blackmisc/pq/physicalquantity.cpp +++ b/src/blackmisc/pq/physicalquantity.cpp @@ -183,8 +183,6 @@ namespace BlackMisc { constexpr double NaN = std::numeric_limits::quiet_NaN(); argument << (this->isNull() ? NaN : this->value(UnitClass::defaultUnit())); - // argument << m_value; - // argument << m_unit; } template @@ -196,8 +194,20 @@ namespace BlackMisc { this->setNull(); } - // argument >> m_value; - // argument >> m_unit; + } + + template + void CPhysicalQuantity::marshallToDbus(QDBusArgument &argument, LosslessTag) const + { + argument << m_value; + argument << m_unit; + } + + template + void CPhysicalQuantity::unmarshallFromDbus(const QDBusArgument &argument, LosslessTag) + { + argument >> m_value; + argument >> m_unit; } template diff --git a/src/blackmisc/pq/physicalquantity.h b/src/blackmisc/pq/physicalquantity.h index 7fe99a811..3e709022d 100644 --- a/src/blackmisc/pq/physicalquantity.h +++ b/src/blackmisc/pq/physicalquantity.h @@ -213,6 +213,12 @@ namespace BlackMisc //! \copydoc BlackMisc::Mixin::DBusByMetaClass::unmarshallFromDbus 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 uint getValueHash() const; diff --git a/src/blackmisc/test/testservice.cpp b/src/blackmisc/test/testservice.cpp index 3ebbe9953..d2f4a0ec7 100644 --- a/src/blackmisc/test/testservice.cpp +++ b/src/blackmisc/test/testservice.cpp @@ -327,6 +327,12 @@ namespace BlackMisc 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 { if (m_verbose) out() << "Pid: " << CTestService::getPid() << " getAtcStationList" << endl; diff --git a/src/blackmisc/test/testservice.h b/src/blackmisc/test/testservice.h index 68b937b4d..0039e4b1d 100644 --- a/src/blackmisc/test/testservice.h +++ b/src/blackmisc/test/testservice.h @@ -21,6 +21,7 @@ #include "blackmisc/aviation/altitude.h" #include "blackmisc/aviation/atcstation.h" #include "blackmisc/aviation/atcstationlist.h" +#include "blackmisc/aviation/flightplan.h" #include "blackmisc/aviation/transponder.h" #include "blackmisc/geo/coordinategeodetic.h" #include "blackmisc/network/client.h" @@ -216,6 +217,9 @@ namespace BlackMisc //! Ping ICAO data object 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 BlackMisc::CVariant pingCVariant(const BlackMisc::CVariant &variant) const; diff --git a/src/blackmisc/test/testserviceinterface.cpp b/src/blackmisc/test/testserviceinterface.cpp index 36ca22582..359b6a299 100644 --- a/src/blackmisc/test/testserviceinterface.cpp +++ b/src/blackmisc/test/testserviceinterface.cpp @@ -10,6 +10,7 @@ #include "testservice.h" #include "testing.h" #include "blackmisc/test/testdata.h" +#include "blackmisc/aviation/flightplan.h" #include class QDBusConnection; @@ -141,6 +142,15 @@ namespace BlackMisc ok = pingCompare(clients, clientsPing, out, verbose, errors); 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 cvPing = testServiceInterface.pingCVariant(cv); ok = pingCompare(cv.value(), cvPing.value(), out, verbose, errors); diff --git a/src/blackmisc/test/testserviceinterface.h b/src/blackmisc/test/testserviceinterface.h index 4e1aadc3a..fad866267 100644 --- a/src/blackmisc/test/testserviceinterface.h +++ b/src/blackmisc/test/testserviceinterface.h @@ -20,6 +20,7 @@ #include "blackmisc/aviation/atcstationlist.h" #include "blackmisc/aviation/callsign.h" #include "blackmisc/aviation/comsystem.h" +#include "blackmisc/aviation/flightplan.h" #include "blackmisc/aviation/track.h" #include "blackmisc/aviation/transponder.h" #include "blackmisc/geo/coordinategeodetic.h" @@ -264,6 +265,13 @@ namespace BlackMisc return asyncCallWithArgumentList(QLatin1String("pingIndexVariantMap"), argumentList); } + QDBusPendingReply pingFlightPlan(const Aviation::CFlightPlan &flightPlan) + { + QList argumentList; + argumentList << QVariant::fromValue(flightPlan); + return asyncCallWithArgumentList(QLatin1String("pingFlightPlan"), argumentList); + } + QDBusPendingReply receiveAltitude(const BlackMisc::Aviation::CAltitude &altitude) { QList argumentList; @@ -382,13 +390,31 @@ namespace BlackMisc template static bool pingCompare(const ValueObject &in, const ValueObject &out, QTextStream &ts, bool verbose, int &errors) { - const bool equal = (in == out); - if (!equal) { errors++; } - if (equal && !verbose) { return true; } - ts << "I: " << in.toQString() << endl << "O: " << out.toQString() << endl; + const bool equal = (in == out && extraCompare(in, out)); + if (!equal) + { + errors++; + if (verbose) { ts << "I: " << in.toQString() << endl << "O: " << out.toQString() << endl; } + } return equal; } + //! Extra comparison step for some types + //! @{ + template + 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 static const QString &errorInfo(bool ok); };