migrate(Lts/Common): apply clang-tidy modernization fixes\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
1 parent
6822817a63
commit
acee7b8766
8 files changed
+688
-1040
No files matched your search
Executable → Regular
+11
-16
@@ -4,37 +4,32 @@
|
|||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
namespace LtsProjectionWorkstation
|
namespace LtsProjectionWorkstation::JsonKeys {
|
||||||
{
|
|
||||||
namespace JsonKeys
|
|
||||||
{
|
|
||||||
|
|
||||||
inline QString ERROR_MESSAGE() { return QStringLiteral("errorMessage"); }
|
inline QString ERROR_MESSAGE() { return QStringLiteral("errorMessage"); }
|
||||||
|
|
||||||
|
|
||||||
inline QString LOGIN_REQUEST() { return QStringLiteral("loginRequest"); }
|
inline QString LOGIN_REQUEST() { return QStringLiteral("loginRequest"); }
|
||||||
inline QString LOGOUT_REQUEST() { return QStringLiteral("logoutRequest"); }
|
inline QString LOGOUT_REQUEST() { return QStringLiteral("logoutRequest"); }
|
||||||
inline QString DISCONNECT_REQUEST() { return QStringLiteral("disconnectRequest"); }
|
inline QString DISCONNECT_REQUEST() {
|
||||||
|
return QStringLiteral("disconnectRequest");
|
||||||
|
}
|
||||||
|
|
||||||
inline QString LOGIN_REPLY() { return QStringLiteral("loginReply"); }
|
inline QString LOGIN_REPLY() { return QStringLiteral("loginReply"); }
|
||||||
inline QString LOGOUT_REPLY() { return QStringLiteral("logoutReply"); }
|
inline QString LOGOUT_REPLY() { return QStringLiteral("logoutReply"); }
|
||||||
inline QString DEDICAED_DISCONNECT() { return QStringLiteral("dedicatedDisconnect"); }
|
inline QString DEDICAED_DISCONNECT() {
|
||||||
|
return QStringLiteral("dedicatedDisconnect");
|
||||||
|
}
|
||||||
|
|
||||||
inline QString USER_ID() { return QStringLiteral("userId"); }
|
inline QString USER_ID() { return QStringLiteral("userId"); }
|
||||||
inline QString USER_PRIORITY() { return QStringLiteral("userPriority"); }
|
inline QString USER_PRIORITY() { return QStringLiteral("userPriority"); }
|
||||||
inline QString EXERCISE_ID() { return QStringLiteral("exerciseId"); }
|
inline QString EXERCISE_ID() { return QStringLiteral("exerciseId"); }
|
||||||
inline QString NAME() { return QStringLiteral("name"); }
|
inline QString NAME() { return QStringLiteral("name"); }
|
||||||
inline QString PORT() { return QStringLiteral("port"); }
|
inline QString PORT() { return QStringLiteral("port"); }
|
||||||
inline QString WIDTH() { return QStringLiteral("width"); }
|
inline QString WIDTH() { return QStringLiteral("width"); }
|
||||||
inline QString HEIGHT() { return QStringLiteral("height"); }
|
inline QString HEIGHT() { return QStringLiteral("height"); }
|
||||||
inline QString REASON() { return QStringLiteral("reason"); }
|
inline QString REASON() { return QStringLiteral("reason"); }
|
||||||
inline QString SUCCESS() { return QStringLiteral("success"); }
|
inline QString SUCCESS() { return QStringLiteral("success"); }
|
||||||
inline QString SCREENS() { return QStringLiteral("screens"); }
|
inline QString SCREENS() { return QStringLiteral("screens"); }
|
||||||
inline QString SETTINGS_DATA() { return QStringLiteral("settingsData"); }
|
inline QString SETTINGS_DATA() { return QStringLiteral("settingsData"); }
|
||||||
|
|
||||||
}
|
} // namespace LtsProjectionWorkstation::JsonKeys
|
||||||
|
|
||||||
}
|
|
||||||
Executable → Regular
+37
-64
@@ -1,102 +1,76 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <QMetaObject>
|
#include <QMetaObject>
|
||||||
|
#include <QObject>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace LtsUtils {
|
||||||
|
|
||||||
namespace LtsUtils
|
class IConnection {
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class IConnection
|
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
virtual ~IConnection() = default;
|
virtual ~IConnection() = default;
|
||||||
virtual void connect(Qt::ConnectionType = Qt::AutoConnection) = 0;
|
virtual void connect(Qt::ConnectionType = Qt::AutoConnection) = 0;
|
||||||
virtual void disconnect() = 0;
|
virtual void disconnect() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class DummyConnection : public IConnection {
|
||||||
|
|
||||||
|
|
||||||
class DummyConnection : public IConnection
|
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
void connect(Qt::ConnectionType = Qt::AutoConnection) override {}
|
void connect(Qt::ConnectionType = Qt::AutoConnection) override {}
|
||||||
void disconnect() override {}
|
void disconnect() override {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
namespace detail
|
template <class T> struct ExtractClass;
|
||||||
{
|
|
||||||
|
|
||||||
|
template <class T, class Member> struct ExtractClass<Member T::*> {
|
||||||
|
|
||||||
template<class T>
|
|
||||||
struct ExtractClass;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class T, class Member>
|
|
||||||
struct ExtractClass<Member T::*>
|
|
||||||
{
|
|
||||||
using type = T;
|
using type = T;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace detail
|
||||||
|
|
||||||
|
template <class Signal, class Slot> class Connection : public IConnection {
|
||||||
|
static_assert(std::is_member_function_pointer_v<Signal>,
|
||||||
|
"Must be a pointer to method");
|
||||||
template<class Signal, class Slot>
|
static_assert(std::is_member_function_pointer_v<Slot>,
|
||||||
class Connection : public IConnection
|
"Must be a pointer to method");
|
||||||
{
|
|
||||||
static_assert(std::is_member_function_pointer<Signal>::value, "Must be a pointer to method");
|
|
||||||
static_assert(std::is_member_function_pointer<Slot>::value, "Must be a pointer to method");
|
|
||||||
|
|
||||||
using Emitter = typename detail::ExtractClass<Signal>::type;
|
using Emitter = typename detail::ExtractClass<Signal>::type;
|
||||||
using Target = typename detail::ExtractClass<Slot>::type;
|
using Target = typename detail::ExtractClass<Slot>::type;
|
||||||
|
|
||||||
static_assert(std::is_base_of<QObject, Emitter>::value, "Must be derived from QObject");
|
static_assert(std::is_base_of_v<QObject, Emitter>,
|
||||||
static_assert(std::is_base_of<QObject, Target>::value, "Must be derived from QObject");
|
"Must be derived from QObject");
|
||||||
|
static_assert(std::is_base_of_v<QObject, Target>,
|
||||||
|
"Must be derived from QObject");
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Connection(Emitter *emitter, Signal signal, Target *target, Slot slot):
|
Connection(Emitter *emitter, Signal signal, Target *target, Slot slot)
|
||||||
m_emitter(emitter),
|
: m_emitter(emitter), m_signal(signal), m_target(target), m_slot(slot) {
|
||||||
m_signal(signal),
|
|
||||||
m_target(target),
|
|
||||||
m_slot(slot)
|
|
||||||
{
|
|
||||||
Q_ASSERT(emitter);
|
Q_ASSERT(emitter);
|
||||||
Q_ASSERT(signal);
|
Q_ASSERT(signal);
|
||||||
Q_ASSERT(target);
|
Q_ASSERT(target);
|
||||||
Q_ASSERT(slot);
|
Q_ASSERT(slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void connect(Qt::ConnectionType connectionType = Qt::AutoConnection) override
|
void
|
||||||
{
|
connect(Qt::ConnectionType connectionType = Qt::AutoConnection) override {
|
||||||
Q_ASSERT(!m_connected);
|
Q_ASSERT(!m_connected);
|
||||||
|
|
||||||
m_connected = true;
|
m_connected = true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (!m_emitter || !m_target)
|
if (!m_emitter || !m_target)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_conn = QObject::connect(m_emitter.data(), m_signal, m_target.data(), m_slot, connectionType);
|
m_conn = QObject::connect(m_emitter.data(), m_signal, m_target.data(),
|
||||||
|
m_slot, connectionType);
|
||||||
Q_ASSERT(m_conn);
|
Q_ASSERT(m_conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
void disconnect() override
|
void disconnect() override {
|
||||||
{
|
|
||||||
Q_ASSERT(m_connected);
|
Q_ASSERT(m_connected);
|
||||||
|
|
||||||
if (m_conn)
|
if (m_conn)
|
||||||
@@ -106,21 +80,20 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_connected{false};
|
bool m_connected{false};
|
||||||
QPointer<Emitter> m_emitter;
|
QPointer<Emitter> m_emitter;
|
||||||
Signal m_signal;
|
Signal m_signal;
|
||||||
QPointer<Target> m_target;
|
QPointer<Target> m_target;
|
||||||
Slot m_slot;
|
Slot m_slot;
|
||||||
QMetaObject::Connection m_conn;
|
QMetaObject::Connection m_conn;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class Signal, class Slot>
|
||||||
|
Connection<Signal, Slot> *
|
||||||
template<class Signal, class Slot>
|
createConnection(typename detail::ExtractClass<Signal>::type *emitter,
|
||||||
Connection<Signal, Slot>* createConnection(typename detail::ExtractClass<Signal>::type *emitter, Signal signal,
|
Signal signal,
|
||||||
typename detail::ExtractClass<Slot>::type *target, Slot slot)
|
typename detail::ExtractClass<Slot>::type *target, Slot slot) {
|
||||||
{
|
|
||||||
return new Connection<Signal, Slot>(emitter, signal, target, slot);
|
return new Connection<Signal, Slot>(emitter, signal, target, slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace LtsUtils
|
||||||
Executable → Regular
+10
-18
@@ -1,43 +1,35 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
namespace LtsUtils
|
namespace LtsUtils {
|
||||||
{
|
|
||||||
|
|
||||||
template <typename T, typename S>
|
template <typename T, typename S> inline void convert(const S &in, T &out) {
|
||||||
inline void convert(const S &in, T &out)
|
static_assert(!std::is_same_v<S, T>,
|
||||||
{
|
"Try to convert a type to the same type - is useless");
|
||||||
static_assert(!std::is_same<S, T>::value, "Try to convert a type to the same type - is useless");
|
|
||||||
out.reserve(static_cast<int>(in.size()));
|
out.reserve(static_cast<int>(in.size()));
|
||||||
std::copy(in.begin(), in.end(), std::back_inserter(out));
|
std::copy(in.begin(), in.end(), std::back_inserter(out));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename S>
|
template <typename T, typename S> inline T convert(const S &in) {
|
||||||
inline T convert(const S &in)
|
static_assert(!std::is_same_v<S, T>,
|
||||||
{
|
"Try to convert a type to the same type - is useless");
|
||||||
static_assert(!std::is_same<S, T>::value, "Try to convert a type to the same type - is useless");
|
|
||||||
T out;
|
T out;
|
||||||
convert(in, out);
|
convert(in, out);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T> inline QByteArray toQByteArray(const T &in) {
|
||||||
template <typename T>
|
|
||||||
inline QByteArray toQByteArray(const T &in)
|
|
||||||
{
|
|
||||||
return convert<QByteArray>(in);
|
return convert<QByteArray>(in);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename V = typename T::value_type>
|
template <typename T, typename V = typename T::value_type>
|
||||||
bool isInVector(const T &vec, const V &valueToSearch)
|
bool isInVector(const T &vec, const V &valueToSearch) {
|
||||||
{
|
|
||||||
const auto end = vec.end();
|
const auto end = vec.end();
|
||||||
return std::find(vec.begin(), end, valueToSearch) != end;
|
return std::find(vec.begin(), end, valueToSearch) != end;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace LtsUtils
|
||||||
Executable → Regular
+196
-373
@@ -1,6 +1,5 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
@@ -8,178 +7,149 @@
|
|||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
#include <QJsonParseError>
|
#include <QJsonParseError>
|
||||||
#include <QJsonValue>
|
#include <QJsonValue>
|
||||||
#include <QVector>
|
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <string>
|
#include <QVector>
|
||||||
#include <vector>
|
|
||||||
#include <map>
|
|
||||||
#include <exception>
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <exception>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace LtsUtils
|
namespace LtsUtils {
|
||||||
{
|
|
||||||
|
|
||||||
class JsonParseError : public std::runtime_error
|
class JsonParseError : public std::runtime_error {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
JsonParseError(const QJsonParseError &err)
|
JsonParseError(const QJsonParseError &err)
|
||||||
: std::runtime_error("json parse error: " + err.errorString().toStdString() + " - at offset " + std::to_string(err.offset)){}
|
: std::runtime_error(
|
||||||
|
"json parse error: " + err.errorString().toStdString() +
|
||||||
|
" - at offset " + std::to_string(err.offset)) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class JsonError : public std::runtime_error
|
class JsonError : public std::runtime_error {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
using std::runtime_error::runtime_error;
|
using std::runtime_error::runtime_error;
|
||||||
};
|
};
|
||||||
|
|
||||||
class JsonKeyError : public JsonError
|
class JsonKeyError : public JsonError {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
using JsonError::JsonError;
|
using JsonError::JsonError;
|
||||||
};
|
};
|
||||||
|
|
||||||
class JsonRangeError : public JsonError
|
class JsonRangeError : public JsonError {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
using JsonError::JsonError;
|
using JsonError::JsonError;
|
||||||
};
|
};
|
||||||
|
|
||||||
class JsonTypeError : public JsonError
|
class JsonTypeError : public JsonError {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
using JsonError::JsonError;
|
using JsonError::JsonError;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class JsonObject {
|
||||||
|
|
||||||
|
|
||||||
class JsonObject
|
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|
||||||
class Key;
|
class Key;
|
||||||
|
|
||||||
JsonObject() = default;
|
JsonObject() = default;
|
||||||
explicit JsonObject(const QJsonObject &json)
|
explicit JsonObject(const QJsonObject &json)
|
||||||
: m_json(json)
|
: m_json(json), m_jsonIsSet(true) {}
|
||||||
, m_jsonIsSet(true)
|
|
||||||
{}
|
|
||||||
|
|
||||||
explicit JsonObject(QJsonObject &&json)
|
explicit JsonObject(QJsonObject &&json)
|
||||||
: m_json(std::move(json))
|
: m_json(std::move(json)), m_jsonIsSet(true) {}
|
||||||
, m_jsonIsSet(true)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static inline JsonObject fromJson(const char *json, int len = -1);
|
static inline JsonObject fromJson(const char *json, int len = -1);
|
||||||
static inline JsonObject fromJson(const QByteArray &json) { return fromJson(json.data(), json.size()); }
|
static inline JsonObject fromJson(const QByteArray &json) {
|
||||||
static inline JsonObject fromJson(const std::string &json) { return fromJson(json.c_str(), json.size()); }
|
return fromJson(json.data(), json.size());
|
||||||
|
}
|
||||||
|
static inline JsonObject fromJson(const std::string &json) {
|
||||||
|
return fromJson(json.c_str(), json.size());
|
||||||
|
}
|
||||||
|
|
||||||
static inline JsonObject fromJsonSafe(const char *json, int len = -1) noexcept(false);
|
static inline JsonObject fromJsonSafe(const char *json,
|
||||||
static inline JsonObject fromJsonSafe(const QByteArray &json) noexcept(false) { return fromJsonSafe(json.data(), json.size()); }
|
int len = -1) noexcept(false);
|
||||||
static inline JsonObject fromJsonSafe(const std::string &json) noexcept(false) { return fromJsonSafe(json.c_str(), json.size()); }
|
static inline JsonObject
|
||||||
|
fromJsonSafe(const QByteArray &json) noexcept(false) {
|
||||||
|
return fromJsonSafe(json.data(), json.size());
|
||||||
|
}
|
||||||
|
static inline JsonObject
|
||||||
|
fromJsonSafe(const std::string &json) noexcept(false) {
|
||||||
|
return fromJsonSafe(json.c_str(), json.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T> [[nodiscard]] bool contains(const Key &key) const;
|
||||||
|
|
||||||
|
[[nodiscard]] bool isNull(const Key &key) const {
|
||||||
|
return contains<void>(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] bool isEmpty() const { return m_json.isEmpty(); }
|
||||||
|
[[nodiscard]] bool isValid() const { return m_jsonIsSet; }
|
||||||
|
|
||||||
template<class T>
|
template <class T> T value(const Key &key) const noexcept(false);
|
||||||
bool contains(const Key &key) const;
|
|
||||||
|
|
||||||
bool isNull(const Key &key) const { return contains<void>(key); }
|
template <class T>
|
||||||
|
|
||||||
bool isEmpty() const { return m_json.isEmpty(); }
|
|
||||||
bool isValid() const { return m_jsonIsSet; }
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
T value(const Key &key) const noexcept(false);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
T valueOr(const Key &key, const T &defaultValue) const noexcept(false);
|
T valueOr(const Key &key, const T &defaultValue) const noexcept(false);
|
||||||
|
|
||||||
|
template <class T> [[nodiscard]] bool isMap() const;
|
||||||
|
|
||||||
|
template <class T> QMap<QString, T> toMap() const noexcept(false);
|
||||||
|
|
||||||
|
template <class T> std::map<std::string, T> toStdMap() const;
|
||||||
|
|
||||||
template<class T>
|
bool operator==(const JsonObject &other) const {
|
||||||
bool isMap() const;
|
return m_json == other.m_json;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
QMap<QString, T> toMap() const noexcept(false);
|
|
||||||
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
std::map<std::string, T> toStdMap() const;
|
|
||||||
|
|
||||||
bool operator==(const JsonObject &other) const { return m_json == other.m_json; }
|
|
||||||
bool operator!=(const JsonObject &other) const { return !(*this == other); }
|
bool operator!=(const JsonObject &other) const { return !(*this == other); }
|
||||||
|
|
||||||
class Key
|
class Key {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
Key(const QString &s)
|
Key(QString s) : m_s(std::move(s)) {}
|
||||||
: m_s(s)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Key(const std::string &s)
|
Key(const std::string &s) : m_s(QString::fromStdString(s)) {}
|
||||||
: m_s(QString::fromStdString(s))
|
|
||||||
{}
|
|
||||||
|
|
||||||
Key(const char *s)
|
Key(const char *s) : m_s(QString::fromUtf8(s)) {}
|
||||||
: m_s(QString::fromUtf8(s))
|
|
||||||
{}
|
|
||||||
|
|
||||||
operator const QString &() const { return m_s; }
|
operator const QString &() const { return m_s; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const QString m_s;
|
const QString m_s;
|
||||||
};
|
};
|
||||||
|
|
||||||
operator const QJsonObject &() const { return m_json; }
|
operator const QJsonObject &() const { return m_json; }
|
||||||
const QJsonObject &object() const { return m_json; }
|
[[nodiscard]] const QJsonObject &object() const { return m_json; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool containsAny(const QString &key) const { return m_json.contains(key); }
|
[[nodiscard]] bool containsAny(const QString &key) const {
|
||||||
|
return m_json.contains(key);
|
||||||
|
}
|
||||||
|
|
||||||
QJsonObject m_json;
|
QJsonObject m_json;
|
||||||
bool m_jsonIsSet = false;
|
bool m_jsonIsSet = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
JsonObject JsonObject::fromJson(const char *json, int len)
|
JsonObject JsonObject::fromJson(const char *json, int len) {
|
||||||
{
|
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
len = strlen(json);
|
len = strlen(json);
|
||||||
QJsonParseError error;
|
QJsonParseError error;
|
||||||
const auto doc = QJsonDocument::fromJson(QByteArray::fromRawData(json, len), &error);
|
const auto doc =
|
||||||
|
QJsonDocument::fromJson(QByteArray::fromRawData(json, len), &error);
|
||||||
if (error.error != QJsonParseError::NoError)
|
if (error.error != QJsonParseError::NoError)
|
||||||
return JsonObject();
|
return {};
|
||||||
|
|
||||||
if (!doc.isObject())
|
if (!doc.isObject())
|
||||||
return JsonObject();
|
return {};
|
||||||
|
|
||||||
return JsonObject(doc.object());
|
return JsonObject(doc.object());
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject JsonObject::fromJsonSafe(const char *json, int len) noexcept(false)
|
JsonObject JsonObject::fromJsonSafe(const char *json, int len) noexcept(false) {
|
||||||
{
|
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
len = strlen(json);
|
len = strlen(json);
|
||||||
QJsonParseError error;
|
QJsonParseError error;
|
||||||
const auto doc = QJsonDocument::fromJson(QByteArray::fromRawData(json, len), &error);
|
const auto doc =
|
||||||
|
QJsonDocument::fromJson(QByteArray::fromRawData(json, len), &error);
|
||||||
if (error.error != QJsonParseError::NoError)
|
if (error.error != QJsonParseError::NoError)
|
||||||
throw JsonParseError(error);
|
throw JsonParseError(error);
|
||||||
|
|
||||||
@@ -189,106 +159,85 @@ JsonObject JsonObject::fromJsonSafe(const char *json, int len) noexcept(false)
|
|||||||
return JsonObject(doc.object());
|
return JsonObject(doc.object());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class JsonArray {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class JsonArray
|
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
JsonArray() = default;
|
JsonArray() = default;
|
||||||
explicit JsonArray(const QJsonArray &json)
|
explicit JsonArray(const QJsonArray &json)
|
||||||
: m_json(json)
|
: m_json(json), m_jsonIsSet(true) {}
|
||||||
, m_jsonIsSet(true)
|
|
||||||
{}
|
|
||||||
|
|
||||||
explicit JsonArray(QJsonArray &&json)
|
explicit JsonArray(QJsonArray &&json)
|
||||||
: m_json(std::move(json))
|
: m_json(std::move(json)), m_jsonIsSet(true) {}
|
||||||
, m_jsonIsSet(true)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static inline JsonArray fromJson(const char *json, int len = -1);
|
static inline JsonArray fromJson(const char *json, int len = -1);
|
||||||
static inline JsonArray fromJson(const QByteArray &json) { return fromJson(json.data(), json.size()); }
|
static inline JsonArray fromJson(const QByteArray &json) {
|
||||||
static inline JsonArray fromJson(const std::string &json) { return fromJson(json.c_str(), json.size()); }
|
return fromJson(json.data(), json.size());
|
||||||
|
}
|
||||||
|
static inline JsonArray fromJson(const std::string &json) {
|
||||||
|
return fromJson(json.c_str(), json.size());
|
||||||
|
}
|
||||||
|
|
||||||
static inline JsonArray fromJsonSafe(const char *json, int len = -1) noexcept(false);
|
static inline JsonArray fromJsonSafe(const char *json,
|
||||||
static inline JsonArray fromJsonSafe(const QByteArray &json) noexcept(false) { return fromJson(json.data(), json.size()); }
|
int len = -1) noexcept(false);
|
||||||
static inline JsonArray fromJsonSafe(const std::string &json) noexcept(false) { return fromJson(json.c_str(), json.size()); }
|
static inline JsonArray fromJsonSafe(const QByteArray &json) noexcept(false) {
|
||||||
|
return fromJson(json.data(), json.size());
|
||||||
|
}
|
||||||
|
static inline JsonArray
|
||||||
|
fromJsonSafe(const std::string &json) noexcept(false) {
|
||||||
|
return fromJson(json.c_str(), json.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] int size() const { return m_json.size(); }
|
||||||
|
[[nodiscard]] bool isEmpty() const { return m_json.isEmpty(); }
|
||||||
|
[[nodiscard]] bool isValid() const { return m_jsonIsSet; }
|
||||||
|
|
||||||
int size() const { return m_json.size(); }
|
template <class T>
|
||||||
bool isEmpty() const { return m_json.isEmpty(); }
|
[[nodiscard]] bool contains(int index) const noexcept(false);
|
||||||
bool isValid() const { return m_jsonIsSet; }
|
|
||||||
|
|
||||||
|
[[nodiscard]] bool isNull(int index) const noexcept(false) {
|
||||||
|
return contains<void>(index);
|
||||||
|
}
|
||||||
|
|
||||||
template<class T>
|
template <class T> T at(int index) const noexcept(false);
|
||||||
bool contains(int index) const noexcept(false);
|
|
||||||
|
|
||||||
|
template <class T> [[nodiscard]] bool isVector() const;
|
||||||
|
|
||||||
bool isNull(int index) const noexcept(false) { return contains<void>(index); }
|
template <class T> QVector<T> toVector() const noexcept(false);
|
||||||
|
|
||||||
|
template <class T> std::vector<T> toStdVector() const;
|
||||||
|
|
||||||
template<class T>
|
bool operator==(const JsonArray &other) const {
|
||||||
T at(int index) const noexcept(false);
|
return m_json == other.m_json;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
bool isVector() const;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
QVector<T> toVector() const noexcept(false);
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
std::vector<T> toStdVector() const;
|
|
||||||
|
|
||||||
bool operator==(const JsonArray &other) const { return m_json == other.m_json; }
|
|
||||||
bool operator!=(const JsonArray &other) const { return !(*this == other); }
|
bool operator!=(const JsonArray &other) const { return !(*this == other); }
|
||||||
|
|
||||||
const QJsonArray &operator()() const { return m_json; }
|
const QJsonArray &operator()() const { return m_json; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QJsonArray m_json;
|
QJsonArray m_json;
|
||||||
bool m_jsonIsSet = false;
|
bool m_jsonIsSet = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
JsonArray JsonArray::fromJson(const char *json, int len)
|
JsonArray JsonArray::fromJson(const char *json, int len) {
|
||||||
{
|
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
len = strlen(json);
|
len = strlen(json);
|
||||||
QJsonParseError error;
|
QJsonParseError error;
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(QByteArray::fromRawData(json, len), &error);
|
QJsonDocument doc =
|
||||||
|
QJsonDocument::fromJson(QByteArray::fromRawData(json, len), &error);
|
||||||
if (error.error != QJsonParseError::NoError)
|
if (error.error != QJsonParseError::NoError)
|
||||||
return JsonArray();
|
return {};
|
||||||
|
|
||||||
if (!doc.isArray())
|
if (!doc.isArray())
|
||||||
return JsonArray();
|
return {};
|
||||||
|
|
||||||
return JsonArray(doc.array());
|
return JsonArray(doc.array());
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonArray JsonArray::fromJsonSafe(const char *json, int len) noexcept(false)
|
JsonArray JsonArray::fromJsonSafe(const char *json, int len) noexcept(false) {
|
||||||
{
|
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
len = strlen(json);
|
len = strlen(json);
|
||||||
QJsonParseError error;
|
QJsonParseError error;
|
||||||
const auto doc = QJsonDocument::fromJson(QByteArray::fromRawData(json, len), &error);
|
const auto doc =
|
||||||
|
QJsonDocument::fromJson(QByteArray::fromRawData(json, len), &error);
|
||||||
if (error.error != QJsonParseError::NoError)
|
if (error.error != QJsonParseError::NoError)
|
||||||
throw JsonParseError(error);
|
throw JsonParseError(error);
|
||||||
|
|
||||||
@@ -298,329 +247,218 @@ JsonArray JsonArray::fromJsonSafe(const char *json, int len) noexcept(false)
|
|||||||
return JsonArray(doc.array());
|
return JsonArray(doc.array());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class T> struct JsonValue;
|
||||||
|
|
||||||
|
template <class Int> struct JsonLimits {
|
||||||
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
struct JsonValue;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<class Int>
|
|
||||||
struct JsonLimits
|
|
||||||
{
|
|
||||||
static constexpr Int lowest() { return std::numeric_limits<Int>::lowest(); }
|
static constexpr Int lowest() { return std::numeric_limits<Int>::lowest(); }
|
||||||
static constexpr Int max() { return std::numeric_limits<Int>::max(); }
|
static constexpr Int max() { return std::numeric_limits<Int>::max(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <> struct JsonLimits<int64_t> {
|
||||||
|
static constexpr int64_t lowest() {
|
||||||
template<>
|
return -(static_cast<int64_t>(1) << 53) + 1;
|
||||||
struct JsonLimits<int64_t>
|
}
|
||||||
{
|
static constexpr int64_t max() { return (static_cast<int64_t>(1) << 53) - 1; }
|
||||||
static constexpr int64_t lowest() { return -(static_cast<int64_t>(1) << 53) + 1; }
|
|
||||||
static constexpr int64_t max() { return (static_cast<int64_t>(1) << 53) - 1; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <> struct JsonLimits<uint64_t> {
|
||||||
|
|
||||||
template<>
|
|
||||||
struct JsonLimits<uint64_t>
|
|
||||||
{
|
|
||||||
static constexpr uint64_t lowest() { return 0; }
|
static constexpr uint64_t lowest() { return 0; }
|
||||||
static constexpr uint64_t max() { return JsonLimits<int64_t>::max(); }
|
static constexpr uint64_t max() { return JsonLimits<int64_t>::max(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class Int> struct JsonIntValue {
|
||||||
|
static bool matchesType(const QJsonValue &value) {
|
||||||
template<class Int>
|
|
||||||
struct JsonIntValue
|
|
||||||
{
|
|
||||||
static bool matchesType(const QJsonValue &value)
|
|
||||||
{
|
|
||||||
if (!value.isDouble())
|
if (!value.isDouble())
|
||||||
return false;
|
return false;
|
||||||
double val = value.toDouble();
|
double val = value.toDouble();
|
||||||
|
|
||||||
if (val < JsonLimits<Int>::lowest())
|
if (val < JsonLimits<Int>::lowest())
|
||||||
return false;
|
return false;
|
||||||
if (val > JsonLimits<Int>::max())
|
if (val > JsonLimits<Int>::max())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
double wholeInt = static_cast<Int>(val);
|
double wholeInt = static_cast<Int>(val);
|
||||||
return val == wholeInt;
|
return val == wholeInt;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Int value(const QJsonValue &value) noexcept(false)
|
static Int value(const QJsonValue &value) noexcept(false) {
|
||||||
{
|
|
||||||
if (!matchesType(value))
|
if (!matchesType(value))
|
||||||
throw JsonTypeError("JSON value not of type Int");
|
throw JsonTypeError("JSON value not of type Int");
|
||||||
return static_cast<Int>(value.toDouble());
|
return static_cast<Int>(value.toDouble());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <> struct JsonValue<int16_t> : JsonIntValue<int16_t> {};
|
||||||
|
|
||||||
|
template <> struct JsonValue<uint16_t> : JsonIntValue<uint16_t> {};
|
||||||
|
|
||||||
|
template <> struct JsonValue<int32_t> : JsonIntValue<int32_t> {};
|
||||||
|
|
||||||
template<>
|
template <> struct JsonValue<uint32_t> : JsonIntValue<uint32_t> {};
|
||||||
struct JsonValue<int16_t> : JsonIntValue<int16_t>
|
|
||||||
{};
|
|
||||||
|
|
||||||
template<>
|
template <> struct JsonValue<int64_t> : JsonIntValue<int64_t> {};
|
||||||
struct JsonValue<uint16_t> : JsonIntValue<uint16_t>
|
|
||||||
{};
|
|
||||||
|
|
||||||
template<>
|
template <> struct JsonValue<uint64_t> : JsonIntValue<uint64_t> {};
|
||||||
struct JsonValue<int32_t> : JsonIntValue<int32_t>
|
|
||||||
{};
|
|
||||||
|
|
||||||
template<>
|
template <> struct JsonValue<double> {
|
||||||
struct JsonValue<uint32_t> : JsonIntValue<uint32_t>
|
|
||||||
{};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct JsonValue<int64_t> : JsonIntValue<int64_t>
|
|
||||||
{};
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct JsonValue<uint64_t> : JsonIntValue<uint64_t>
|
|
||||||
{};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template<>
|
|
||||||
struct JsonValue<double>
|
|
||||||
{
|
|
||||||
static bool matchesType(const QJsonValue &value) { return value.isDouble(); }
|
static bool matchesType(const QJsonValue &value) { return value.isDouble(); }
|
||||||
|
|
||||||
static double value(const QJsonValue &value) noexcept(false)
|
static double value(const QJsonValue &value) noexcept(false) {
|
||||||
{
|
|
||||||
if (!matchesType(value))
|
if (!matchesType(value))
|
||||||
throw JsonTypeError("JSON value not of type Double");
|
throw JsonTypeError("JSON value not of type Double");
|
||||||
return value.toDouble();
|
return value.toDouble();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <> struct JsonValue<bool> {
|
||||||
|
|
||||||
template<>
|
|
||||||
struct JsonValue<bool>
|
|
||||||
{
|
|
||||||
static bool matchesType(const QJsonValue &value) { return value.isBool(); }
|
static bool matchesType(const QJsonValue &value) { return value.isBool(); }
|
||||||
|
|
||||||
static bool value(const QJsonValue &value) noexcept(false)
|
static bool value(const QJsonValue &value) noexcept(false) {
|
||||||
{
|
|
||||||
if (!matchesType(value))
|
if (!matchesType(value))
|
||||||
throw JsonTypeError("JSON value not of type Bool");
|
throw JsonTypeError("JSON value not of type Bool");
|
||||||
return value.toBool();
|
return value.toBool();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <> struct JsonValue<QString> {
|
||||||
|
|
||||||
template<>
|
|
||||||
struct JsonValue<QString>
|
|
||||||
{
|
|
||||||
static bool matchesType(const QJsonValue &value) { return value.isString(); }
|
static bool matchesType(const QJsonValue &value) { return value.isString(); }
|
||||||
|
|
||||||
static QString value(const QJsonValue &value) noexcept(false)
|
static QString value(const QJsonValue &value) noexcept(false) {
|
||||||
{
|
|
||||||
if (!matchesType(value))
|
if (!matchesType(value))
|
||||||
throw JsonTypeError("JSON value not of type String");
|
throw JsonTypeError("JSON value not of type String");
|
||||||
return value.toString();
|
return value.toString();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <> struct JsonValue<std::string> {
|
||||||
|
|
||||||
template<>
|
|
||||||
struct JsonValue<std::string>
|
|
||||||
{
|
|
||||||
static bool matchesType(const QJsonValue &value) { return value.isString(); }
|
static bool matchesType(const QJsonValue &value) { return value.isString(); }
|
||||||
|
|
||||||
static std::string value(const QJsonValue &value)
|
static std::string value(const QJsonValue &value) {
|
||||||
{
|
|
||||||
return JsonValue<QString>::value(value).toStdString();
|
return JsonValue<QString>::value(value).toStdString();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <> struct JsonValue<QJsonObject> {
|
||||||
|
|
||||||
template<>
|
|
||||||
struct JsonValue<QJsonObject>
|
|
||||||
{
|
|
||||||
static bool matchesType(const QJsonValue &value) { return value.isObject(); }
|
static bool matchesType(const QJsonValue &value) { return value.isObject(); }
|
||||||
|
|
||||||
static QJsonObject value(const QJsonValue &value) noexcept(false)
|
static QJsonObject value(const QJsonValue &value) noexcept(false) {
|
||||||
{
|
|
||||||
if (!matchesType(value))
|
if (!matchesType(value))
|
||||||
throw JsonTypeError("JSON value not of type Object");
|
throw JsonTypeError("JSON value not of type Object");
|
||||||
return value.toObject();
|
return value.toObject();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <> struct JsonValue<JsonObject> {
|
||||||
|
|
||||||
template<>
|
|
||||||
struct JsonValue<JsonObject>
|
|
||||||
{
|
|
||||||
static bool matchesType(const QJsonValue &value) { return value.isObject(); }
|
static bool matchesType(const QJsonValue &value) { return value.isObject(); }
|
||||||
static JsonObject value(const QJsonValue &value) { return JsonObject(JsonValue<QJsonObject>::value(value)); }
|
static JsonObject value(const QJsonValue &value) {
|
||||||
|
return JsonObject(JsonValue<QJsonObject>::value(value));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <> struct JsonValue<void> {
|
||||||
|
|
||||||
template<>
|
|
||||||
struct JsonValue<void>
|
|
||||||
{
|
|
||||||
static bool matchesType(const QJsonValue &value) { return value.isNull(); }
|
static bool matchesType(const QJsonValue &value) { return value.isNull(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <> struct JsonValue<QJsonArray> {
|
||||||
|
|
||||||
template<>
|
|
||||||
struct JsonValue<QJsonArray>
|
|
||||||
{
|
|
||||||
static bool matchesType(const QJsonValue &value) { return value.isArray(); }
|
static bool matchesType(const QJsonValue &value) { return value.isArray(); }
|
||||||
|
|
||||||
static QJsonArray value(const QJsonValue &value) noexcept(false)
|
static QJsonArray value(const QJsonValue &value) noexcept(false) {
|
||||||
{
|
|
||||||
if (!matchesType(value))
|
if (!matchesType(value))
|
||||||
throw JsonTypeError("JSON value not of type Array");
|
throw JsonTypeError("JSON value not of type Array");
|
||||||
return value.toArray();
|
return value.toArray();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <> struct JsonValue<JsonArray> {
|
||||||
|
|
||||||
template<>
|
|
||||||
struct JsonValue<JsonArray>
|
|
||||||
{
|
|
||||||
static bool matchesType(const QJsonValue &value) { return value.isArray(); }
|
static bool matchesType(const QJsonValue &value) { return value.isArray(); }
|
||||||
static JsonArray value(const QJsonValue &value) { return JsonArray(JsonValue<QJsonArray>::value(value)); }
|
static JsonArray value(const QJsonValue &value) {
|
||||||
|
return JsonArray(JsonValue<QJsonArray>::value(value));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class T> struct JsonValue<QVector<T>> {
|
||||||
|
static bool matchesType(const QJsonValue &value) {
|
||||||
template<class T>
|
|
||||||
struct JsonValue<QVector<T>>
|
|
||||||
{
|
|
||||||
static bool matchesType(const QJsonValue &value)
|
|
||||||
{
|
|
||||||
if (!value.isArray())
|
if (!value.isArray())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const JsonArray array(value.toArray());
|
const JsonArray array(value.toArray());
|
||||||
return array.isVector<T>();
|
return array.isVector<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
static QVector<T> value(const QJsonValue &value)
|
static QVector<T> value(const QJsonValue &value) {
|
||||||
{
|
const JsonArray array(JsonValue<QJsonArray>::value(value));
|
||||||
const JsonArray array(JsonValue<QJsonArray>::value(value));
|
|
||||||
return array.toVector<T>();
|
return array.toVector<T>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class T> struct JsonValue<std::vector<T>> {
|
||||||
|
static bool matchesType(const QJsonValue &value) {
|
||||||
template<class T>
|
|
||||||
struct JsonValue<std::vector<T>>
|
|
||||||
{
|
|
||||||
static bool matchesType(const QJsonValue &value)
|
|
||||||
{
|
|
||||||
return JsonValue<QVector<T>>::matchesType(value);
|
return JsonValue<QVector<T>>::matchesType(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<T> value(const QJsonValue &value)
|
static std::vector<T> value(const QJsonValue &value) {
|
||||||
{
|
const JsonArray array(JsonValue<QJsonArray>::value(value));
|
||||||
const JsonArray array(JsonValue<QJsonArray>::value(value));
|
|
||||||
return array.toStdVector<T>();
|
return array.toStdVector<T>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class T> struct JsonValue<QMap<QString, T>> {
|
||||||
|
static bool matchesType(const QJsonValue &value) {
|
||||||
template<class T>
|
|
||||||
struct JsonValue<QMap<QString, T>>
|
|
||||||
{
|
|
||||||
static bool matchesType(const QJsonValue &value)
|
|
||||||
{
|
|
||||||
if (!value.isObject())
|
if (!value.isObject())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const JsonObject obj(JsonValue<QJsonObject>::value(value));
|
const JsonObject obj(JsonValue<QJsonObject>::value(value));
|
||||||
return obj.isMap<T>();
|
return obj.isMap<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
static QMap<QString, T> value(const QJsonValue &value)
|
static QMap<QString, T> value(const QJsonValue &value) {
|
||||||
{
|
const JsonObject obj(JsonValue<QJsonObject>::value(value));
|
||||||
const JsonObject obj(JsonValue<QJsonObject>::value(value));
|
|
||||||
return obj.toMap<T>();
|
return obj.toMap<T>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class T> struct JsonValue<std::map<std::string, T>> {
|
||||||
|
static bool matchesType(const QJsonValue &value) {
|
||||||
template<class T>
|
|
||||||
struct JsonValue<std::map<std::string, T>>
|
|
||||||
{
|
|
||||||
static bool matchesType(const QJsonValue &value)
|
|
||||||
{
|
|
||||||
return JsonValue<QMap<QString, T>>::matchesType(value);
|
return JsonValue<QMap<QString, T>>::matchesType(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::map<std::string, T> value(const QJsonValue &value)
|
static std::map<std::string, T> value(const QJsonValue &value) {
|
||||||
{
|
const JsonObject obj(JsonValue<QJsonObject>::value(value));
|
||||||
const JsonObject obj(JsonValue<QJsonObject>::value(value));
|
|
||||||
return obj.toStdMap<T>();
|
return obj.toStdMap<T>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class T> bool JsonObject::contains(const Key &key) const {
|
||||||
|
|
||||||
template<class T>
|
|
||||||
bool JsonObject::contains(const Key &key) const
|
|
||||||
{
|
|
||||||
if (!m_json.contains(key))
|
if (!m_json.contains(key))
|
||||||
return false;
|
return false;
|
||||||
return JsonValue<T>::matchesType(m_json.value(key));
|
return JsonValue<T>::matchesType(m_json.value(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template <class T> T JsonObject::value(const Key &key) const noexcept(false) {
|
||||||
T JsonObject::value(const Key &key) const noexcept(false)
|
|
||||||
{
|
|
||||||
if (!containsAny(key))
|
if (!containsAny(key))
|
||||||
throw JsonKeyError("no element with key: " + static_cast<const QString &>(key).toStdString());
|
throw JsonKeyError("no element with key: " +
|
||||||
try
|
static_cast<const QString &>(key).toStdString());
|
||||||
{
|
try {
|
||||||
return JsonValue<T>::value(m_json.value(key));
|
return JsonValue<T>::value(m_json.value(key));
|
||||||
}
|
} catch (const JsonTypeError &typeError) {
|
||||||
catch(const JsonTypeError &typeError)
|
throw JsonTypeError(std::string(typeError.what()) + " - key: " +
|
||||||
{
|
static_cast<const QString &>(key).toStdString());
|
||||||
throw JsonTypeError(std::string(typeError.what()) + " - key: " + static_cast<const QString &>(key).toStdString());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template <class T>
|
||||||
T JsonObject::valueOr(const Key &key, const T &defaultValue) const
|
T JsonObject::valueOr(const Key &key, const T &defaultValue) const {
|
||||||
{
|
try {
|
||||||
try
|
|
||||||
{
|
|
||||||
return value<T>(key);
|
return value<T>(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (const JsonKeyError &)
|
catch (const JsonKeyError &) {
|
||||||
{
|
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template <class T> bool JsonObject::isMap() const {
|
||||||
bool JsonObject::isMap() const
|
const QStringList keys = m_json.keys();
|
||||||
{
|
|
||||||
const QStringList keys = m_json.keys();
|
|
||||||
for (const auto &key : keys)
|
for (const auto &key : keys)
|
||||||
if (!JsonValue<T>::matchesType(m_json.value(key)))
|
if (!JsonValue<T>::matchesType(m_json.value(key)))
|
||||||
return false;
|
return false;
|
||||||
@@ -628,69 +466,54 @@ bool JsonObject::isMap() const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template <class T> QMap<QString, T> JsonObject::toMap() const {
|
||||||
QMap<QString, T> JsonObject::toMap() const
|
QMap<QString, T> result;
|
||||||
{
|
|
||||||
QMap<QString, T> result;
|
|
||||||
for (auto current = m_json.begin(); current != m_json.end(); ++current)
|
for (auto current = m_json.begin(); current != m_json.end(); ++current)
|
||||||
result.insert(current.key(), JsonValue<T>::value(current.value()));
|
result.insert(current.key(), JsonValue<T>::value(current.value()));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template <class T> std::map<std::string, T> JsonObject::toStdMap() const {
|
||||||
std::map<std::string, T> JsonObject::toStdMap() const
|
std::map<std::string, T> result;
|
||||||
{
|
|
||||||
std::map<std::string, T> result;
|
|
||||||
for (auto current = m_json.begin(); current != m_json.end(); ++current)
|
for (auto current = m_json.begin(); current != m_json.end(); ++current)
|
||||||
result.insert({current.key().toStdString(), JsonValue<T>::value(current.value())});
|
result.insert(
|
||||||
|
{current.key().toStdString(), JsonValue<T>::value(current.value())});
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class T> bool JsonArray::contains(int index) const noexcept(false) {
|
||||||
|
|
||||||
template<class T>
|
|
||||||
bool JsonArray::contains(int index) const noexcept(false)
|
|
||||||
{
|
|
||||||
if (index < 0 || index >= m_json.size())
|
if (index < 0 || index >= m_json.size())
|
||||||
throw JsonRangeError("index out of range: " + std::to_string(index));
|
throw JsonRangeError("index out of range: " + std::to_string(index));
|
||||||
return JsonValue<T>::matchesType(m_json.at(index));
|
return JsonValue<T>::matchesType(m_json.at(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template <class T> T JsonArray::at(int index) const noexcept(false) {
|
||||||
T JsonArray::at(int index) const noexcept(false)
|
|
||||||
{
|
|
||||||
if (index < 0 || index >= m_json.size())
|
if (index < 0 || index >= m_json.size())
|
||||||
throw JsonRangeError("index out of range: " + std::to_string(index));
|
throw JsonRangeError("index out of range: " + std::to_string(index));
|
||||||
return JsonValue<T>::value(m_json.at(index));
|
return JsonValue<T>::value(m_json.at(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template <class T> bool JsonArray::isVector() const {
|
||||||
bool JsonArray::isVector() const
|
|
||||||
{
|
|
||||||
for (const QJsonValue &value : m_json)
|
for (const QJsonValue &value : m_json)
|
||||||
if (!JsonValue<T>::matchesType(value))
|
if (!JsonValue<T>::matchesType(value))
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template <class T> QVector<T> JsonArray::toVector() const {
|
||||||
QVector<T> JsonArray::toVector() const
|
QVector<T> result;
|
||||||
{
|
|
||||||
QVector<T> result;
|
|
||||||
result.reserve(m_json.size());
|
result.reserve(m_json.size());
|
||||||
for (const QJsonValue &value : m_json)
|
for (const QJsonValue &value : m_json)
|
||||||
result.push_back(JsonValue<T>::value(value));
|
result.push_back(JsonValue<T>::value(value));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template <class T> std::vector<T> JsonArray::toStdVector() const {
|
||||||
std::vector<T> JsonArray::toStdVector() const
|
std::vector<T> result;
|
||||||
{
|
|
||||||
std::vector<T> result;
|
|
||||||
result.reserve(m_json.size());
|
result.reserve(m_json.size());
|
||||||
for (const QJsonValue &value : m_json)
|
for (const QJsonValue &value : m_json)
|
||||||
result.push_back(JsonValue<T>::value(value));
|
result.push_back(JsonValue<T>::value(value));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace LtsUtils
|
||||||
Executable → Regular
+9
-20
@@ -1,45 +1,34 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <cstdint>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
namespace LtsUtils
|
namespace LtsUtils {
|
||||||
{
|
|
||||||
|
|
||||||
template<typename T, typename C>
|
template <typename T, typename C> class PgArray {
|
||||||
class PgArray
|
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
using Type = T;
|
using Type = T;
|
||||||
using ContainerType = C;
|
using ContainerType = C;
|
||||||
|
|
||||||
PgArray() = default;
|
PgArray() = default;
|
||||||
Q_DECL_CONSTEXPR explicit PgArray(const C &data)
|
Q_DECL_CONSTEXPR explicit PgArray(const C &data) : m_data(data) {}
|
||||||
: m_data(data)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Q_DECL_CONSTEXPR C operator()()const
|
Q_DECL_CONSTEXPR C operator()() const { return m_data; }
|
||||||
{
|
|
||||||
return m_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString toPgString() const;
|
[[nodiscard]] QString toPgString() const;
|
||||||
static PgArray fromPgString(const QString &str);
|
static PgArray fromPgString(const QString &str);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
C m_data;
|
C m_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
using IntArray = PgArray<int, std::vector<int>>;
|
using IntArray = PgArray<int, std::vector<int>>;
|
||||||
using BigintArray = PgArray<int64_t, std::vector<int64_t>>;
|
using BigintArray = PgArray<int64_t, std::vector<int64_t>>;
|
||||||
|
|
||||||
|
|
||||||
using IntArray2D = PgArray<int, std::map<int, int>>;
|
using IntArray2D = PgArray<int, std::map<int, int>>;
|
||||||
using BigintArray2D = PgArray<int64_t, std::map<int64_t, int64_t>>;
|
using BigintArray2D = PgArray<int64_t, std::map<int64_t, int64_t>>;
|
||||||
|
|
||||||
}
|
} // namespace LtsUtils
|
||||||
Executable → Regular
+9
-25
@@ -1,15 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
|
namespace LtsUtils {
|
||||||
|
|
||||||
namespace LtsUtils
|
class PromiseExample1_Class : public QObject {
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
class PromiseExample1_Class : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
using QObject::QObject;
|
using QObject::QObject;
|
||||||
@@ -22,49 +17,38 @@ signals:
|
|||||||
void signalDone2(bool didThisWork, int someNumberThatReturns);
|
void signalDone2(bool didThisWork, int someNumberThatReturns);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PromiseExample1 : public QObject {
|
||||||
class PromiseExample1 : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit PromiseExample1(QObject *parent = nullptr);
|
explicit PromiseExample1(QObject *parent = nullptr);
|
||||||
|
|
||||||
bool isSuccess() const { return m_success; }
|
[[nodiscard]] bool isSuccess() const { return m_success; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_success;
|
bool m_success;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PromiseExample2 : public QObject {
|
||||||
|
|
||||||
|
|
||||||
class PromiseExample2 : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit PromiseExample2(QObject *parent = nullptr);
|
explicit PromiseExample2(QObject *parent = nullptr);
|
||||||
|
|
||||||
bool isSuccess() const { return m_success; }
|
[[nodiscard]] bool isSuccess() const { return m_success; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_success;
|
bool m_success;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PromiseExample3 : public QObject {
|
||||||
|
|
||||||
|
|
||||||
class PromiseExample3 : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit PromiseExample3(QObject *parent = nullptr);
|
explicit PromiseExample3(QObject *parent = nullptr);
|
||||||
|
|
||||||
bool isSuccess() const { return m_success; }
|
[[nodiscard]] bool isSuccess() const { return m_success; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_success;
|
bool m_success;
|
||||||
bool m_alreadyRejected;
|
bool m_alreadyRejected;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace LtsUtils
|
||||||
}
|
|
||||||
Executable → Regular
+232
-273
@@ -1,282 +1,241 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QtCore/QByteArray>
|
#include <QtCore/QByteArray>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
namespace LtsUtils
|
namespace LtsUtils {
|
||||||
{
|
|
||||||
|
|
||||||
|
template <typename T> void inline set8Byte(const T in, QByteArray &out) {
|
||||||
|
static_assert(std::is_integral_v<T> || std::is_enum_v<T>,
|
||||||
template<typename T>
|
"Only integrals allowed for raw byte accessd");
|
||||||
void inline set8Byte(const T in, QByteArray& out)
|
out += (in & 0xFF00000000000000UL) >> 56;
|
||||||
{
|
out += (in & 0x00FF000000000000UL) >> 48;
|
||||||
static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "Only integrals allowed for raw byte accessd");
|
out += (in & 0x0000FF0000000000UL) >> 40;
|
||||||
out += (in & 0xFF00000000000000UL) >> 56;
|
out += (in & 0x000000FF00000000UL) >> 32;
|
||||||
out += (in & 0x00FF000000000000UL) >> 48;
|
out += (in & 0x00000000FF000000UL) >> 24;
|
||||||
out += (in & 0x0000FF0000000000UL) >> 40;
|
out += (in & 0x0000000000FF0000UL) >> 16;
|
||||||
out += (in & 0x000000FF00000000UL) >> 32;
|
out += (in & 0x000000000000FF00UL) >> 8;
|
||||||
out += (in & 0x00000000FF000000UL) >> 24;
|
out += (in & 0x00000000000000FFUL);
|
||||||
out += (in & 0x0000000000FF0000UL) >> 16;
|
|
||||||
out += (in & 0x000000000000FF00UL) >> 8;
|
|
||||||
out += (in & 0x00000000000000FFUL);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
void inline set8Byte(const double in, QByteArray &out)
|
|
||||||
{
|
|
||||||
union hack
|
|
||||||
{
|
|
||||||
double d;
|
|
||||||
int64_t i;
|
|
||||||
} h;
|
|
||||||
h.d = in;
|
|
||||||
set8Byte(h.i, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
bool inline get8Byte(const QByteArray& baData,
|
|
||||||
size_t &pos,
|
|
||||||
T& out)
|
|
||||||
{
|
|
||||||
static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "Only integrals allowed for raw byte accessd");
|
|
||||||
static_assert(sizeof(T) >= 8, "sizeof(out) is smaller than 8 bytes - will not fit");
|
|
||||||
out = T();
|
|
||||||
|
|
||||||
if(size_t(baData.size()) < pos + 8)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const char *data = baData.data() + pos;
|
|
||||||
|
|
||||||
if(std::numeric_limits<T>::is_signed)
|
|
||||||
out |= static_cast<signed long long>(data[0]) << 56;
|
|
||||||
else
|
|
||||||
out |= (data[0] & 0xFFULL) << 56;
|
|
||||||
out |= (data[1] & 0xFFULL) << 48;
|
|
||||||
out |= (data[2] & 0xFFULL) << 40;
|
|
||||||
out |= (data[3] & 0xFFULL) << 32;
|
|
||||||
out |= (data[4] & 0xFFULL) << 24;
|
|
||||||
out |= (data[5] & 0xFFULL) << 16;
|
|
||||||
out |= (data[6] & 0xFFULL) << 8;
|
|
||||||
out |= (data[7] & 0xFFULL);
|
|
||||||
|
|
||||||
pos += 8;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
bool inline get8Byte(const QByteArray& baData,
|
|
||||||
size_t &pos,
|
|
||||||
double& out)
|
|
||||||
{
|
|
||||||
out = 0.;
|
|
||||||
union hack
|
|
||||||
{
|
|
||||||
double d;
|
|
||||||
int64_t i;
|
|
||||||
} h;
|
|
||||||
if (!get8Byte(baData, pos, h.i))
|
|
||||||
return false;
|
|
||||||
out = h.d;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
bool inline get8Byte(const QByteArray& data, T& out)
|
|
||||||
{
|
|
||||||
size_t pos = 0;
|
|
||||||
return get8Byte(data, pos, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void inline set4Byte(const T in, QByteArray& out)
|
|
||||||
{
|
|
||||||
static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "Only integrals allowed for raw byte accessd");
|
|
||||||
out += (in & 0xFF000000) >> 24;
|
|
||||||
out += (in & 0x00FF0000) >> 16;
|
|
||||||
out += (in & 0x0000FF00) >> 8;
|
|
||||||
out += (in & 0x000000FF);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
void inline set4Byte(const double in, QByteArray& out)
|
|
||||||
{
|
|
||||||
int tmp = qRound(in);
|
|
||||||
return set4Byte(tmp, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
bool inline get4Byte(const QByteArray& baData,
|
|
||||||
size_t &pos,
|
|
||||||
T& out)
|
|
||||||
{
|
|
||||||
static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "Only integrals allowed for raw byte accessd");
|
|
||||||
static_assert(sizeof(T) >= 4, "sizeof(out) is smaller than 4 bytes - will not fit");
|
|
||||||
out = T();
|
|
||||||
|
|
||||||
if(size_t(baData.size()) < pos + 4)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const char *data = baData.data() + pos;
|
|
||||||
|
|
||||||
if(std::numeric_limits<T>::is_signed)
|
|
||||||
out |= data[0] << 24;
|
|
||||||
else
|
|
||||||
out |= (data[0] & 0xFFU) << 24;
|
|
||||||
out |= (data[1] & 0xFFU) << 16;
|
|
||||||
out |= (data[2] & 0xFFU) << 8;
|
|
||||||
out |= (data[3] & 0xFFU);
|
|
||||||
|
|
||||||
pos += 4;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
bool inline get4Byte(const QByteArray& baData,
|
|
||||||
size_t &pos,
|
|
||||||
double& out)
|
|
||||||
{
|
|
||||||
out = 0.;
|
|
||||||
int tmp;
|
|
||||||
if(!get4Byte(baData, pos, tmp))
|
|
||||||
return false;
|
|
||||||
out = tmp;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
bool inline get4Byte(const QByteArray& data, T& out)
|
|
||||||
{
|
|
||||||
size_t pos = 0;
|
|
||||||
return get4Byte(data, pos, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void inline set3Byte(const T in, QByteArray& out)
|
|
||||||
{
|
|
||||||
static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "Only integrals allowed for raw byte accessd");
|
|
||||||
out += (in & 0x00FF0000) >> 16;
|
|
||||||
out += (in & 0x0000FF00) >> 8;
|
|
||||||
out += (in & 0x000000FF);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
bool inline get3Byte(const QByteArray& baData,
|
|
||||||
size_t &pos,
|
|
||||||
T& out)
|
|
||||||
{
|
|
||||||
static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "Only integrals allowed for raw byte accessd");
|
|
||||||
static_assert(sizeof(T) >= 3, "sizeof(out) is smaller than 3 bytes - will not fit");
|
|
||||||
out = T();
|
|
||||||
|
|
||||||
if(size_t(baData.size()) < pos + 3)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const char *data = baData.data() + pos;
|
|
||||||
|
|
||||||
if(std::numeric_limits<T>::is_signed)
|
|
||||||
out |= data[0] << 16;
|
|
||||||
else
|
|
||||||
out |= (data[0] & 0xFFU) << 16;
|
|
||||||
out |= (data[1] & 0xFFU) << 8;
|
|
||||||
out |= (data[2] & 0xFFU);
|
|
||||||
|
|
||||||
pos += 3;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
bool inline get3Byte(const QByteArray& data, T& out)
|
|
||||||
{
|
|
||||||
size_t pos = 0;
|
|
||||||
return get3Byte(data, pos, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void inline set2Byte(const T in, QByteArray& out)
|
|
||||||
{
|
|
||||||
static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "Only integrals allowed for raw byte accessd");
|
|
||||||
out += (in & 0x0000FF00) >> 8;
|
|
||||||
out += (in & 0x000000FF);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
bool inline get2Byte(const QByteArray& baData,
|
|
||||||
size_t &pos,
|
|
||||||
T& out)
|
|
||||||
{
|
|
||||||
static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "Only integrals allowed for raw byte accessd");
|
|
||||||
static_assert(sizeof(T) >= 2, "sizeof(out) is smaller than 2 bytes - will not fit");
|
|
||||||
out = T();
|
|
||||||
|
|
||||||
if(size_t(baData.size()) < pos + 2)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const char *data = baData.data() + pos;
|
|
||||||
|
|
||||||
if(std::numeric_limits<T>::is_signed)
|
|
||||||
out |= data[0] << 8;
|
|
||||||
else
|
|
||||||
out |= (data[0] & 0xFFU) << 8;
|
|
||||||
out |= data[1] & 0xFFU;
|
|
||||||
|
|
||||||
pos += 2;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
bool inline get2Byte(const QByteArray& data, T& out)
|
|
||||||
{
|
|
||||||
size_t pos = 0;
|
|
||||||
return get2Byte(data, pos, out);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void inline set1Byte(const T in, QByteArray& out)
|
|
||||||
{
|
|
||||||
static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "Only integrals allowed for raw byte accessd");
|
|
||||||
unsigned char c = in;
|
|
||||||
out += c;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
bool inline get1Byte(const QByteArray& baData,
|
|
||||||
size_t &pos,
|
|
||||||
T& out)
|
|
||||||
{
|
|
||||||
static_assert(std::is_integral<T>::value || std::is_enum<T>::value, "Only integrals allowed for raw byte accessd");
|
|
||||||
out = T();
|
|
||||||
|
|
||||||
if(size_t(baData.size()) < pos + 1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
const char *data = baData.data() + pos;
|
|
||||||
|
|
||||||
if(std::numeric_limits<T>::is_signed)
|
|
||||||
out = (T)(data[0]);
|
|
||||||
else
|
|
||||||
out = (T)(data[0] & 0xFF);
|
|
||||||
|
|
||||||
pos += 1;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
bool inline get1Byte(const QByteArray& data, T& out)
|
|
||||||
{
|
|
||||||
size_t pos = 0;
|
|
||||||
return get1Byte(data, pos, out);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <> void inline set8Byte(const double in, QByteArray &out) {
|
||||||
|
union hack {
|
||||||
|
double d;
|
||||||
|
int64_t i;
|
||||||
|
} h;
|
||||||
|
h.d = in;
|
||||||
|
set8Byte(h.i, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool inline get8Byte(const QByteArray &baData, size_t &pos, T &out) {
|
||||||
|
static_assert(std::is_integral_v<T> || std::is_enum_v<T>,
|
||||||
|
"Only integrals allowed for raw byte accessd");
|
||||||
|
static_assert(sizeof(T) >= 8,
|
||||||
|
"sizeof(out) is smaller than 8 bytes - will not fit");
|
||||||
|
out = T();
|
||||||
|
|
||||||
|
if (size_t(baData.size()) < pos + 8)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const char *data = baData.data() + pos;
|
||||||
|
|
||||||
|
if (std::numeric_limits<T>::is_signed)
|
||||||
|
out |= static_cast<signed long long>(data[0]) << 56;
|
||||||
|
else
|
||||||
|
out |= (data[0] & 0xFFULL) << 56;
|
||||||
|
out |= (data[1] & 0xFFULL) << 48;
|
||||||
|
out |= (data[2] & 0xFFULL) << 40;
|
||||||
|
out |= (data[3] & 0xFFULL) << 32;
|
||||||
|
out |= (data[4] & 0xFFULL) << 24;
|
||||||
|
out |= (data[5] & 0xFFULL) << 16;
|
||||||
|
out |= (data[6] & 0xFFULL) << 8;
|
||||||
|
out |= (data[7] & 0xFFULL);
|
||||||
|
|
||||||
|
pos += 8;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
bool inline get8Byte(const QByteArray &baData, size_t &pos, double &out) {
|
||||||
|
out = 0.;
|
||||||
|
union hack {
|
||||||
|
double d;
|
||||||
|
int64_t i;
|
||||||
|
} h;
|
||||||
|
if (!get8Byte(baData, pos, h.i))
|
||||||
|
return false;
|
||||||
|
out = h.d;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> bool inline get8Byte(const QByteArray &data, T &out) {
|
||||||
|
size_t pos = 0;
|
||||||
|
return get8Byte(data, pos, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> void inline set4Byte(const T in, QByteArray &out) {
|
||||||
|
static_assert(std::is_integral_v<T> || std::is_enum_v<T>,
|
||||||
|
"Only integrals allowed for raw byte accessd");
|
||||||
|
out += (in & 0xFF000000) >> 24;
|
||||||
|
out += (in & 0x00FF0000) >> 16;
|
||||||
|
out += (in & 0x0000FF00) >> 8;
|
||||||
|
out += (in & 0x000000FF);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <> void inline set4Byte(const double in, QByteArray &out) {
|
||||||
|
int tmp = qRound(in);
|
||||||
|
return set4Byte(tmp, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool inline get4Byte(const QByteArray &baData, size_t &pos, T &out) {
|
||||||
|
static_assert(std::is_integral_v<T> || std::is_enum_v<T>,
|
||||||
|
"Only integrals allowed for raw byte accessd");
|
||||||
|
static_assert(sizeof(T) >= 4,
|
||||||
|
"sizeof(out) is smaller than 4 bytes - will not fit");
|
||||||
|
out = T();
|
||||||
|
|
||||||
|
if (size_t(baData.size()) < pos + 4)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const char *data = baData.data() + pos;
|
||||||
|
|
||||||
|
if (std::numeric_limits<T>::is_signed)
|
||||||
|
out |= data[0] << 24;
|
||||||
|
else
|
||||||
|
out |= (data[0] & 0xFFU) << 24;
|
||||||
|
out |= (data[1] & 0xFFU) << 16;
|
||||||
|
out |= (data[2] & 0xFFU) << 8;
|
||||||
|
out |= (data[3] & 0xFFU);
|
||||||
|
|
||||||
|
pos += 4;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
bool inline get4Byte(const QByteArray &baData, size_t &pos, double &out) {
|
||||||
|
out = 0.;
|
||||||
|
int tmp;
|
||||||
|
if (!get4Byte(baData, pos, tmp))
|
||||||
|
return false;
|
||||||
|
out = tmp;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> bool inline get4Byte(const QByteArray &data, T &out) {
|
||||||
|
size_t pos = 0;
|
||||||
|
return get4Byte(data, pos, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> void inline set3Byte(const T in, QByteArray &out) {
|
||||||
|
static_assert(std::is_integral_v<T> || std::is_enum_v<T>,
|
||||||
|
"Only integrals allowed for raw byte accessd");
|
||||||
|
out += (in & 0x00FF0000) >> 16;
|
||||||
|
out += (in & 0x0000FF00) >> 8;
|
||||||
|
out += (in & 0x000000FF);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool inline get3Byte(const QByteArray &baData, size_t &pos, T &out) {
|
||||||
|
static_assert(std::is_integral_v<T> || std::is_enum_v<T>,
|
||||||
|
"Only integrals allowed for raw byte accessd");
|
||||||
|
static_assert(sizeof(T) >= 3,
|
||||||
|
"sizeof(out) is smaller than 3 bytes - will not fit");
|
||||||
|
out = T();
|
||||||
|
|
||||||
|
if (size_t(baData.size()) < pos + 3)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const char *data = baData.data() + pos;
|
||||||
|
|
||||||
|
if (std::numeric_limits<T>::is_signed)
|
||||||
|
out |= data[0] << 16;
|
||||||
|
else
|
||||||
|
out |= (data[0] & 0xFFU) << 16;
|
||||||
|
out |= (data[1] & 0xFFU) << 8;
|
||||||
|
out |= (data[2] & 0xFFU);
|
||||||
|
|
||||||
|
pos += 3;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> bool inline get3Byte(const QByteArray &data, T &out) {
|
||||||
|
size_t pos = 0;
|
||||||
|
return get3Byte(data, pos, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> void inline set2Byte(const T in, QByteArray &out) {
|
||||||
|
static_assert(std::is_integral_v<T> || std::is_enum_v<T>,
|
||||||
|
"Only integrals allowed for raw byte accessd");
|
||||||
|
out += (in & 0x0000FF00) >> 8;
|
||||||
|
out += (in & 0x000000FF);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool inline get2Byte(const QByteArray &baData, size_t &pos, T &out) {
|
||||||
|
static_assert(std::is_integral_v<T> || std::is_enum_v<T>,
|
||||||
|
"Only integrals allowed for raw byte accessd");
|
||||||
|
static_assert(sizeof(T) >= 2,
|
||||||
|
"sizeof(out) is smaller than 2 bytes - will not fit");
|
||||||
|
out = T();
|
||||||
|
|
||||||
|
if (size_t(baData.size()) < pos + 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const char *data = baData.data() + pos;
|
||||||
|
|
||||||
|
if (std::numeric_limits<T>::is_signed)
|
||||||
|
out |= data[0] << 8;
|
||||||
|
else
|
||||||
|
out |= (data[0] & 0xFFU) << 8;
|
||||||
|
out |= data[1] & 0xFFU;
|
||||||
|
|
||||||
|
pos += 2;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> bool inline get2Byte(const QByteArray &data, T &out) {
|
||||||
|
size_t pos = 0;
|
||||||
|
return get2Byte(data, pos, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> void inline set1Byte(const T in, QByteArray &out) {
|
||||||
|
static_assert(std::is_integral_v<T> || std::is_enum_v<T>,
|
||||||
|
"Only integrals allowed for raw byte accessd");
|
||||||
|
unsigned char c = in;
|
||||||
|
out += c;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool inline get1Byte(const QByteArray &baData, size_t &pos, T &out) {
|
||||||
|
static_assert(std::is_integral_v<T> || std::is_enum_v<T>,
|
||||||
|
"Only integrals allowed for raw byte accessd");
|
||||||
|
out = T();
|
||||||
|
|
||||||
|
if (size_t(baData.size()) < pos + 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const char *data = baData.data() + pos;
|
||||||
|
|
||||||
|
if (std::numeric_limits<T>::is_signed)
|
||||||
|
out = (T)(data[0]);
|
||||||
|
else
|
||||||
|
out = (T)(data[0] & 0xFF);
|
||||||
|
|
||||||
|
pos += 1;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> bool inline get1Byte(const QByteArray &data, T &out) {
|
||||||
|
size_t pos = 0;
|
||||||
|
return get1Byte(data, pos, out);
|
||||||
|
}
|
||||||
|
} // namespace LtsUtils
|
||||||
Executable → Regular
+184
-251
@@ -6,14 +6,13 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define HTTP_PARSER_VERSION_MAJOR 2
|
#define HTTP_PARSER_VERSION_MAJOR 2
|
||||||
#define HTTP_PARSER_VERSION_MINOR 9
|
#define HTTP_PARSER_VERSION_MINOR 9
|
||||||
#define HTTP_PARSER_VERSION_PATCH 4
|
#define HTTP_PARSER_VERSION_PATCH 4
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#if defined(_WIN32) && !defined(__MINGW32__) && \
|
#if defined(_WIN32) && !defined(__MINGW32__) && \
|
||||||
(!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__)
|
(!defined(_MSC_VER) || _MSC_VER < 1600) && !defined(__WINE__)
|
||||||
#include <BaseTsd.h>
|
#include <BaseTsd.h>
|
||||||
typedef __int8 int8_t;
|
typedef __int8 int8_t;
|
||||||
typedef unsigned __int8 uint8_t;
|
typedef unsigned __int8 uint8_t;
|
||||||
@@ -27,229 +26,196 @@ typedef unsigned __int64 uint64_t;
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef HTTP_PARSER_STRICT
|
#ifndef HTTP_PARSER_STRICT
|
||||||
# define HTTP_PARSER_STRICT 1
|
#define HTTP_PARSER_STRICT 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef HTTP_MAX_HEADER_SIZE
|
#ifndef HTTP_MAX_HEADER_SIZE
|
||||||
# define HTTP_MAX_HEADER_SIZE (80*1024)
|
#define HTTP_MAX_HEADER_SIZE (80 * 1024)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef struct http_parser http_parser;
|
using http_parser = struct http_parser;
|
||||||
typedef struct http_parser_settings http_parser_settings;
|
using http_parser_settings = struct http_parser_settings;
|
||||||
|
|
||||||
|
using http_data_cb = int (*)(http_parser *, const char *, size_t);
|
||||||
|
using http_cb = int (*)(http_parser *);
|
||||||
|
|
||||||
|
#define HTTP_STATUS_MAP(XX) \
|
||||||
|
XX(100, CONTINUE, Continue) \
|
||||||
|
XX(101, SWITCHING_PROTOCOLS, Switching Protocols) \
|
||||||
|
XX(102, PROCESSING, Processing) \
|
||||||
|
XX(200, OK, OK) \
|
||||||
|
XX(201, CREATED, Created) \
|
||||||
|
XX(202, ACCEPTED, Accepted) \
|
||||||
|
XX(203, NON_AUTHORITATIVE_INFORMATION, Non - Authoritative Information) \
|
||||||
|
XX(204, NO_CONTENT, No Content) \
|
||||||
|
XX(205, RESET_CONTENT, Reset Content) \
|
||||||
|
XX(206, PARTIAL_CONTENT, Partial Content) \
|
||||||
|
XX(207, MULTI_STATUS, Multi - Status) \
|
||||||
|
XX(208, ALREADY_REPORTED, Already Reported) \
|
||||||
|
XX(226, IM_USED, IM Used) \
|
||||||
|
XX(300, MULTIPLE_CHOICES, Multiple Choices) \
|
||||||
|
XX(301, MOVED_PERMANENTLY, Moved Permanently) \
|
||||||
|
XX(302, FOUND, Found) \
|
||||||
|
XX(303, SEE_OTHER, See Other) \
|
||||||
|
XX(304, NOT_MODIFIED, Not Modified) \
|
||||||
|
XX(305, USE_PROXY, Use Proxy) \
|
||||||
|
XX(307, TEMPORARY_REDIRECT, Temporary Redirect) \
|
||||||
|
XX(308, PERMANENT_REDIRECT, Permanent Redirect) \
|
||||||
|
XX(400, BAD_REQUEST, Bad Request) \
|
||||||
|
XX(401, UNAUTHORIZED, Unauthorized) \
|
||||||
|
XX(402, PAYMENT_REQUIRED, Payment Required) \
|
||||||
|
XX(403, FORBIDDEN, Forbidden) \
|
||||||
|
XX(404, NOT_FOUND, Not Found) \
|
||||||
|
XX(405, METHOD_NOT_ALLOWED, Method Not Allowed) \
|
||||||
|
XX(406, NOT_ACCEPTABLE, Not Acceptable) \
|
||||||
|
XX(407, PROXY_AUTHENTICATION_REQUIRED, Proxy Authentication Required) \
|
||||||
|
XX(408, REQUEST_TIMEOUT, Request Timeout) \
|
||||||
|
XX(409, CONFLICT, Conflict) \
|
||||||
|
XX(410, GONE, Gone) \
|
||||||
|
XX(411, LENGTH_REQUIRED, Length Required) \
|
||||||
|
XX(412, PRECONDITION_FAILED, Precondition Failed) \
|
||||||
|
XX(413, PAYLOAD_TOO_LARGE, Payload Too Large) \
|
||||||
|
XX(414, URI_TOO_LONG, URI Too Long) \
|
||||||
|
XX(415, UNSUPPORTED_MEDIA_TYPE, Unsupported Media Type) \
|
||||||
|
XX(416, RANGE_NOT_SATISFIABLE, Range Not Satisfiable) \
|
||||||
|
XX(417, EXPECTATION_FAILED, Expectation Failed) \
|
||||||
|
XX(421, MISDIRECTED_REQUEST, Misdirected Request) \
|
||||||
|
XX(422, UNPROCESSABLE_ENTITY, Unprocessable Entity) \
|
||||||
|
XX(423, LOCKED, Locked) \
|
||||||
|
XX(424, FAILED_DEPENDENCY, Failed Dependency) \
|
||||||
|
XX(426, UPGRADE_REQUIRED, Upgrade Required) \
|
||||||
|
XX(428, PRECONDITION_REQUIRED, Precondition Required) \
|
||||||
|
XX(429, TOO_MANY_REQUESTS, Too Many Requests) \
|
||||||
|
XX(431, REQUEST_HEADER_FIELDS_TOO_LARGE, Request Header Fields Too Large) \
|
||||||
|
XX(451, UNAVAILABLE_FOR_LEGAL_REASONS, Unavailable For Legal Reasons) \
|
||||||
|
XX(500, INTERNAL_SERVER_ERROR, Internal Server Error) \
|
||||||
|
XX(501, NOT_IMPLEMENTED, Not Implemented) \
|
||||||
|
XX(502, BAD_GATEWAY, Bad Gateway) \
|
||||||
|
XX(503, SERVICE_UNAVAILABLE, Service Unavailable) \
|
||||||
|
XX(504, GATEWAY_TIMEOUT, Gateway Timeout) \
|
||||||
|
XX(505, HTTP_VERSION_NOT_SUPPORTED, HTTP Version Not Supported) \
|
||||||
|
XX(506, VARIANT_ALSO_NEGOTIATES, Variant Also Negotiates) \
|
||||||
|
XX(507, INSUFFICIENT_STORAGE, Insufficient Storage) \
|
||||||
|
XX(508, LOOP_DETECTED, Loop Detected) \
|
||||||
|
XX(510, NOT_EXTENDED, Not Extended) \
|
||||||
|
XX(511, NETWORK_AUTHENTICATION_REQUIRED, Network Authentication Required)
|
||||||
|
|
||||||
|
enum http_status {
|
||||||
typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
|
|
||||||
typedef int (*http_cb) (http_parser*);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define HTTP_STATUS_MAP(XX) \
|
|
||||||
XX(100, CONTINUE, Continue) \
|
|
||||||
XX(101, SWITCHING_PROTOCOLS, Switching Protocols) \
|
|
||||||
XX(102, PROCESSING, Processing) \
|
|
||||||
XX(200, OK, OK) \
|
|
||||||
XX(201, CREATED, Created) \
|
|
||||||
XX(202, ACCEPTED, Accepted) \
|
|
||||||
XX(203, NON_AUTHORITATIVE_INFORMATION, Non-Authoritative Information) \
|
|
||||||
XX(204, NO_CONTENT, No Content) \
|
|
||||||
XX(205, RESET_CONTENT, Reset Content) \
|
|
||||||
XX(206, PARTIAL_CONTENT, Partial Content) \
|
|
||||||
XX(207, MULTI_STATUS, Multi-Status) \
|
|
||||||
XX(208, ALREADY_REPORTED, Already Reported) \
|
|
||||||
XX(226, IM_USED, IM Used) \
|
|
||||||
XX(300, MULTIPLE_CHOICES, Multiple Choices) \
|
|
||||||
XX(301, MOVED_PERMANENTLY, Moved Permanently) \
|
|
||||||
XX(302, FOUND, Found) \
|
|
||||||
XX(303, SEE_OTHER, See Other) \
|
|
||||||
XX(304, NOT_MODIFIED, Not Modified) \
|
|
||||||
XX(305, USE_PROXY, Use Proxy) \
|
|
||||||
XX(307, TEMPORARY_REDIRECT, Temporary Redirect) \
|
|
||||||
XX(308, PERMANENT_REDIRECT, Permanent Redirect) \
|
|
||||||
XX(400, BAD_REQUEST, Bad Request) \
|
|
||||||
XX(401, UNAUTHORIZED, Unauthorized) \
|
|
||||||
XX(402, PAYMENT_REQUIRED, Payment Required) \
|
|
||||||
XX(403, FORBIDDEN, Forbidden) \
|
|
||||||
XX(404, NOT_FOUND, Not Found) \
|
|
||||||
XX(405, METHOD_NOT_ALLOWED, Method Not Allowed) \
|
|
||||||
XX(406, NOT_ACCEPTABLE, Not Acceptable) \
|
|
||||||
XX(407, PROXY_AUTHENTICATION_REQUIRED, Proxy Authentication Required) \
|
|
||||||
XX(408, REQUEST_TIMEOUT, Request Timeout) \
|
|
||||||
XX(409, CONFLICT, Conflict) \
|
|
||||||
XX(410, GONE, Gone) \
|
|
||||||
XX(411, LENGTH_REQUIRED, Length Required) \
|
|
||||||
XX(412, PRECONDITION_FAILED, Precondition Failed) \
|
|
||||||
XX(413, PAYLOAD_TOO_LARGE, Payload Too Large) \
|
|
||||||
XX(414, URI_TOO_LONG, URI Too Long) \
|
|
||||||
XX(415, UNSUPPORTED_MEDIA_TYPE, Unsupported Media Type) \
|
|
||||||
XX(416, RANGE_NOT_SATISFIABLE, Range Not Satisfiable) \
|
|
||||||
XX(417, EXPECTATION_FAILED, Expectation Failed) \
|
|
||||||
XX(421, MISDIRECTED_REQUEST, Misdirected Request) \
|
|
||||||
XX(422, UNPROCESSABLE_ENTITY, Unprocessable Entity) \
|
|
||||||
XX(423, LOCKED, Locked) \
|
|
||||||
XX(424, FAILED_DEPENDENCY, Failed Dependency) \
|
|
||||||
XX(426, UPGRADE_REQUIRED, Upgrade Required) \
|
|
||||||
XX(428, PRECONDITION_REQUIRED, Precondition Required) \
|
|
||||||
XX(429, TOO_MANY_REQUESTS, Too Many Requests) \
|
|
||||||
XX(431, REQUEST_HEADER_FIELDS_TOO_LARGE, Request Header Fields Too Large) \
|
|
||||||
XX(451, UNAVAILABLE_FOR_LEGAL_REASONS, Unavailable For Legal Reasons) \
|
|
||||||
XX(500, INTERNAL_SERVER_ERROR, Internal Server Error) \
|
|
||||||
XX(501, NOT_IMPLEMENTED, Not Implemented) \
|
|
||||||
XX(502, BAD_GATEWAY, Bad Gateway) \
|
|
||||||
XX(503, SERVICE_UNAVAILABLE, Service Unavailable) \
|
|
||||||
XX(504, GATEWAY_TIMEOUT, Gateway Timeout) \
|
|
||||||
XX(505, HTTP_VERSION_NOT_SUPPORTED, HTTP Version Not Supported) \
|
|
||||||
XX(506, VARIANT_ALSO_NEGOTIATES, Variant Also Negotiates) \
|
|
||||||
XX(507, INSUFFICIENT_STORAGE, Insufficient Storage) \
|
|
||||||
XX(508, LOOP_DETECTED, Loop Detected) \
|
|
||||||
XX(510, NOT_EXTENDED, Not Extended) \
|
|
||||||
XX(511, NETWORK_AUTHENTICATION_REQUIRED, Network Authentication Required) \
|
|
||||||
|
|
||||||
enum http_status
|
|
||||||
{
|
|
||||||
#define XX(num, name, string) HTTP_STATUS_##name = num,
|
#define XX(num, name, string) HTTP_STATUS_##name = num,
|
||||||
HTTP_STATUS_MAP(XX)
|
HTTP_STATUS_MAP(XX)
|
||||||
#undef XX
|
#undef XX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define HTTP_METHOD_MAP(XX) \
|
||||||
|
XX(0, DELETE, DELETE) \
|
||||||
|
XX(1, GET, GET) \
|
||||||
|
XX(2, HEAD, HEAD) \
|
||||||
|
XX(3, POST, POST) \
|
||||||
|
XX(4, PUT, PUT) \
|
||||||
|
\
|
||||||
|
XX(5, CONNECT, CONNECT) \
|
||||||
|
XX(6, OPTIONS, OPTIONS) \
|
||||||
|
XX(7, TRACE, TRACE) \
|
||||||
|
\
|
||||||
|
XX(8, COPY, COPY) \
|
||||||
|
XX(9, LOCK, LOCK) \
|
||||||
|
XX(10, MKCOL, MKCOL) \
|
||||||
|
XX(11, MOVE, MOVE) \
|
||||||
|
XX(12, PROPFIND, PROPFIND) \
|
||||||
|
XX(13, PROPPATCH, PROPPATCH) \
|
||||||
|
XX(14, SEARCH, SEARCH) \
|
||||||
|
XX(15, UNLOCK, UNLOCK) \
|
||||||
|
XX(16, BIND, BIND) \
|
||||||
|
XX(17, REBIND, REBIND) \
|
||||||
|
XX(18, UNBIND, UNBIND) \
|
||||||
|
XX(19, ACL, ACL) \
|
||||||
|
\
|
||||||
|
XX(20, REPORT, REPORT) \
|
||||||
|
XX(21, MKACTIVITY, MKACTIVITY) \
|
||||||
|
XX(22, CHECKOUT, CHECKOUT) \
|
||||||
|
XX(23, MERGE, MERGE) \
|
||||||
|
\
|
||||||
|
XX(24, MSEARCH, M - SEARCH) \
|
||||||
|
XX(25, NOTIFY, NOTIFY) \
|
||||||
|
XX(26, SUBSCRIBE, SUBSCRIBE) \
|
||||||
|
XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \
|
||||||
|
\
|
||||||
|
XX(28, PATCH, PATCH) \
|
||||||
|
XX(29, PURGE, PURGE) \
|
||||||
|
\
|
||||||
|
XX(30, MKCALENDAR, MKCALENDAR) \
|
||||||
|
\
|
||||||
|
XX(31, LINK, LINK) \
|
||||||
|
XX(32, UNLINK, UNLINK) \
|
||||||
|
\
|
||||||
|
XX(33, SOURCE, SOURCE)
|
||||||
|
|
||||||
|
enum http_method {
|
||||||
#define HTTP_METHOD_MAP(XX) \
|
|
||||||
XX(0, DELETE, DELETE) \
|
|
||||||
XX(1, GET, GET) \
|
|
||||||
XX(2, HEAD, HEAD) \
|
|
||||||
XX(3, POST, POST) \
|
|
||||||
XX(4, PUT, PUT) \
|
|
||||||
\
|
|
||||||
XX(5, CONNECT, CONNECT) \
|
|
||||||
XX(6, OPTIONS, OPTIONS) \
|
|
||||||
XX(7, TRACE, TRACE) \
|
|
||||||
\
|
|
||||||
XX(8, COPY, COPY) \
|
|
||||||
XX(9, LOCK, LOCK) \
|
|
||||||
XX(10, MKCOL, MKCOL) \
|
|
||||||
XX(11, MOVE, MOVE) \
|
|
||||||
XX(12, PROPFIND, PROPFIND) \
|
|
||||||
XX(13, PROPPATCH, PROPPATCH) \
|
|
||||||
XX(14, SEARCH, SEARCH) \
|
|
||||||
XX(15, UNLOCK, UNLOCK) \
|
|
||||||
XX(16, BIND, BIND) \
|
|
||||||
XX(17, REBIND, REBIND) \
|
|
||||||
XX(18, UNBIND, UNBIND) \
|
|
||||||
XX(19, ACL, ACL) \
|
|
||||||
\
|
|
||||||
XX(20, REPORT, REPORT) \
|
|
||||||
XX(21, MKACTIVITY, MKACTIVITY) \
|
|
||||||
XX(22, CHECKOUT, CHECKOUT) \
|
|
||||||
XX(23, MERGE, MERGE) \
|
|
||||||
\
|
|
||||||
XX(24, MSEARCH, M-SEARCH) \
|
|
||||||
XX(25, NOTIFY, NOTIFY) \
|
|
||||||
XX(26, SUBSCRIBE, SUBSCRIBE) \
|
|
||||||
XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \
|
|
||||||
\
|
|
||||||
XX(28, PATCH, PATCH) \
|
|
||||||
XX(29, PURGE, PURGE) \
|
|
||||||
\
|
|
||||||
XX(30, MKCALENDAR, MKCALENDAR) \
|
|
||||||
\
|
|
||||||
XX(31, LINK, LINK) \
|
|
||||||
XX(32, UNLINK, UNLINK) \
|
|
||||||
\
|
|
||||||
XX(33, SOURCE, SOURCE) \
|
|
||||||
|
|
||||||
enum http_method
|
|
||||||
{
|
|
||||||
#define XX(num, name, string) HTTP_##name = num,
|
#define XX(num, name, string) HTTP_##name = num,
|
||||||
HTTP_METHOD_MAP(XX)
|
HTTP_METHOD_MAP(XX)
|
||||||
#undef XX
|
#undef XX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH };
|
enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH };
|
||||||
|
|
||||||
|
enum flags {
|
||||||
|
F_CHUNKED = 1 << 0,
|
||||||
|
F_CONNECTION_KEEP_ALIVE = 1 << 1,
|
||||||
|
F_CONNECTION_CLOSE = 1 << 2,
|
||||||
|
F_CONNECTION_UPGRADE = 1 << 3,
|
||||||
|
F_TRAILING = 1 << 4,
|
||||||
|
F_UPGRADE = 1 << 5,
|
||||||
|
F_SKIPBODY = 1 << 6,
|
||||||
|
F_CONTENTLENGTH = 1 << 7,
|
||||||
|
F_TRANSFER_ENCODING = 1 << 8
|
||||||
|
};
|
||||||
|
|
||||||
|
#define HTTP_ERRNO_MAP(XX) \
|
||||||
enum flags
|
\
|
||||||
{ F_CHUNKED = 1 << 0
|
XX(OK, "success") \
|
||||||
, F_CONNECTION_KEEP_ALIVE = 1 << 1
|
\
|
||||||
, F_CONNECTION_CLOSE = 1 << 2
|
XX(CB_message_begin, "the on_message_begin callback failed") \
|
||||||
, F_CONNECTION_UPGRADE = 1 << 3
|
XX(CB_url, "the on_url callback failed") \
|
||||||
, F_TRAILING = 1 << 4
|
XX(CB_header_field, "the on_header_field callback failed") \
|
||||||
, F_UPGRADE = 1 << 5
|
XX(CB_header_value, "the on_header_value callback failed") \
|
||||||
, F_SKIPBODY = 1 << 6
|
XX(CB_headers_complete, "the on_headers_complete callback failed") \
|
||||||
, F_CONTENTLENGTH = 1 << 7
|
XX(CB_body, "the on_body callback failed") \
|
||||||
, F_TRANSFER_ENCODING = 1 << 8
|
XX(CB_message_complete, "the on_message_complete callback failed") \
|
||||||
};
|
XX(CB_status, "the on_status callback failed") \
|
||||||
|
XX(CB_chunk_header, "the on_chunk_header callback failed") \
|
||||||
|
XX(CB_chunk_complete, "the on_chunk_complete callback failed") \
|
||||||
|
\
|
||||||
|
XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \
|
||||||
#define HTTP_ERRNO_MAP(XX) \
|
XX(HEADER_OVERFLOW, "too many header bytes seen; overflow detected") \
|
||||||
\
|
XX(CLOSED_CONNECTION, \
|
||||||
XX(OK, "success") \
|
"data received after completed connection: close message") \
|
||||||
\
|
XX(INVALID_VERSION, "invalid HTTP version") \
|
||||||
\
|
XX(INVALID_STATUS, "invalid HTTP status code") \
|
||||||
XX(CB_message_begin, "the on_message_begin callback failed") \
|
XX(INVALID_METHOD, "invalid HTTP method") \
|
||||||
XX(CB_url, "the on_url callback failed") \
|
XX(INVALID_URL, "invalid URL") \
|
||||||
XX(CB_header_field, "the on_header_field callback failed") \
|
XX(INVALID_HOST, "invalid host") \
|
||||||
XX(CB_header_value, "the on_header_value callback failed") \
|
XX(INVALID_PORT, "invalid port") \
|
||||||
XX(CB_headers_complete, "the on_headers_complete callback failed") \
|
XX(INVALID_PATH, "invalid path") \
|
||||||
XX(CB_body, "the on_body callback failed") \
|
XX(INVALID_QUERY_STRING, "invalid query string") \
|
||||||
XX(CB_message_complete, "the on_message_complete callback failed") \
|
XX(INVALID_FRAGMENT, "invalid fragment") \
|
||||||
XX(CB_status, "the on_status callback failed") \
|
XX(LF_EXPECTED, "LF character expected") \
|
||||||
XX(CB_chunk_header, "the on_chunk_header callback failed") \
|
XX(INVALID_HEADER_TOKEN, "invalid character in header") \
|
||||||
XX(CB_chunk_complete, "the on_chunk_complete callback failed") \
|
XX(INVALID_CONTENT_LENGTH, "invalid character in content-length header") \
|
||||||
\
|
XX(UNEXPECTED_CONTENT_LENGTH, "unexpected content-length header") \
|
||||||
\
|
XX(INVALID_CHUNK_SIZE, "invalid character in chunk size header") \
|
||||||
XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \
|
XX(INVALID_CONSTANT, "invalid constant string") \
|
||||||
XX(HEADER_OVERFLOW, \
|
XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state") \
|
||||||
"too many header bytes seen; overflow detected") \
|
XX(STRICT, "strict mode assertion failed") \
|
||||||
XX(CLOSED_CONNECTION, \
|
XX(PAUSED, "parser is paused") \
|
||||||
"data received after completed connection: close message") \
|
XX(UNKNOWN, "an unknown error occurred") \
|
||||||
XX(INVALID_VERSION, "invalid HTTP version") \
|
XX(INVALID_TRANSFER_ENCODING, "request has invalid transfer-encoding")
|
||||||
XX(INVALID_STATUS, "invalid HTTP status code") \
|
|
||||||
XX(INVALID_METHOD, "invalid HTTP method") \
|
|
||||||
XX(INVALID_URL, "invalid URL") \
|
|
||||||
XX(INVALID_HOST, "invalid host") \
|
|
||||||
XX(INVALID_PORT, "invalid port") \
|
|
||||||
XX(INVALID_PATH, "invalid path") \
|
|
||||||
XX(INVALID_QUERY_STRING, "invalid query string") \
|
|
||||||
XX(INVALID_FRAGMENT, "invalid fragment") \
|
|
||||||
XX(LF_EXPECTED, "LF character expected") \
|
|
||||||
XX(INVALID_HEADER_TOKEN, "invalid character in header") \
|
|
||||||
XX(INVALID_CONTENT_LENGTH, \
|
|
||||||
"invalid character in content-length header") \
|
|
||||||
XX(UNEXPECTED_CONTENT_LENGTH, \
|
|
||||||
"unexpected content-length header") \
|
|
||||||
XX(INVALID_CHUNK_SIZE, \
|
|
||||||
"invalid character in chunk size header") \
|
|
||||||
XX(INVALID_CONSTANT, "invalid constant string") \
|
|
||||||
XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\
|
|
||||||
XX(STRICT, "strict mode assertion failed") \
|
|
||||||
XX(PAUSED, "parser is paused") \
|
|
||||||
XX(UNKNOWN, "an unknown error occurred") \
|
|
||||||
XX(INVALID_TRANSFER_ENCODING, \
|
|
||||||
"request has invalid transfer-encoding") \
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define HTTP_ERRNO_GEN(n, s) HPE_##n,
|
#define HTTP_ERRNO_GEN(n, s) HPE_##n,
|
||||||
enum http_errno {
|
enum http_errno { HTTP_ERRNO_MAP(HTTP_ERRNO_GEN) };
|
||||||
HTTP_ERRNO_MAP(HTTP_ERRNO_GEN)
|
|
||||||
};
|
|
||||||
#undef HTTP_ERRNO_GEN
|
#undef HTTP_ERRNO_GEN
|
||||||
|
|
||||||
|
#define HTTP_PARSER_ERRNO(p) ((enum http_errno)(p)->http_errno)
|
||||||
|
|
||||||
#define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno)
|
|
||||||
|
|
||||||
|
|
||||||
struct http_parser {
|
struct http_parser {
|
||||||
|
|
||||||
@@ -264,51 +230,41 @@ struct http_parser {
|
|||||||
uint32_t nread;
|
uint32_t nread;
|
||||||
uint64_t content_length;
|
uint64_t content_length;
|
||||||
|
|
||||||
|
|
||||||
unsigned short http_major;
|
unsigned short http_major;
|
||||||
unsigned short http_minor;
|
unsigned short http_minor;
|
||||||
unsigned int status_code : 16;
|
unsigned int status_code : 16;
|
||||||
unsigned int method : 8;
|
unsigned int method : 8;
|
||||||
unsigned int http_errno : 7;
|
unsigned int http_errno : 7;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
unsigned int upgrade : 1;
|
unsigned int upgrade : 1;
|
||||||
|
|
||||||
|
|
||||||
void *data;
|
void *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct http_parser_settings {
|
struct http_parser_settings {
|
||||||
http_cb on_message_begin;
|
http_cb on_message_begin;
|
||||||
http_data_cb on_url;
|
http_data_cb on_url;
|
||||||
http_data_cb on_status;
|
http_data_cb on_status;
|
||||||
http_data_cb on_header_field;
|
http_data_cb on_header_field;
|
||||||
http_data_cb on_header_value;
|
http_data_cb on_header_value;
|
||||||
http_cb on_headers_complete;
|
http_cb on_headers_complete;
|
||||||
http_data_cb on_body;
|
http_data_cb on_body;
|
||||||
http_cb on_message_complete;
|
http_cb on_message_complete;
|
||||||
|
|
||||||
|
http_cb on_chunk_header;
|
||||||
http_cb on_chunk_header;
|
http_cb on_chunk_complete;
|
||||||
http_cb on_chunk_complete;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum http_parser_url_fields {
|
||||||
enum http_parser_url_fields
|
UF_SCHEMA = 0,
|
||||||
{ UF_SCHEMA = 0
|
UF_HOST = 1,
|
||||||
, UF_HOST = 1
|
UF_PORT = 2,
|
||||||
, UF_PORT = 2
|
UF_PATH = 3,
|
||||||
, UF_PATH = 3
|
UF_QUERY = 4,
|
||||||
, UF_QUERY = 4
|
UF_FRAGMENT = 5,
|
||||||
, UF_FRAGMENT = 5
|
UF_USERINFO = 6,
|
||||||
, UF_USERINFO = 6
|
UF_MAX = 7
|
||||||
, UF_MAX = 7
|
};
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct http_parser_url {
|
struct http_parser_url {
|
||||||
uint16_t field_set;
|
uint16_t field_set;
|
||||||
@@ -320,58 +276,35 @@ struct http_parser_url {
|
|||||||
} field_data[UF_MAX];
|
} field_data[UF_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
unsigned long http_parser_version(void);
|
unsigned long http_parser_version(void);
|
||||||
|
|
||||||
void http_parser_init(http_parser *parser, enum http_parser_type type);
|
void http_parser_init(http_parser *parser, enum http_parser_type type);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void http_parser_settings_init(http_parser_settings *settings);
|
void http_parser_settings_init(http_parser_settings *settings);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
size_t http_parser_execute(http_parser *parser,
|
size_t http_parser_execute(http_parser *parser,
|
||||||
const http_parser_settings *settings,
|
const http_parser_settings *settings,
|
||||||
const char *data,
|
const char *data, size_t len);
|
||||||
size_t len);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int http_should_keep_alive(const http_parser *parser);
|
int http_should_keep_alive(const http_parser *parser);
|
||||||
|
|
||||||
|
|
||||||
const char *http_method_str(enum http_method m);
|
const char *http_method_str(enum http_method m);
|
||||||
|
|
||||||
|
|
||||||
const char *http_status_str(enum http_status s);
|
const char *http_status_str(enum http_status s);
|
||||||
|
|
||||||
|
|
||||||
const char *http_errno_name(enum http_errno err);
|
const char *http_errno_name(enum http_errno err);
|
||||||
|
|
||||||
|
|
||||||
const char *http_errno_description(enum http_errno err);
|
const char *http_errno_description(enum http_errno err);
|
||||||
|
|
||||||
|
|
||||||
void http_parser_url_init(struct http_parser_url *u);
|
void http_parser_url_init(struct http_parser_url *u);
|
||||||
|
|
||||||
|
int http_parser_parse_url(const char *buf, size_t buflen, int is_connect,
|
||||||
int http_parser_parse_url(const char *buf, size_t buflen,
|
|
||||||
int is_connect,
|
|
||||||
struct http_parser_url *u);
|
struct http_parser_url *u);
|
||||||
|
|
||||||
|
|
||||||
void http_parser_pause(http_parser *parser, int paused);
|
void http_parser_pause(http_parser *parser, int paused);
|
||||||
|
|
||||||
|
|
||||||
int http_body_is_final(const http_parser *parser);
|
int http_body_is_final(const http_parser *parser);
|
||||||
|
|
||||||
|
|
||||||
void http_parser_set_max_header_size(uint32_t size);
|
void http_parser_set_max_header_size(uint32_t size);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|||||||
Reference in new issue
Block a user