| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- #ifndef QTJSONSERIALIZER_TYPEEXTRACTORS_H
- #define QTJSONSERIALIZER_TYPEEXTRACTORS_H
- #include "typeconverter.h"
- #include <optional>
- #include <tuple>
- #include <variant>
- #include <QtCore/qbytearray.h>
- #include <QtCore/qpair.h>
- namespace QtJsonSerializer::TypeExtractors {
- template <template <typename> class TSmartPointer, typename TType>
- class SmartPointerExtractor final : public TypeExtractor
- {
- public:
- using Pointer = TType*;
- using Type = TSmartPointer<TType>;
- QByteArray baseType() const final {
- return QByteArrayLiteral("pointer");
- }
- QList<int> subtypes() const final {
- return {qMetaTypeId<Pointer>()};
- }
- QVariant extract(const QVariant &value, int) const final {
- return QVariant::fromValue<Pointer>(value.value<Type>().get());
- }
- void emplace(QVariant &target, const QVariant &value, int) const final {
- target = QVariant::fromValue(Type{value.value<Pointer>()});
- }
- };
- template <typename TType>
- class SmartPointerExtractor<QPointer, TType> final : public TypeExtractor
- {
- static_assert(std::is_base_of_v<QObject, TType>, "QPointer can only handle QObject types");
- public:
- using Pointer = TType*;
- using Type = QPointer<TType>;
- QByteArray baseType() const final {
- return QByteArrayLiteral("qpointer");
- }
- QList<int> subtypes() const final {
- return {qMetaTypeId<Pointer>()};
- }
- QVariant extract(const QVariant &value, int) const final {
- return QVariant::fromValue<Pointer>(value.value<Type>().data());
- }
- void emplace(QVariant &target, const QVariant &value, int) const final {
- target = QVariant::fromValue(Type{value.value<Pointer>()});
- }
- };
- template <template <typename, typename> class TPair, typename TFirst, typename TSecond>
- class PairExtractor final : public TypeExtractor
- {
- public:
- using Type = TPair<TFirst, TSecond>;
- QByteArray baseType() const final {
- return QByteArrayLiteral("pair");
- }
- QList<int> subtypes() const final {
- return {qMetaTypeId<TFirst>(), qMetaTypeId<TSecond>()};
- }
- QVariant extract(const QVariant &value, int index) const final {
- const auto vPair = value.value<Type>();
- switch (index) {
- case 0:
- return QVariant::fromValue(vPair.first);
- case 1:
- return QVariant::fromValue(vPair.second);
- default:
- return {};
- }
- }
- void emplace(QVariant &target, const QVariant &value, int index) const final {
- Q_ASSERT(target.userType() == qMetaTypeId<Type>());
- const auto vPair = reinterpret_cast<Type*>(target.data());
- switch (index) {
- case 0:
- vPair->first = value.value<TFirst>();
- break;
- case 1:
- vPair->second = value.value<TSecond>();
- break;
- default:
- break;
- }
- }
- };
- template <typename TValue>
- class OptionalExtractor final : public TypeExtractor
- {
- public:
- using Type = std::optional<TValue>;
- QByteArray baseType() const final {
- return QByteArrayLiteral("optional");
- }
- QList<int> subtypes() const final {
- return {qMetaTypeId<TValue>()};
- }
- QVariant extract(const QVariant &value, int) const final {
- if (const auto opt = value.value<std::optional<TValue>>(); opt)
- return QVariant::fromValue(*opt);
- else
- return QVariant::fromValue(nullptr);
- }
- void emplace(QVariant &target, const QVariant &value, int) const final {
- if (value.isNull())
- target = QVariant::fromValue<std::optional<TValue>>(std::nullopt);
- else
- target = QVariant::fromValue<std::optional<TValue>>(value.value<TValue>());
- }
- };
- template <typename... TValues>
- class TupleExtractor final : public TypeExtractor
- {
- public:
- using Type = std::tuple<TValues...>;
- private:
- template <size_t Index>
- inline QVariant getIf(const Type &, size_t) const {
- return {};
- }
- template <size_t Index, typename TValue, typename... TRest>
- inline QVariant getIf(const Type &tpl, size_t index) const {
- if (Index == index)
- return QVariant::fromValue(std::get<Index>(tpl));
- else
- return getIf<Index + 1, TRest...>(tpl, index);
- }
- template <size_t Index>
- inline void setIf(Type *, size_t, const QVariant &) const {}
- template <size_t Index, typename TValue, typename... TRest>
- inline void setIf(Type *tpl, size_t index, const QVariant &value) const {
- if (Index == index)
- std::get<Index>(*tpl) = value.value<TValue>();
- else
- setIf<Index + 1, TRest...>(tpl, index, value);
- }
- public:
- QByteArray baseType() const final {
- return QByteArrayLiteral("tuple");
- }
- QList<int> subtypes() const final {
- return {qMetaTypeId<TValues>()...};
- }
- QVariant extract(const QVariant &value, int index) const final {
- return getIf<0, TValues...>(value.value<Type>(), static_cast<size_t>(index));
- }
- void emplace(QVariant &target, const QVariant &value, int index) const final {
- Q_ASSERT(target.userType() == qMetaTypeId<Type>());
- setIf<0, TValues...>(reinterpret_cast<Type*>(target.data()), static_cast<size_t>(index), value);
- }
- };
- template <typename... TValues>
- class VariantExtractor final : public TypeExtractor
- {
- public:
- using Type = std::variant<TValues...>;
- private:
- template <typename _>
- inline Type constructIfType(const QVariant &) const { return {}; }
- template <typename _, typename TValue, typename... TArgs>
- inline Type constructIfType(const QVariant &var) const {
- if (var.userType() == qMetaTypeId<TValue>())
- return var.value<TValue>();
- else
- return constructIfType<_, TArgs...>(var);
- }
- public:
- QByteArray baseType() const final {
- return QByteArrayLiteral("variant");
- }
- QList<int> subtypes() const final {
- return {qMetaTypeId<TValues>()...};
- }
- QVariant extract(const QVariant &value, int) const final {
- return std::visit([](const auto &x) {
- return QVariant::fromValue(x);
- }, value.value<Type>());
- }
- void emplace(QVariant &target, const QVariant &value, int) const final {
- target = QVariant::fromValue(constructIfType<void, TValues...>(value));
- }
- };
- }
- #endif // QTJSONSERIALIZER_TYPEEXTRACTORS_H
|