From acee7b876687a95f962ebfdac63c51892313d010 Mon Sep 17 00:00:00 2001 From: Torsten Wierschin Date: Sat, 18 Jul 2026 16:48:13 +0200 Subject: [PATCH] migrate(Lts/Common): apply clang-tidy modernization fixes\n\nCo-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../WebSocket/json_keys.h | 75 +- Lts/Common/LtsUtils/LtsUtilsCore/connection.h | 225 ++- Lts/Common/LtsUtils/LtsUtilsCore/dds_vector.h | 78 +- .../LtsUtils/LtsUtilsCore/json_object.h | 1215 +++++++---------- Lts/Common/LtsUtils/LtsUtilsCore/pgarray.h | 79 +- .../LtsUtils/LtsUtilsCore/promise_examples.h | 124 +- .../LtsUtilsCore/qbytearray_byteaccess.h | 523 ++++--- Lts/Common/httq/include/http_parser.h | 465 +++---- 8 files changed, 1216 insertions(+), 1568 deletions(-) mode change 100755 => 100644 Lts/Common/LtsProjectionWorkstation/WebSocket/json_keys.h mode change 100755 => 100644 Lts/Common/LtsUtils/LtsUtilsCore/connection.h mode change 100755 => 100644 Lts/Common/LtsUtils/LtsUtilsCore/dds_vector.h mode change 100755 => 100644 Lts/Common/LtsUtils/LtsUtilsCore/json_object.h mode change 100755 => 100644 Lts/Common/LtsUtils/LtsUtilsCore/pgarray.h mode change 100755 => 100644 Lts/Common/LtsUtils/LtsUtilsCore/promise_examples.h mode change 100755 => 100644 Lts/Common/LtsUtils/LtsUtilsCore/qbytearray_byteaccess.h mode change 100755 => 100644 Lts/Common/httq/include/http_parser.h diff --git a/Lts/Common/LtsProjectionWorkstation/WebSocket/json_keys.h b/Lts/Common/LtsProjectionWorkstation/WebSocket/json_keys.h old mode 100755 new mode 100644 index fcfcbfa1e..a8673fc52 --- a/Lts/Common/LtsProjectionWorkstation/WebSocket/json_keys.h +++ b/Lts/Common/LtsProjectionWorkstation/WebSocket/json_keys.h @@ -1,40 +1,35 @@ - - -#pragma once - -#include - -namespace LtsProjectionWorkstation -{ -namespace JsonKeys -{ - -inline QString ERROR_MESSAGE() { return QStringLiteral("errorMessage"); } - - -inline QString LOGIN_REQUEST() { return QStringLiteral("loginRequest"); } -inline QString LOGOUT_REQUEST() { return QStringLiteral("logoutRequest"); } -inline QString DISCONNECT_REQUEST() { return QStringLiteral("disconnectRequest"); } - - - -inline QString LOGIN_REPLY() { return QStringLiteral("loginReply"); } -inline QString LOGOUT_REPLY() { return QStringLiteral("logoutReply"); } -inline QString DEDICAED_DISCONNECT() { return QStringLiteral("dedicatedDisconnect"); } - - -inline QString USER_ID() { return QStringLiteral("userId"); } -inline QString USER_PRIORITY() { return QStringLiteral("userPriority"); } -inline QString EXERCISE_ID() { return QStringLiteral("exerciseId"); } -inline QString NAME() { return QStringLiteral("name"); } -inline QString PORT() { return QStringLiteral("port"); } -inline QString WIDTH() { return QStringLiteral("width"); } -inline QString HEIGHT() { return QStringLiteral("height"); } -inline QString REASON() { return QStringLiteral("reason"); } -inline QString SUCCESS() { return QStringLiteral("success"); } -inline QString SCREENS() { return QStringLiteral("screens"); } -inline QString SETTINGS_DATA() { return QStringLiteral("settingsData"); } - -} - -} + + +#pragma once + +#include + +namespace LtsProjectionWorkstation::JsonKeys { + +inline QString ERROR_MESSAGE() { return QStringLiteral("errorMessage"); } + +inline QString LOGIN_REQUEST() { return QStringLiteral("loginRequest"); } +inline QString LOGOUT_REQUEST() { return QStringLiteral("logoutRequest"); } +inline QString DISCONNECT_REQUEST() { + return QStringLiteral("disconnectRequest"); +} + +inline QString LOGIN_REPLY() { return QStringLiteral("loginReply"); } +inline QString LOGOUT_REPLY() { return QStringLiteral("logoutReply"); } +inline QString DEDICAED_DISCONNECT() { + return QStringLiteral("dedicatedDisconnect"); +} + +inline QString USER_ID() { return QStringLiteral("userId"); } +inline QString USER_PRIORITY() { return QStringLiteral("userPriority"); } +inline QString EXERCISE_ID() { return QStringLiteral("exerciseId"); } +inline QString NAME() { return QStringLiteral("name"); } +inline QString PORT() { return QStringLiteral("port"); } +inline QString WIDTH() { return QStringLiteral("width"); } +inline QString HEIGHT() { return QStringLiteral("height"); } +inline QString REASON() { return QStringLiteral("reason"); } +inline QString SUCCESS() { return QStringLiteral("success"); } +inline QString SCREENS() { return QStringLiteral("screens"); } +inline QString SETTINGS_DATA() { return QStringLiteral("settingsData"); } + +} // namespace LtsProjectionWorkstation::JsonKeys diff --git a/Lts/Common/LtsUtils/LtsUtilsCore/connection.h b/Lts/Common/LtsUtils/LtsUtilsCore/connection.h old mode 100755 new mode 100644 index 47f736947..5c14f79c5 --- a/Lts/Common/LtsUtils/LtsUtilsCore/connection.h +++ b/Lts/Common/LtsUtils/LtsUtilsCore/connection.h @@ -1,126 +1,99 @@ - - - -#pragma once - -#include -#include -#include -#include -#include - - -namespace LtsUtils -{ - - - -class IConnection -{ -public: - virtual ~IConnection() = default; - virtual void connect(Qt::ConnectionType = Qt::AutoConnection) = 0; - virtual void disconnect() = 0; -}; - - - - -class DummyConnection : public IConnection -{ -public: - void connect(Qt::ConnectionType = Qt::AutoConnection) override {} - void disconnect() override {} -}; - - -namespace detail -{ - - - -template -struct ExtractClass; - - - -template -struct ExtractClass -{ - using type = T; -}; - -} - - - - -template -class Connection : public IConnection -{ - static_assert(std::is_member_function_pointer::value, "Must be a pointer to method"); - static_assert(std::is_member_function_pointer::value, "Must be a pointer to method"); - - using Emitter = typename detail::ExtractClass::type; - using Target = typename detail::ExtractClass::type; - - static_assert(std::is_base_of::value, "Must be derived from QObject"); - static_assert(std::is_base_of::value, "Must be derived from QObject"); - -public: - Connection(Emitter *emitter, Signal signal, Target *target, Slot slot): - m_emitter(emitter), - m_signal(signal), - m_target(target), - m_slot(slot) - { - Q_ASSERT(emitter); - Q_ASSERT(signal); - Q_ASSERT(target); - Q_ASSERT(slot); - } - - void connect(Qt::ConnectionType connectionType = Qt::AutoConnection) override - { - Q_ASSERT(!m_connected); - - m_connected = true; - - - - if (!m_emitter || !m_target) - return; - - m_conn = QObject::connect(m_emitter.data(), m_signal, m_target.data(), m_slot, connectionType); - Q_ASSERT(m_conn); - } - - void disconnect() override - { - Q_ASSERT(m_connected); - - if (m_conn) - QObject::disconnect(m_conn); - - m_connected = false; - } - -private: - bool m_connected{false}; - QPointer m_emitter; - Signal m_signal; - QPointer m_target; - Slot m_slot; - QMetaObject::Connection m_conn; -}; - - - -template -Connection* createConnection(typename detail::ExtractClass::type *emitter, Signal signal, - typename detail::ExtractClass::type *target, Slot slot) -{ - return new Connection(emitter, signal, target, slot); -} - -} + + +#pragma once + +#include +#include +#include +#include +#include + +namespace LtsUtils { + +class IConnection { +public: + virtual ~IConnection() = default; + virtual void connect(Qt::ConnectionType = Qt::AutoConnection) = 0; + virtual void disconnect() = 0; +}; + +class DummyConnection : public IConnection { +public: + void connect(Qt::ConnectionType = Qt::AutoConnection) override {} + void disconnect() override {} +}; + +namespace detail { + +template struct ExtractClass; + +template struct ExtractClass { + using type = T; +}; + +} // namespace detail + +template class Connection : public IConnection { + static_assert(std::is_member_function_pointer_v, + "Must be a pointer to method"); + static_assert(std::is_member_function_pointer_v, + "Must be a pointer to method"); + + using Emitter = typename detail::ExtractClass::type; + using Target = typename detail::ExtractClass::type; + + static_assert(std::is_base_of_v, + "Must be derived from QObject"); + static_assert(std::is_base_of_v, + "Must be derived from QObject"); + +public: + Connection(Emitter *emitter, Signal signal, Target *target, Slot slot) + : m_emitter(emitter), m_signal(signal), m_target(target), m_slot(slot) { + Q_ASSERT(emitter); + Q_ASSERT(signal); + Q_ASSERT(target); + Q_ASSERT(slot); + } + + void + connect(Qt::ConnectionType connectionType = Qt::AutoConnection) override { + Q_ASSERT(!m_connected); + + m_connected = true; + + if (!m_emitter || !m_target) + return; + + m_conn = QObject::connect(m_emitter.data(), m_signal, m_target.data(), + m_slot, connectionType); + Q_ASSERT(m_conn); + } + + void disconnect() override { + Q_ASSERT(m_connected); + + if (m_conn) + QObject::disconnect(m_conn); + + m_connected = false; + } + +private: + bool m_connected{false}; + QPointer m_emitter; + Signal m_signal; + QPointer m_target; + Slot m_slot; + QMetaObject::Connection m_conn; +}; + +template +Connection * +createConnection(typename detail::ExtractClass::type *emitter, + Signal signal, + typename detail::ExtractClass::type *target, Slot slot) { + return new Connection(emitter, signal, target, slot); +} + +} // namespace LtsUtils diff --git a/Lts/Common/LtsUtils/LtsUtilsCore/dds_vector.h b/Lts/Common/LtsUtils/LtsUtilsCore/dds_vector.h old mode 100755 new mode 100644 index 7d92a2f23..232831401 --- a/Lts/Common/LtsUtils/LtsUtilsCore/dds_vector.h +++ b/Lts/Common/LtsUtils/LtsUtilsCore/dds_vector.h @@ -1,43 +1,35 @@ - - - -#pragma once - -#include -#include - -namespace LtsUtils -{ - -template -inline void convert(const S &in, T &out) -{ - static_assert(!std::is_same::value, "Try to convert a type to the same type - is useless"); - out.reserve(static_cast(in.size())); - std::copy(in.begin(), in.end(), std::back_inserter(out)); -} - -template -inline T convert(const S &in) -{ - static_assert(!std::is_same::value, "Try to convert a type to the same type - is useless"); - T out; - convert(in, out); - return out; -} - - -template -inline QByteArray toQByteArray(const T &in) -{ - return convert(in); -} - -template -bool isInVector(const T &vec, const V &valueToSearch) -{ - const auto end = vec.end(); - return std::find(vec.begin(), end, valueToSearch) != end; -} - -} + + +#pragma once + +#include +#include + +namespace LtsUtils { + +template inline void convert(const S &in, T &out) { + static_assert(!std::is_same_v, + "Try to convert a type to the same type - is useless"); + out.reserve(static_cast(in.size())); + std::copy(in.begin(), in.end(), std::back_inserter(out)); +} + +template inline T convert(const S &in) { + static_assert(!std::is_same_v, + "Try to convert a type to the same type - is useless"); + T out; + convert(in, out); + return out; +} + +template inline QByteArray toQByteArray(const T &in) { + return convert(in); +} + +template +bool isInVector(const T &vec, const V &valueToSearch) { + const auto end = vec.end(); + return std::find(vec.begin(), end, valueToSearch) != end; +} + +} // namespace LtsUtils diff --git a/Lts/Common/LtsUtils/LtsUtilsCore/json_object.h b/Lts/Common/LtsUtils/LtsUtilsCore/json_object.h old mode 100755 new mode 100644 index b896ef56d..ec73d43f1 --- a/Lts/Common/LtsUtils/LtsUtilsCore/json_object.h +++ b/Lts/Common/LtsUtils/LtsUtilsCore/json_object.h @@ -1,696 +1,519 @@ - - - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace LtsUtils -{ - -class JsonParseError : public std::runtime_error -{ -public: - JsonParseError(const QJsonParseError &err) - : std::runtime_error("json parse error: " + err.errorString().toStdString() + " - at offset " + std::to_string(err.offset)){} -}; - -class JsonError : public std::runtime_error -{ -public: - using std::runtime_error::runtime_error; -}; - -class JsonKeyError : public JsonError -{ -public: - using JsonError::JsonError; -}; - -class JsonRangeError : public JsonError -{ -public: - using JsonError::JsonError; -}; - -class JsonTypeError : public JsonError -{ -public: - using JsonError::JsonError; -}; - - - - -class JsonObject -{ -public: - - - class Key; - - JsonObject() = default; - explicit JsonObject(const QJsonObject &json) - : m_json(json) - , m_jsonIsSet(true) - {} - - explicit JsonObject(QJsonObject &&json) - : m_json(std::move(json)) - , m_jsonIsSet(true) - {} - - - - - - - - - - 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 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 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 - bool contains(const Key &key) const; - - bool isNull(const Key &key) const { return contains(key); } - - bool isEmpty() const { return m_json.isEmpty(); } - bool isValid() const { return m_jsonIsSet; } - - - - template - T value(const Key &key) const noexcept(false); - - - - template - T valueOr(const Key &key, const T &defaultValue) const noexcept(false); - - - - - template - bool isMap() const; - - - - template - QMap toMap() const noexcept(false); - - - template - std::map toStdMap() const; - - bool operator==(const JsonObject &other) const { return m_json == other.m_json; } - bool operator!=(const JsonObject &other) const { return !(*this == other); } - - class Key - { - public: - Key(const QString &s) - : m_s(s) - {} - - Key(const std::string &s) - : m_s(QString::fromStdString(s)) - {} - - Key(const char *s) - : m_s(QString::fromUtf8(s)) - {} - - operator const QString &() const { return m_s; } - - private: - const QString m_s; - }; - - operator const QJsonObject &() const { return m_json; } - const QJsonObject &object() const { return m_json; } - -private: - bool containsAny(const QString &key) const { return m_json.contains(key); } - - QJsonObject m_json; - bool m_jsonIsSet = false; -}; - -JsonObject JsonObject::fromJson(const char *json, int len) -{ - if (len < 0) - len = strlen(json); - QJsonParseError error; - const auto doc = QJsonDocument::fromJson(QByteArray::fromRawData(json, len), &error); - if (error.error != QJsonParseError::NoError) - return JsonObject(); - - if (!doc.isObject()) - return JsonObject(); - - return JsonObject(doc.object()); -} - -JsonObject JsonObject::fromJsonSafe(const char *json, int len) noexcept(false) -{ - if (len < 0) - len = strlen(json); - QJsonParseError error; - const auto doc = QJsonDocument::fromJson(QByteArray::fromRawData(json, len), &error); - if (error.error != QJsonParseError::NoError) - throw JsonParseError(error); - - if (!doc.isObject()) - throw JsonTypeError("JSON root is not an object"); - - return JsonObject(doc.object()); -} - - - - - -class JsonArray -{ -public: - JsonArray() = default; - explicit JsonArray(const QJsonArray &json) - : m_json(json) - , m_jsonIsSet(true) - {} - - explicit JsonArray(QJsonArray &&json) - : m_json(std::move(json)) - , m_jsonIsSet(true) - {} - - - - - - - - - - - - - - - - - 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 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 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()); } - - - int size() const { return m_json.size(); } - bool isEmpty() const { return m_json.isEmpty(); } - bool isValid() const { return m_jsonIsSet; } - - - template - bool contains(int index) const noexcept(false); - - - bool isNull(int index) const noexcept(false) { return contains(index); } - - - template - T at(int index) const noexcept(false); - - - - template - bool isVector() const; - - - - template - QVector toVector() const noexcept(false); - - template - std::vector toStdVector() const; - - bool operator==(const JsonArray &other) const { return m_json == other.m_json; } - bool operator!=(const JsonArray &other) const { return !(*this == other); } - - const QJsonArray &operator()() const { return m_json; } -private: - QJsonArray m_json; - bool m_jsonIsSet = false; -}; - -JsonArray JsonArray::fromJson(const char *json, int len) -{ - if (len < 0) - len = strlen(json); - QJsonParseError error; - QJsonDocument doc = QJsonDocument::fromJson(QByteArray::fromRawData(json, len), &error); - if (error.error != QJsonParseError::NoError) - return JsonArray(); - - if (!doc.isArray()) - return JsonArray(); - - return JsonArray(doc.array()); -} - -JsonArray JsonArray::fromJsonSafe(const char *json, int len) noexcept(false) -{ - if (len < 0) - len = strlen(json); - QJsonParseError error; - const auto doc = QJsonDocument::fromJson(QByteArray::fromRawData(json, len), &error); - if (error.error != QJsonParseError::NoError) - throw JsonParseError(error); - - if (!doc.isArray()) - throw JsonTypeError("JSON root is not an array"); - - return JsonArray(doc.array()); -} - - - - - -template -struct JsonValue; - - - -template -struct JsonLimits -{ - static constexpr Int lowest() { return std::numeric_limits::lowest(); } - static constexpr Int max() { return std::numeric_limits::max(); } -}; - - - -template<> -struct JsonLimits -{ - static constexpr int64_t lowest() { return -(static_cast(1) << 53) + 1; } - static constexpr int64_t max() { return (static_cast(1) << 53) - 1; } -}; - - - -template<> -struct JsonLimits -{ - static constexpr uint64_t lowest() { return 0; } - static constexpr uint64_t max() { return JsonLimits::max(); } -}; - - - -template -struct JsonIntValue -{ - static bool matchesType(const QJsonValue &value) - { - if (!value.isDouble()) - return false; - double val = value.toDouble(); - - if (val < JsonLimits::lowest()) - return false; - if (val > JsonLimits::max()) - return false; - - double wholeInt = static_cast(val); - return val == wholeInt; - } - - static Int value(const QJsonValue &value) noexcept(false) - { - if (!matchesType(value)) - throw JsonTypeError("JSON value not of type Int"); - return static_cast(value.toDouble()); - } -}; - - - - -template<> -struct JsonValue : JsonIntValue -{}; - -template<> -struct JsonValue : JsonIntValue -{}; - -template<> -struct JsonValue : JsonIntValue -{}; - -template<> -struct JsonValue : JsonIntValue -{}; - -template<> -struct JsonValue : JsonIntValue -{}; - -template<> -struct JsonValue : JsonIntValue -{}; - - - - -template<> -struct JsonValue -{ - static bool matchesType(const QJsonValue &value) { return value.isDouble(); } - - static double value(const QJsonValue &value) noexcept(false) - { - if (!matchesType(value)) - throw JsonTypeError("JSON value not of type Double"); - return value.toDouble(); - } -}; - - - -template<> -struct JsonValue -{ - static bool matchesType(const QJsonValue &value) { return value.isBool(); } - - static bool value(const QJsonValue &value) noexcept(false) - { - if (!matchesType(value)) - throw JsonTypeError("JSON value not of type Bool"); - return value.toBool(); - } -}; - - - -template<> -struct JsonValue -{ - static bool matchesType(const QJsonValue &value) { return value.isString(); } - - static QString value(const QJsonValue &value) noexcept(false) - { - if (!matchesType(value)) - throw JsonTypeError("JSON value not of type String"); - return value.toString(); - } -}; - - - -template<> -struct JsonValue -{ - static bool matchesType(const QJsonValue &value) { return value.isString(); } - - static std::string value(const QJsonValue &value) - { - return JsonValue::value(value).toStdString(); - } -}; - - - -template<> -struct JsonValue -{ - static bool matchesType(const QJsonValue &value) { return value.isObject(); } - - static QJsonObject value(const QJsonValue &value) noexcept(false) - { - if (!matchesType(value)) - throw JsonTypeError("JSON value not of type Object"); - return value.toObject(); - } -}; - - - -template<> -struct JsonValue -{ - static bool matchesType(const QJsonValue &value) { return value.isObject(); } - static JsonObject value(const QJsonValue &value) { return JsonObject(JsonValue::value(value)); } -}; - - - -template<> -struct JsonValue -{ - static bool matchesType(const QJsonValue &value) { return value.isNull(); } -}; - - - -template<> -struct JsonValue -{ - static bool matchesType(const QJsonValue &value) { return value.isArray(); } - - static QJsonArray value(const QJsonValue &value) noexcept(false) - { - if (!matchesType(value)) - throw JsonTypeError("JSON value not of type Array"); - return value.toArray(); - } -}; - - - -template<> -struct JsonValue -{ - static bool matchesType(const QJsonValue &value) { return value.isArray(); } - static JsonArray value(const QJsonValue &value) { return JsonArray(JsonValue::value(value)); } -}; - - - -template -struct JsonValue> -{ - static bool matchesType(const QJsonValue &value) - { - if (!value.isArray()) - return false; - - const JsonArray array(value.toArray()); - return array.isVector(); - } - - static QVector value(const QJsonValue &value) - { - const JsonArray array(JsonValue::value(value)); - return array.toVector(); - } -}; - - - -template -struct JsonValue> -{ - static bool matchesType(const QJsonValue &value) - { - return JsonValue>::matchesType(value); - } - - static std::vector value(const QJsonValue &value) - { - const JsonArray array(JsonValue::value(value)); - return array.toStdVector(); - } -}; - - - -template -struct JsonValue> -{ - static bool matchesType(const QJsonValue &value) - { - if (!value.isObject()) - return false; - - const JsonObject obj(JsonValue::value(value)); - return obj.isMap(); - } - - static QMap value(const QJsonValue &value) - { - const JsonObject obj(JsonValue::value(value)); - return obj.toMap(); - } -}; - - - -template -struct JsonValue> -{ - static bool matchesType(const QJsonValue &value) - { - return JsonValue>::matchesType(value); - } - - static std::map value(const QJsonValue &value) - { - const JsonObject obj(JsonValue::value(value)); - return obj.toStdMap(); - } -}; - - - -template -bool JsonObject::contains(const Key &key) const -{ - if (!m_json.contains(key)) - return false; - return JsonValue::matchesType(m_json.value(key)); -} - -template -T JsonObject::value(const Key &key) const noexcept(false) -{ - if (!containsAny(key)) - throw JsonKeyError("no element with key: " + static_cast(key).toStdString()); - try - { - return JsonValue::value(m_json.value(key)); - } - catch(const JsonTypeError &typeError) - { - throw JsonTypeError(std::string(typeError.what()) + " - key: " + static_cast(key).toStdString()); - } -} - -template -T JsonObject::valueOr(const Key &key, const T &defaultValue) const -{ - try - { - return value(key); - } - - catch (const JsonKeyError &) - { - return defaultValue; - } -} - -template -bool JsonObject::isMap() const -{ - const QStringList keys = m_json.keys(); - for (const auto &key : keys) - if (!JsonValue::matchesType(m_json.value(key))) - return false; - - return true; -} - -template -QMap JsonObject::toMap() const -{ - QMap result; - for (auto current = m_json.begin(); current != m_json.end(); ++current) - result.insert(current.key(), JsonValue::value(current.value())); - return result; -} - -template -std::map JsonObject::toStdMap() const -{ - std::map result; - for (auto current = m_json.begin(); current != m_json.end(); ++current) - result.insert({current.key().toStdString(), JsonValue::value(current.value())}); - return result; -} - - - -template -bool JsonArray::contains(int index) const noexcept(false) -{ - if (index < 0 || index >= m_json.size()) - throw JsonRangeError("index out of range: " + std::to_string(index)); - return JsonValue::matchesType(m_json.at(index)); -} - -template -T JsonArray::at(int index) const noexcept(false) -{ - if (index < 0 || index >= m_json.size()) - throw JsonRangeError("index out of range: " + std::to_string(index)); - return JsonValue::value(m_json.at(index)); -} - -template -bool JsonArray::isVector() const -{ - for (const QJsonValue &value : m_json) - if (!JsonValue::matchesType(value)) - return false; - return true; -} - -template -QVector JsonArray::toVector() const -{ - QVector result; - result.reserve(m_json.size()); - for (const QJsonValue &value : m_json) - result.push_back(JsonValue::value(value)); - return result; -} - -template -std::vector JsonArray::toStdVector() const -{ - std::vector result; - result.reserve(m_json.size()); - for (const QJsonValue &value : m_json) - result.push_back(JsonValue::value(value)); - return result; -} - -} + + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace LtsUtils { + +class JsonParseError : public std::runtime_error { +public: + JsonParseError(const QJsonParseError &err) + : std::runtime_error( + "json parse error: " + err.errorString().toStdString() + + " - at offset " + std::to_string(err.offset)) {} +}; + +class JsonError : public std::runtime_error { +public: + using std::runtime_error::runtime_error; +}; + +class JsonKeyError : public JsonError { +public: + using JsonError::JsonError; +}; + +class JsonRangeError : public JsonError { +public: + using JsonError::JsonError; +}; + +class JsonTypeError : public JsonError { +public: + using JsonError::JsonError; +}; + +class JsonObject { +public: + class Key; + + JsonObject() = default; + explicit JsonObject(const QJsonObject &json) + : m_json(json), m_jsonIsSet(true) {} + + explicit JsonObject(QJsonObject &&json) + : m_json(std::move(json)), m_jsonIsSet(true) {} + + 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 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 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 [[nodiscard]] bool contains(const Key &key) const; + + [[nodiscard]] bool isNull(const Key &key) const { + return contains(key); + } + + [[nodiscard]] bool isEmpty() const { return m_json.isEmpty(); } + [[nodiscard]] bool isValid() const { return m_jsonIsSet; } + + template T value(const Key &key) const noexcept(false); + + template + T valueOr(const Key &key, const T &defaultValue) const noexcept(false); + + template [[nodiscard]] bool isMap() const; + + template QMap toMap() const noexcept(false); + + template std::map toStdMap() const; + + bool operator==(const JsonObject &other) const { + return m_json == other.m_json; + } + bool operator!=(const JsonObject &other) const { return !(*this == other); } + + class Key { + public: + Key(QString s) : m_s(std::move(s)) {} + + Key(const std::string &s) : m_s(QString::fromStdString(s)) {} + + Key(const char *s) : m_s(QString::fromUtf8(s)) {} + + operator const QString &() const { return m_s; } + + private: + const QString m_s; + }; + + operator const QJsonObject &() const { return m_json; } + [[nodiscard]] const QJsonObject &object() const { return m_json; } + +private: + [[nodiscard]] bool containsAny(const QString &key) const { + return m_json.contains(key); + } + + QJsonObject m_json; + bool m_jsonIsSet = false; +}; + +JsonObject JsonObject::fromJson(const char *json, int len) { + if (len < 0) + len = strlen(json); + QJsonParseError error; + const auto doc = + QJsonDocument::fromJson(QByteArray::fromRawData(json, len), &error); + if (error.error != QJsonParseError::NoError) + return {}; + + if (!doc.isObject()) + return {}; + + return JsonObject(doc.object()); +} + +JsonObject JsonObject::fromJsonSafe(const char *json, int len) noexcept(false) { + if (len < 0) + len = strlen(json); + QJsonParseError error; + const auto doc = + QJsonDocument::fromJson(QByteArray::fromRawData(json, len), &error); + if (error.error != QJsonParseError::NoError) + throw JsonParseError(error); + + if (!doc.isObject()) + throw JsonTypeError("JSON root is not an object"); + + return JsonObject(doc.object()); +} + +class JsonArray { +public: + JsonArray() = default; + explicit JsonArray(const QJsonArray &json) + : m_json(json), m_jsonIsSet(true) {} + + explicit JsonArray(QJsonArray &&json) + : m_json(std::move(json)), m_jsonIsSet(true) {} + + 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 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 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; } + + template + [[nodiscard]] bool contains(int index) const noexcept(false); + + [[nodiscard]] bool isNull(int index) const noexcept(false) { + return contains(index); + } + + template T at(int index) const noexcept(false); + + template [[nodiscard]] bool isVector() const; + + template QVector toVector() const noexcept(false); + + template std::vector toStdVector() const; + + bool operator==(const JsonArray &other) const { + return m_json == other.m_json; + } + bool operator!=(const JsonArray &other) const { return !(*this == other); } + + const QJsonArray &operator()() const { return m_json; } + +private: + QJsonArray m_json; + bool m_jsonIsSet = false; +}; + +JsonArray JsonArray::fromJson(const char *json, int len) { + if (len < 0) + len = strlen(json); + QJsonParseError error; + QJsonDocument doc = + QJsonDocument::fromJson(QByteArray::fromRawData(json, len), &error); + if (error.error != QJsonParseError::NoError) + return {}; + + if (!doc.isArray()) + return {}; + + return JsonArray(doc.array()); +} + +JsonArray JsonArray::fromJsonSafe(const char *json, int len) noexcept(false) { + if (len < 0) + len = strlen(json); + QJsonParseError error; + const auto doc = + QJsonDocument::fromJson(QByteArray::fromRawData(json, len), &error); + if (error.error != QJsonParseError::NoError) + throw JsonParseError(error); + + if (!doc.isArray()) + throw JsonTypeError("JSON root is not an array"); + + return JsonArray(doc.array()); +} + +template struct JsonValue; + +template struct JsonLimits { + static constexpr Int lowest() { return std::numeric_limits::lowest(); } + static constexpr Int max() { return std::numeric_limits::max(); } +}; + +template <> struct JsonLimits { + static constexpr int64_t lowest() { + return -(static_cast(1) << 53) + 1; + } + static constexpr int64_t max() { return (static_cast(1) << 53) - 1; } +}; + +template <> struct JsonLimits { + static constexpr uint64_t lowest() { return 0; } + static constexpr uint64_t max() { return JsonLimits::max(); } +}; + +template struct JsonIntValue { + static bool matchesType(const QJsonValue &value) { + if (!value.isDouble()) + return false; + double val = value.toDouble(); + + if (val < JsonLimits::lowest()) + return false; + if (val > JsonLimits::max()) + return false; + + double wholeInt = static_cast(val); + return val == wholeInt; + } + + static Int value(const QJsonValue &value) noexcept(false) { + if (!matchesType(value)) + throw JsonTypeError("JSON value not of type Int"); + return static_cast(value.toDouble()); + } +}; + +template <> struct JsonValue : JsonIntValue {}; + +template <> struct JsonValue : JsonIntValue {}; + +template <> struct JsonValue : JsonIntValue {}; + +template <> struct JsonValue : JsonIntValue {}; + +template <> struct JsonValue : JsonIntValue {}; + +template <> struct JsonValue : JsonIntValue {}; + +template <> struct JsonValue { + static bool matchesType(const QJsonValue &value) { return value.isDouble(); } + + static double value(const QJsonValue &value) noexcept(false) { + if (!matchesType(value)) + throw JsonTypeError("JSON value not of type Double"); + return value.toDouble(); + } +}; + +template <> struct JsonValue { + static bool matchesType(const QJsonValue &value) { return value.isBool(); } + + static bool value(const QJsonValue &value) noexcept(false) { + if (!matchesType(value)) + throw JsonTypeError("JSON value not of type Bool"); + return value.toBool(); + } +}; + +template <> struct JsonValue { + static bool matchesType(const QJsonValue &value) { return value.isString(); } + + static QString value(const QJsonValue &value) noexcept(false) { + if (!matchesType(value)) + throw JsonTypeError("JSON value not of type String"); + return value.toString(); + } +}; + +template <> struct JsonValue { + static bool matchesType(const QJsonValue &value) { return value.isString(); } + + static std::string value(const QJsonValue &value) { + return JsonValue::value(value).toStdString(); + } +}; + +template <> struct JsonValue { + static bool matchesType(const QJsonValue &value) { return value.isObject(); } + + static QJsonObject value(const QJsonValue &value) noexcept(false) { + if (!matchesType(value)) + throw JsonTypeError("JSON value not of type Object"); + return value.toObject(); + } +}; + +template <> struct JsonValue { + static bool matchesType(const QJsonValue &value) { return value.isObject(); } + static JsonObject value(const QJsonValue &value) { + return JsonObject(JsonValue::value(value)); + } +}; + +template <> struct JsonValue { + static bool matchesType(const QJsonValue &value) { return value.isNull(); } +}; + +template <> struct JsonValue { + static bool matchesType(const QJsonValue &value) { return value.isArray(); } + + static QJsonArray value(const QJsonValue &value) noexcept(false) { + if (!matchesType(value)) + throw JsonTypeError("JSON value not of type Array"); + return value.toArray(); + } +}; + +template <> struct JsonValue { + static bool matchesType(const QJsonValue &value) { return value.isArray(); } + static JsonArray value(const QJsonValue &value) { + return JsonArray(JsonValue::value(value)); + } +}; + +template struct JsonValue> { + static bool matchesType(const QJsonValue &value) { + if (!value.isArray()) + return false; + + const JsonArray array(value.toArray()); + return array.isVector(); + } + + static QVector value(const QJsonValue &value) { + const JsonArray array(JsonValue::value(value)); + return array.toVector(); + } +}; + +template struct JsonValue> { + static bool matchesType(const QJsonValue &value) { + return JsonValue>::matchesType(value); + } + + static std::vector value(const QJsonValue &value) { + const JsonArray array(JsonValue::value(value)); + return array.toStdVector(); + } +}; + +template struct JsonValue> { + static bool matchesType(const QJsonValue &value) { + if (!value.isObject()) + return false; + + const JsonObject obj(JsonValue::value(value)); + return obj.isMap(); + } + + static QMap value(const QJsonValue &value) { + const JsonObject obj(JsonValue::value(value)); + return obj.toMap(); + } +}; + +template struct JsonValue> { + static bool matchesType(const QJsonValue &value) { + return JsonValue>::matchesType(value); + } + + static std::map value(const QJsonValue &value) { + const JsonObject obj(JsonValue::value(value)); + return obj.toStdMap(); + } +}; + +template bool JsonObject::contains(const Key &key) const { + if (!m_json.contains(key)) + return false; + return JsonValue::matchesType(m_json.value(key)); +} + +template T JsonObject::value(const Key &key) const noexcept(false) { + if (!containsAny(key)) + throw JsonKeyError("no element with key: " + + static_cast(key).toStdString()); + try { + return JsonValue::value(m_json.value(key)); + } catch (const JsonTypeError &typeError) { + throw JsonTypeError(std::string(typeError.what()) + " - key: " + + static_cast(key).toStdString()); + } +} + +template +T JsonObject::valueOr(const Key &key, const T &defaultValue) const { + try { + return value(key); + } + + catch (const JsonKeyError &) { + return defaultValue; + } +} + +template bool JsonObject::isMap() const { + const QStringList keys = m_json.keys(); + for (const auto &key : keys) + if (!JsonValue::matchesType(m_json.value(key))) + return false; + + return true; +} + +template QMap JsonObject::toMap() const { + QMap result; + for (auto current = m_json.begin(); current != m_json.end(); ++current) + result.insert(current.key(), JsonValue::value(current.value())); + return result; +} + +template std::map JsonObject::toStdMap() const { + std::map result; + for (auto current = m_json.begin(); current != m_json.end(); ++current) + result.insert( + {current.key().toStdString(), JsonValue::value(current.value())}); + return result; +} + +template bool JsonArray::contains(int index) const noexcept(false) { + if (index < 0 || index >= m_json.size()) + throw JsonRangeError("index out of range: " + std::to_string(index)); + return JsonValue::matchesType(m_json.at(index)); +} + +template T JsonArray::at(int index) const noexcept(false) { + if (index < 0 || index >= m_json.size()) + throw JsonRangeError("index out of range: " + std::to_string(index)); + return JsonValue::value(m_json.at(index)); +} + +template bool JsonArray::isVector() const { + for (const QJsonValue &value : m_json) + if (!JsonValue::matchesType(value)) + return false; + return true; +} + +template QVector JsonArray::toVector() const { + QVector result; + result.reserve(m_json.size()); + for (const QJsonValue &value : m_json) + result.push_back(JsonValue::value(value)); + return result; +} + +template std::vector JsonArray::toStdVector() const { + std::vector result; + result.reserve(m_json.size()); + for (const QJsonValue &value : m_json) + result.push_back(JsonValue::value(value)); + return result; +} + +} // namespace LtsUtils diff --git a/Lts/Common/LtsUtils/LtsUtilsCore/pgarray.h b/Lts/Common/LtsUtils/LtsUtilsCore/pgarray.h old mode 100755 new mode 100644 index ddafb4f9a..d40eb48a1 --- a/Lts/Common/LtsUtils/LtsUtilsCore/pgarray.h +++ b/Lts/Common/LtsUtils/LtsUtilsCore/pgarray.h @@ -1,45 +1,34 @@ - - - -#pragma once -#include -#include -#include -#include - -namespace LtsUtils -{ - -template -class PgArray -{ -public: - using Type = T; - using ContainerType = C; - - PgArray() = default; - Q_DECL_CONSTEXPR explicit PgArray(const C &data) - : m_data(data) - {} - - Q_DECL_CONSTEXPR C operator()()const - { - return m_data; - } - - QString toPgString() const; - static PgArray fromPgString(const QString &str); -private: - C m_data; -}; - - - -using IntArray = PgArray>; -using BigintArray = PgArray>; - - -using IntArray2D = PgArray>; -using BigintArray2D = PgArray>; - -} + + +#pragma once +#include +#include +#include +#include + +namespace LtsUtils { + +template class PgArray { +public: + using Type = T; + using ContainerType = C; + + PgArray() = default; + Q_DECL_CONSTEXPR explicit PgArray(const C &data) : m_data(data) {} + + Q_DECL_CONSTEXPR C operator()() const { return m_data; } + + [[nodiscard]] QString toPgString() const; + static PgArray fromPgString(const QString &str); + +private: + C m_data; +}; + +using IntArray = PgArray>; +using BigintArray = PgArray>; + +using IntArray2D = PgArray>; +using BigintArray2D = PgArray>; + +} // namespace LtsUtils diff --git a/Lts/Common/LtsUtils/LtsUtilsCore/promise_examples.h b/Lts/Common/LtsUtils/LtsUtilsCore/promise_examples.h old mode 100755 new mode 100644 index 9edb31123..234df6bb5 --- a/Lts/Common/LtsUtils/LtsUtilsCore/promise_examples.h +++ b/Lts/Common/LtsUtils/LtsUtilsCore/promise_examples.h @@ -1,70 +1,54 @@ -#pragma once - - -#include - - -namespace LtsUtils -{ - - -class PromiseExample1_Class : public QObject -{ - Q_OBJECT -public: - using QObject::QObject; - - void doSomethingAsync1(); - void doSomethingAsync2(); - -signals: - void signalDone1(bool didThisWork); - void signalDone2(bool didThisWork, int someNumberThatReturns); -}; - - -class PromiseExample1 : public QObject -{ - Q_OBJECT -public: - explicit PromiseExample1(QObject *parent = nullptr); - - bool isSuccess() const { return m_success; } - -private: - bool m_success; -}; - - - - -class PromiseExample2 : public QObject -{ - Q_OBJECT -public: - explicit PromiseExample2(QObject *parent = nullptr); - - bool isSuccess() const { return m_success; } - -private: - bool m_success; -}; - - - - -class PromiseExample3 : public QObject -{ - Q_OBJECT -public: - explicit PromiseExample3(QObject *parent = nullptr); - - bool isSuccess() const { return m_success; } - -private: - bool m_success; - bool m_alreadyRejected; -}; - - -} +#pragma once + +#include + +namespace LtsUtils { + +class PromiseExample1_Class : public QObject { + Q_OBJECT +public: + using QObject::QObject; + + void doSomethingAsync1(); + void doSomethingAsync2(); + +signals: + void signalDone1(bool didThisWork); + void signalDone2(bool didThisWork, int someNumberThatReturns); +}; + +class PromiseExample1 : public QObject { + Q_OBJECT +public: + explicit PromiseExample1(QObject *parent = nullptr); + + [[nodiscard]] bool isSuccess() const { return m_success; } + +private: + bool m_success; +}; + +class PromiseExample2 : public QObject { + Q_OBJECT +public: + explicit PromiseExample2(QObject *parent = nullptr); + + [[nodiscard]] bool isSuccess() const { return m_success; } + +private: + bool m_success; +}; + +class PromiseExample3 : public QObject { + Q_OBJECT +public: + explicit PromiseExample3(QObject *parent = nullptr); + + [[nodiscard]] bool isSuccess() const { return m_success; } + +private: + bool m_success; + bool m_alreadyRejected; +}; + +} // namespace LtsUtils diff --git a/Lts/Common/LtsUtils/LtsUtilsCore/qbytearray_byteaccess.h b/Lts/Common/LtsUtils/LtsUtilsCore/qbytearray_byteaccess.h old mode 100755 new mode 100644 index 99d16f47f..51956975a --- a/Lts/Common/LtsUtils/LtsUtilsCore/qbytearray_byteaccess.h +++ b/Lts/Common/LtsUtils/LtsUtilsCore/qbytearray_byteaccess.h @@ -1,282 +1,241 @@ - - - -#pragma once - -#include -#include - -namespace LtsUtils -{ - - - - template - void inline set8Byte(const T in, QByteArray& out) - { - static_assert(std::is_integral::value || std::is_enum::value, "Only integrals allowed for raw byte accessd"); - out += (in & 0xFF00000000000000UL) >> 56; - out += (in & 0x00FF000000000000UL) >> 48; - out += (in & 0x0000FF0000000000UL) >> 40; - out += (in & 0x000000FF00000000UL) >> 32; - out += (in & 0x00000000FF000000UL) >> 24; - 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 - bool inline get8Byte(const QByteArray& baData, - size_t &pos, - T& out) - { - static_assert(std::is_integral::value || std::is_enum::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::is_signed) - out |= static_cast(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 - bool inline get8Byte(const QByteArray& data, T& out) - { - size_t pos = 0; - return get8Byte(data, pos, out); - } - - - template - void inline set4Byte(const T in, QByteArray& out) - { - static_assert(std::is_integral::value || std::is_enum::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 - bool inline get4Byte(const QByteArray& baData, - size_t &pos, - T& out) - { - static_assert(std::is_integral::value || std::is_enum::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::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 - bool inline get4Byte(const QByteArray& data, T& out) - { - size_t pos = 0; - return get4Byte(data, pos, out); - } - - - template - void inline set3Byte(const T in, QByteArray& out) - { - static_assert(std::is_integral::value || std::is_enum::value, "Only integrals allowed for raw byte accessd"); - out += (in & 0x00FF0000) >> 16; - out += (in & 0x0000FF00) >> 8; - out += (in & 0x000000FF); - } - - template - bool inline get3Byte(const QByteArray& baData, - size_t &pos, - T& out) - { - static_assert(std::is_integral::value || std::is_enum::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::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 - bool inline get3Byte(const QByteArray& data, T& out) - { - size_t pos = 0; - return get3Byte(data, pos, out); - } - - - template - void inline set2Byte(const T in, QByteArray& out) - { - static_assert(std::is_integral::value || std::is_enum::value, "Only integrals allowed for raw byte accessd"); - out += (in & 0x0000FF00) >> 8; - out += (in & 0x000000FF); - } - - template - bool inline get2Byte(const QByteArray& baData, - size_t &pos, - T& out) - { - static_assert(std::is_integral::value || std::is_enum::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::is_signed) - out |= data[0] << 8; - else - out |= (data[0] & 0xFFU) << 8; - out |= data[1] & 0xFFU; - - pos += 2; - - return true; - } - - template - bool inline get2Byte(const QByteArray& data, T& out) - { - size_t pos = 0; - return get2Byte(data, pos, out); - } - - - template - void inline set1Byte(const T in, QByteArray& out) - { - static_assert(std::is_integral::value || std::is_enum::value, "Only integrals allowed for raw byte accessd"); - unsigned char c = in; - out += c; - } - - template - bool inline get1Byte(const QByteArray& baData, - size_t &pos, - T& out) - { - static_assert(std::is_integral::value || std::is_enum::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::is_signed) - out = (T)(data[0]); - else - out = (T)(data[0] & 0xFF); - - pos += 1; - - return true; - } - - template - bool inline get1Byte(const QByteArray& data, T& out) - { - size_t pos = 0; - return get1Byte(data, pos, out); - } -} + + +#pragma once + +#include +#include + +namespace LtsUtils { + +template void inline set8Byte(const T in, QByteArray &out) { + static_assert(std::is_integral_v || std::is_enum_v, + "Only integrals allowed for raw byte accessd"); + out += (in & 0xFF00000000000000UL) >> 56; + out += (in & 0x00FF000000000000UL) >> 48; + out += (in & 0x0000FF0000000000UL) >> 40; + out += (in & 0x000000FF00000000UL) >> 32; + out += (in & 0x00000000FF000000UL) >> 24; + 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 +bool inline get8Byte(const QByteArray &baData, size_t &pos, T &out) { + static_assert(std::is_integral_v || std::is_enum_v, + "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::is_signed) + out |= static_cast(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 bool inline get8Byte(const QByteArray &data, T &out) { + size_t pos = 0; + return get8Byte(data, pos, out); +} + +template void inline set4Byte(const T in, QByteArray &out) { + static_assert(std::is_integral_v || std::is_enum_v, + "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 +bool inline get4Byte(const QByteArray &baData, size_t &pos, T &out) { + static_assert(std::is_integral_v || std::is_enum_v, + "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::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 bool inline get4Byte(const QByteArray &data, T &out) { + size_t pos = 0; + return get4Byte(data, pos, out); +} + +template void inline set3Byte(const T in, QByteArray &out) { + static_assert(std::is_integral_v || std::is_enum_v, + "Only integrals allowed for raw byte accessd"); + out += (in & 0x00FF0000) >> 16; + out += (in & 0x0000FF00) >> 8; + out += (in & 0x000000FF); +} + +template +bool inline get3Byte(const QByteArray &baData, size_t &pos, T &out) { + static_assert(std::is_integral_v || std::is_enum_v, + "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::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 bool inline get3Byte(const QByteArray &data, T &out) { + size_t pos = 0; + return get3Byte(data, pos, out); +} + +template void inline set2Byte(const T in, QByteArray &out) { + static_assert(std::is_integral_v || std::is_enum_v, + "Only integrals allowed for raw byte accessd"); + out += (in & 0x0000FF00) >> 8; + out += (in & 0x000000FF); +} + +template +bool inline get2Byte(const QByteArray &baData, size_t &pos, T &out) { + static_assert(std::is_integral_v || std::is_enum_v, + "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::is_signed) + out |= data[0] << 8; + else + out |= (data[0] & 0xFFU) << 8; + out |= data[1] & 0xFFU; + + pos += 2; + + return true; +} + +template bool inline get2Byte(const QByteArray &data, T &out) { + size_t pos = 0; + return get2Byte(data, pos, out); +} + +template void inline set1Byte(const T in, QByteArray &out) { + static_assert(std::is_integral_v || std::is_enum_v, + "Only integrals allowed for raw byte accessd"); + unsigned char c = in; + out += c; +} + +template +bool inline get1Byte(const QByteArray &baData, size_t &pos, T &out) { + static_assert(std::is_integral_v || std::is_enum_v, + "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::is_signed) + out = (T)(data[0]); + else + out = (T)(data[0] & 0xFF); + + pos += 1; + + return true; +} + +template bool inline get1Byte(const QByteArray &data, T &out) { + size_t pos = 0; + return get1Byte(data, pos, out); +} +} // namespace LtsUtils diff --git a/Lts/Common/httq/include/http_parser.h b/Lts/Common/httq/include/http_parser.h old mode 100755 new mode 100644 index 5e8d9e9f9..9f992ec13 --- a/Lts/Common/httq/include/http_parser.h +++ b/Lts/Common/httq/include/http_parser.h @@ -6,14 +6,13 @@ extern "C" { #endif - #define HTTP_PARSER_VERSION_MAJOR 2 #define HTTP_PARSER_VERSION_MINOR 9 #define HTTP_PARSER_VERSION_PATCH 4 #include -#if defined(_WIN32) && !defined(__MINGW32__) && \ - (!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__) +#if defined(_WIN32) && !defined(__MINGW32__) && \ + (!defined(_MSC_VER) || _MSC_VER < 1600) && !defined(__WINE__) #include typedef __int8 int8_t; typedef unsigned __int8 uint8_t; @@ -27,351 +26,285 @@ typedef unsigned __int64 uint64_t; #include #endif - - #ifndef HTTP_PARSER_STRICT -# define HTTP_PARSER_STRICT 1 +#define HTTP_PARSER_STRICT 1 #endif - - #ifndef HTTP_MAX_HEADER_SIZE -# define HTTP_MAX_HEADER_SIZE (80*1024) +#define HTTP_MAX_HEADER_SIZE (80 * 1024) #endif -typedef struct http_parser http_parser; -typedef struct http_parser_settings http_parser_settings; +using http_parser = struct http_parser; +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) - -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 - { +enum http_status { #define XX(num, name, string) HTTP_STATUS_##name = num, HTTP_STATUS_MAP(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) - -#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 - { +enum http_method { #define XX(num, name, string) HTTP_##name = num, HTTP_METHOD_MAP(XX) #undef XX - }; - +}; 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 +}; - -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) \ - \ - XX(OK, "success") \ - \ - \ - XX(CB_message_begin, "the on_message_begin callback failed") \ - XX(CB_url, "the on_url callback failed") \ - XX(CB_header_field, "the on_header_field callback failed") \ - XX(CB_header_value, "the on_header_value callback failed") \ - XX(CB_headers_complete, "the on_headers_complete callback failed") \ - XX(CB_body, "the on_body callback failed") \ - 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") \ - XX(HEADER_OVERFLOW, \ - "too many header bytes seen; overflow detected") \ - XX(CLOSED_CONNECTION, \ - "data received after completed connection: close message") \ - XX(INVALID_VERSION, "invalid HTTP version") \ - 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_MAP(XX) \ + \ + XX(OK, "success") \ + \ + XX(CB_message_begin, "the on_message_begin callback failed") \ + XX(CB_url, "the on_url callback failed") \ + XX(CB_header_field, "the on_header_field callback failed") \ + XX(CB_header_value, "the on_header_value callback failed") \ + XX(CB_headers_complete, "the on_headers_complete callback failed") \ + XX(CB_body, "the on_body callback failed") \ + 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") \ + XX(HEADER_OVERFLOW, "too many header bytes seen; overflow detected") \ + XX(CLOSED_CONNECTION, \ + "data received after completed connection: close message") \ + XX(INVALID_VERSION, "invalid HTTP version") \ + 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, -enum http_errno { - HTTP_ERRNO_MAP(HTTP_ERRNO_GEN) -}; +enum http_errno { HTTP_ERRNO_MAP(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 { - - unsigned int type : 2; - unsigned int flags : 8; - unsigned int state : 7; - unsigned int header_state : 7; - unsigned int index : 5; + + unsigned int type : 2; + unsigned int flags : 8; + unsigned int state : 7; + unsigned int header_state : 7; + unsigned int index : 5; unsigned int extra_flags : 2; unsigned int lenient_http_headers : 1; - uint32_t nread; - uint64_t content_length; + uint32_t nread; + uint64_t content_length; - unsigned short http_major; unsigned short http_minor; - unsigned int status_code : 16; - unsigned int method : 8; + unsigned int status_code : 16; + unsigned int method : 8; unsigned int http_errno : 7; - - unsigned int upgrade : 1; - - void *data; + void *data; }; - struct http_parser_settings { - http_cb on_message_begin; + http_cb on_message_begin; http_data_cb on_url; http_data_cb on_status; http_data_cb on_header_field; http_data_cb on_header_value; - http_cb on_headers_complete; + http_cb on_headers_complete; http_data_cb on_body; - http_cb on_message_complete; - + http_cb on_message_complete; - http_cb on_chunk_header; - http_cb on_chunk_complete; + http_cb on_chunk_header; + http_cb on_chunk_complete; }; - -enum http_parser_url_fields - { UF_SCHEMA = 0 - , UF_HOST = 1 - , UF_PORT = 2 - , UF_PATH = 3 - , UF_QUERY = 4 - , UF_FRAGMENT = 5 - , UF_USERINFO = 6 - , UF_MAX = 7 - }; - - - +enum http_parser_url_fields { + UF_SCHEMA = 0, + UF_HOST = 1, + UF_PORT = 2, + UF_PATH = 3, + UF_QUERY = 4, + UF_FRAGMENT = 5, + UF_USERINFO = 6, + UF_MAX = 7 +}; struct http_parser_url { - uint16_t field_set; - uint16_t port; + uint16_t field_set; + uint16_t port; struct { - uint16_t off; - uint16_t len; + uint16_t off; + uint16_t len; } field_data[UF_MAX]; }; - - - unsigned long http_parser_version(void); void http_parser_init(http_parser *parser, enum http_parser_type type); - - - void http_parser_settings_init(http_parser_settings *settings); - - - size_t http_parser_execute(http_parser *parser, const http_parser_settings *settings, - const char *data, - size_t len); - - - + const char *data, size_t len); int http_should_keep_alive(const http_parser *parser); - const char *http_method_str(enum http_method m); - const char *http_status_str(enum http_status s); - const char *http_errno_name(enum http_errno err); - const char *http_errno_description(enum http_errno err); - 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); - void http_parser_pause(http_parser *parser, int paused); - int http_body_is_final(const http_parser *parser); - void http_parser_set_max_header_size(uint32_t size); #ifdef __cplusplus