diff --git a/src/blackmisc/datastream.h b/src/blackmisc/datastream.h new file mode 100644 index 000000000..cad7510e0 --- /dev/null +++ b/src/blackmisc/datastream.h @@ -0,0 +1,133 @@ +/* Copyright (C) 2019 + * swift Project Community / Contributors + * + * This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level + * directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated, + * or distributed except according to the terms contained in the LICENSE file. + */ + +//! \file + +#ifndef BLACKMISC_DATASTREAM_H +#define BLACKMISC_DATASTREAM_H + +#include "blackmisc/typetraits.h" +#include + +namespace BlackMisc +{ + class CEmpty; + + namespace Mixin + { + /*! + * CRTP class template to generate non-member QDataStream streaming operators. + * + * \tparam Derived Must implement public methods marshalToDataStream(QDataStream &) and unmarshalFromDataStream(QDataStream &). + */ + template + class DataStreamOperators + { + public: + //! Marshal a value to a QDataStream. + friend QDataStream &operator <<(QDataStream &stream, const Derived &value) + { + value.marshalToDataStream(stream); + return stream; + } + + //! Unmarshal a value from a QDataStream. + friend QDataStream &operator >>(QDataStream &stream, Derived &value) + { + value.unmarshalFromDataStream(stream); + return stream; + } + }; + + /*! + * CRTP class template to generate QDataStream marshalling methods using CMetaClass. + * + * \see BLACKMISC_DECLARE_USING_MIXIN_DATASTREAM + */ + template + class DataStreamByMetaClass : public DataStreamOperators + { + public: + //! Marshal a value to a QDataStream. + void marshalToDataStream(QDataStream &stream) const + { + baseMarshal(static_cast *>(derived()), stream); + constexpr auto meta = introspect().without(MetaFlags()); + meta.forEachMember([ &, this ](auto member) { stream << member.in(*this->derived()); }); + } + + //! Unmarshal a value from a QDataStream. + void unmarshalFromDataStream(QDataStream &stream) + { + baseUnmarshal(static_cast *>(derived()), stream); + constexpr auto meta = introspect().without(MetaFlags()); + meta.forEachMember([ &, this ](auto member) { stream >> member.in(*this->derived()); }); + } + + private: + const Derived *derived() const { return static_cast(this); } + Derived *derived() { return static_cast(this); } + + template static void baseMarshal(const T *base, QDataStream &stream) { base->marshalToDataStream(stream); } + template static void baseUnmarshal(T *base, QDataStream &stream) { base->unmarshalFromDataStream(stream); } + static void baseMarshal(const void *, QDataStream &) {} + static void baseUnmarshal(void *, QDataStream &) {} + static void baseMarshal(const CEmpty *, QDataStream &) {} + static void baseUnmarshal(CEmpty *, QDataStream &) {} + }; + + /*! + * When a derived class and a base class both inherit from Mixin::DataStreamByMetaClass, + * the derived class uses this macro to disambiguate the inherited members. + */ +# define BLACKMISC_DECLARE_USING_MIXIN_DATASTREAM(DERIVED) \ + using ::BlackMisc::Mixin::DataStreamByMetaClass::marshalToDataStream; \ + using ::BlackMisc::Mixin::DataStreamByMetaClass::unmarshalFromDataStream; + } +} + +/*! + * Operator for marshalling enums with QDataStream. + */ +template ::value>> +QDataStream &operator <<(QDataStream &stream, E value) +{ + return stream << static_cast(value); +} + +/*! + * Operator for unmarshalling enums with QDataStream. + */ +template ::value>> +QDataStream &operator >>(QDataStream &stream, E &value) +{ + int temp; + stream >> temp; + value = static_cast(temp); + return stream; +} + +/*! + * Operator for marshalling pairs with QDataStream. + */ +template +QDataStream &operator <<(QDataStream &stream, const std::pair &pair) +{ + return stream << pair.first << pair.second; +} + +/*! + * Operator for unmarshalling pairs with QDataStream. + */ +template +QDataStream &operator >>(QDataStream &stream, std::pair &pair) +{ + return stream >> pair.first >> pair.second; +} + +#endif diff --git a/src/blackmisc/metaclass.h b/src/blackmisc/metaclass.h index fd8ce796a..94679d81d 100644 --- a/src/blackmisc/metaclass.h +++ b/src/blackmisc/metaclass.h @@ -182,7 +182,7 @@ namespace BlackMisc enum MetaFlag { DisabledForComparison = 1 << 0, //!< Element will be ignored by compare() and comparison operators - DisabledForMarshalling = 1 << 1, //!< Element will be ignored during DBus marshalling + DisabledForMarshalling = 1 << 1, //!< Element will be ignored during DBus and QDataStream marshalling 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