mumble-voip_mumble/src/mumble/JSONSerialization.h

201 lines
6.5 KiB
C++

// Copyright 2022-2023 The Mumble Developers. All rights reserved.
// Use of this source code is governed by a BSD-style license
// that can be found in the LICENSE file at the root of the
// Mumble source tree or at <https://www.mumble.info/LICENSE>.
#ifndef MUMBLE_MUMBLE_JSONSERIALIZATION_H_
#define MUMBLE_MUMBLE_JSONSERIALIZATION_H_
#include "EnumStringConversions.h"
#include "Settings.h"
#include <sstream>
#include <type_traits>
#include <boost/version.hpp>
#if BOOST_VERSION >= 106700
// The is_detected type-trait was only included in Boost 1.67
# include <boost/type_traits/is_detected.hpp>
#endif
#include <nlohmann/json.hpp>
#include <QByteArray>
#include <QColor>
#include <QDataStream>
#include <QFlags>
#include <QFont>
#include <QHash>
#include <QList>
#include <QMap>
#include <QObject>
#include <QRect>
#include <QRectF>
#include <QSize>
#include <QSizeF>
#include <QString>
namespace details {
template< typename T > using has_enum_to_string_function = decltype(enumToString(std::declval< T >()));
template< typename T, bool isEnum, bool isQObject > struct StringConverter {
static std::string to_string(const T &value) {
std::stringstream stream;
stream << value;
return stream.str();
}
static T from_string(const std::string &str) {
std::stringstream stream(str);
T value;
stream >> value;
return value;
}
};
template< typename T > struct StringConverter< T, true, false > {
static std::string to_string(const T value) {
#if BOOST_VERSION >= 106700
// boost::is_detected is only available since Boost 1.67 and since we only use it to create a better error
// message, we can simply not make use of it, if earlier versions are used.
static_assert(boost::is_detected< has_enum_to_string_function, T >::value,
"Template specialization requires corresponding enumToString function");
#endif
return enumToString(value);
}
static T from_string(const std::string &str) { return ::stringToEnum< T >(str); }
};
template< typename T > struct StringConverter< T, false, true > {
static std::string to_string(const T &value) {
static_assert(std::is_base_of< QObject, T >::value, "Template specialization only applies to QObjects");
QByteArray data;
QDataStream stream(&data, QIODevice::WriteOnly);
stream.setVersion(QDataStream::Qt_5_0);
stream << value;
return data.toStdString();
}
static T from_string(const std::string &str) {
QByteArray data = QByteArray::fromStdString(str);
QDataStream stream(&data, QIODevice::WriteOnly);
stream.setVersion(QDataStream::Qt_5_0);
T value;
value << stream;
return value;
}
};
template< typename T > std::string to_string(const T &value) {
return StringConverter< T, std::is_enum< T >::value, std::is_base_of< QObject, T >::value >::to_string(value);
}
template<> inline std::string to_string< QString >(const QString &str) {
return str.toStdString();
}
template< typename T > T from_string(const std::string &str) {
return StringConverter< T, std::is_enum< T >::value, std::is_base_of< QObject, T >::value >::from_string(str);
}
template<> inline QString from_string< QString >(const std::string &str) {
return QString::fromStdString(str);
}
} // namespace details
void to_json(nlohmann::json &j, const Settings &settings);
void from_json(const nlohmann::json &j, Settings &settings);
void to_json(nlohmann::json &j, const OverlaySettings &settings);
void from_json(const nlohmann::json &j, OverlaySettings &settings);
void to_json(nlohmann::json &j, const QString &string);
void from_json(const nlohmann::json &j, QString &string);
void to_json(nlohmann::json &j, const QVariant &variant);
void from_json(const nlohmann::json &j, QVariant &variant);
void to_json(nlohmann::json &j, const QPoint &point);
void from_json(const nlohmann::json &j, QPoint &point);
void to_json(nlohmann::json &j, const Shortcut &shortcut);
void from_json(const nlohmann::json &j, Shortcut &shortcut);
void to_json(nlohmann::json &j, const ShortcutTarget &target);
void from_json(const nlohmann::json &j, ShortcutTarget &target);
void to_json(nlohmann::json &j, const PluginSetting &setting);
void from_json(const nlohmann::json &j, PluginSetting &setting);
void to_json(nlohmann::json &j, const QByteArray &byteArray);
void from_json(const nlohmann::json &j, QByteArray &byteArray);
void to_json(nlohmann::json &j, const QColor &color);
void from_json(const nlohmann::json &j, QColor &color);
void to_json(nlohmann::json &j, const QFont &font);
void from_json(const nlohmann::json &j, QFont &font);
void to_json(nlohmann::json &j, const QRect &rect);
void from_json(const nlohmann::json &j, QRect &rect);
void to_json(nlohmann::json &j, const QRectF &rect);
void from_json(const nlohmann::json &j, QRectF &rect);
void to_json(nlohmann::json &j, const QSize &size);
void from_json(const nlohmann::json &j, QSize &size);
void to_json(nlohmann::json &j, const QSizeF &size);
void from_json(const nlohmann::json &j, QSizeF &size);
template< typename T > void to_json(nlohmann::json &j, const QList< T > &list) {
j = nlohmann::json::array();
for (const T &current : list) {
j.push_back(current);
}
}
template< typename T > void from_json(const nlohmann::json &j, QList< T > &list) {
for (auto it = j.begin(); it != j.end(); ++it) {
list.push_back(it->get< T >());
}
}
template< typename Key, typename Value > void to_json(nlohmann::json &j, const QMap< Key, Value > &map) {
j = nlohmann::json::object();
for (auto it = map.constBegin(); it != map.constEnd(); ++it) {
j[details::to_string(it.key())] = it.value();
}
}
template< typename Key, typename Value > void from_json(const nlohmann::json &j, QMap< Key, Value > &map) {
for (auto it = j.cbegin(); it != j.cend(); ++it) {
map[details::from_string< Key >(it.key())] = it.value().get< Value >();
}
}
template< typename Key, typename Value > void to_json(nlohmann::json &j, const QHash< Key, Value > &map) {
j = nlohmann::json::object();
for (auto it = map.constBegin(); it != map.constEnd(); ++it) {
j[details::to_string(it.key())] = it.value();
}
}
template< typename Key, typename Value > void from_json(const nlohmann::json &j, QHash< Key, Value > &map) {
for (auto it = j.cbegin(); it != j.cend(); ++it) {
map[details::from_string< Key >(it.key())] = it.value().get< Value >();
}
}
template< typename T > void to_json(nlohmann::json &j, const QFlags< T > &flags) {
j = static_cast< typename QFlags< T >::Int >(flags);
}
template< typename T > void from_json(const nlohmann::json &j, QFlags< T > &flags) {
flags = QFlag(j.get< typename QFlags< T >::Int >());
}
#endif // MUMBLE_MUMBLE_JSONSERIALIZATION_H_