|
@@ -26,8 +26,10 @@
|
|
|
#include <QString>
|
|
|
#include <QByteArray>
|
|
|
|
|
|
+#include "selfcheckiterator.h"
|
|
|
#include "qtprotobuftypes.h"
|
|
|
-#include "qprotobufobject_p.h"
|
|
|
+#include "qtprotobuflogging.h"
|
|
|
+#include "qabstractprotobufserializer.h"
|
|
|
|
|
|
namespace qtprotobuf {
|
|
|
|
|
@@ -35,7 +37,7 @@ class QProtobufSerializerPrivate {
|
|
|
QProtobufSerializerPrivate() = delete;
|
|
|
~QProtobufSerializerPrivate() = delete;
|
|
|
Q_DISABLE_COPY(QProtobufSerializerPrivate)
|
|
|
- QProtobufSerializerPrivate(ProtobufObjectPrivate &&) = delete;
|
|
|
+ QProtobufSerializerPrivate(QProtobufSerializerPrivate &&) = delete;
|
|
|
QProtobufSerializerPrivate &operator =(QProtobufSerializerPrivate &&) = delete;
|
|
|
public:
|
|
|
template <typename V,
|
|
@@ -84,34 +86,34 @@ public:
|
|
|
|
|
|
template <typename T,
|
|
|
typename std::enable_if_t<!std::is_base_of<QObject, T>::value, int> = 0>
|
|
|
- static void wrapSerializer(const std::function<QByteArray(const T &, int &)> &s, const std::function<QVariant(SelfcheckIterator &)> &d, WireTypes type)
|
|
|
+ static void wrapSerializer(QProtobufSerializer *owner,const std::function<QByteArray(const T &, int &)> &s, const std::function<QVariant(SelfcheckIterator &)> &d, WireTypes type)
|
|
|
{
|
|
|
- ProtobufObjectPrivate::serializers[qMetaTypeId<T>()] = {
|
|
|
- [s](const QVariant &value, int &fieldIndex) {
|
|
|
- return s(value.value<T>(), fieldIndex);
|
|
|
- },
|
|
|
- [d](SelfcheckIterator &it, QVariant & value){
|
|
|
- value = d(it);
|
|
|
- },
|
|
|
- type
|
|
|
- };
|
|
|
- }
|
|
|
+ owner->serializers[qMetaTypeId<T>()] = {
|
|
|
+ [s](const QVariant &value, int &fieldIndex) {
|
|
|
+ return s(value.value<T>(), fieldIndex);
|
|
|
+ },
|
|
|
+ [d](SelfcheckIterator &it, QVariant & value){
|
|
|
+ value = d(it);
|
|
|
+ },
|
|
|
+ type
|
|
|
+ };
|
|
|
+}
|
|
|
|
|
|
- template <typename T,
|
|
|
- typename std::enable_if_t<!std::is_base_of<QObject, T>::value, int> = 0>
|
|
|
- static void wrapSerializer(const std::function<QByteArray(const T &, int &)> &s, const std::function<void(SelfcheckIterator &it, QVariant & value)> &d, WireTypes type)
|
|
|
- {
|
|
|
- ProtobufObjectPrivate::serializers[qMetaTypeId<T>()] = {
|
|
|
+template <typename T,
|
|
|
+typename std::enable_if_t<!std::is_base_of<QObject, T>::value, int> = 0>
|
|
|
+static void wrapSerializer(QProtobufSerializer *owner, const std::function<QByteArray(const T &, int &)> &s, const std::function<void(SelfcheckIterator &it, QVariant & value)> &d, WireTypes type)
|
|
|
+{
|
|
|
+ owner->serializers[qMetaTypeId<T>()] = {
|
|
|
[s](const QVariant &value, int &fieldIndex) {
|
|
|
- return s(value.value<T>(), fieldIndex);
|
|
|
- },
|
|
|
- d,
|
|
|
- type
|
|
|
- };
|
|
|
- }
|
|
|
+ return s(value.value<T>(), fieldIndex);
|
|
|
+ },
|
|
|
+ d,
|
|
|
+ type
|
|
|
+};
|
|
|
+}
|
|
|
|
|
|
- //----------------Serialize basic integral and floating point----------------
|
|
|
- /**
|
|
|
+//----------------Serialize basic integral and floating point----------------
|
|
|
+/**
|
|
|
* @brief Serialization of fixed-length primitive types
|
|
|
*
|
|
|
* Natural layout of bits is used: value is encoded in a byte array same way as it is located in memory
|
|
@@ -120,18 +122,18 @@ public:
|
|
|
* @param[out] outFieldIndex Index of the value in parent structure (ignored)
|
|
|
* @return Byte array with value encoded
|
|
|
*/
|
|
|
- template <typename V,
|
|
|
- typename std::enable_if_t<std::is_floating_point<V>::value, int> = 0>
|
|
|
- static QByteArray serializeBasic(const V &value, int &/*outFieldIndex*/) {
|
|
|
- qProtoDebug() << __func__ << "value" << value;
|
|
|
-
|
|
|
- //Reserve required number of bytes
|
|
|
- QByteArray result(sizeof(V), '\0');
|
|
|
- *reinterpret_cast<V *>(result.data()) = value;
|
|
|
- return result;
|
|
|
- }
|
|
|
+template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_floating_point<V>::value, int> = 0>
|
|
|
+static QByteArray serializeBasic(const V &value, int &/*outFieldIndex*/) {
|
|
|
+ qProtoDebug() << __func__ << "value" << value;
|
|
|
+
|
|
|
+ //Reserve required number of bytes
|
|
|
+ QByteArray result(sizeof(V), '\0');
|
|
|
+ *reinterpret_cast<V *>(result.data()) = value;
|
|
|
+ return result;
|
|
|
+}
|
|
|
|
|
|
- /**
|
|
|
+/**
|
|
|
* @brief Serialization of fixed length integral types
|
|
|
*
|
|
|
* @details Natural layout of bits is employed
|
|
@@ -140,21 +142,21 @@ public:
|
|
|
* @param[out] outFieldIndex Index of the value in parent structure (ignored)
|
|
|
* @return Byte array with value encoded
|
|
|
*/
|
|
|
- template <typename V,
|
|
|
- typename std::enable_if_t<std::is_same<V, fixed32>::value
|
|
|
- || std::is_same<V, fixed64>::value
|
|
|
- || std::is_same<V, sfixed32>::value
|
|
|
- || std::is_same<V, sfixed64>::value, int> = 0>
|
|
|
- static QByteArray serializeBasic(const V &value, int &/*outFieldIndex*/) {
|
|
|
- qProtoDebug() << __func__ << "value" << value;
|
|
|
-
|
|
|
- //Reserve required number of bytes
|
|
|
- QByteArray result(sizeof(V), '\0');
|
|
|
- *reinterpret_cast<V *>(result.data()) = value;
|
|
|
- return result;
|
|
|
- }
|
|
|
+template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_same<V, fixed32>::value
|
|
|
+ || std::is_same<V, fixed64>::value
|
|
|
+ || std::is_same<V, sfixed32>::value
|
|
|
+ || std::is_same<V, sfixed64>::value, int> = 0>
|
|
|
+static QByteArray serializeBasic(const V &value, int &/*outFieldIndex*/) {
|
|
|
+ qProtoDebug() << __func__ << "value" << value;
|
|
|
+
|
|
|
+ //Reserve required number of bytes
|
|
|
+ QByteArray result(sizeof(V), '\0');
|
|
|
+ *reinterpret_cast<V *>(result.data()) = value;
|
|
|
+ return result;
|
|
|
+}
|
|
|
|
|
|
- /**
|
|
|
+/**
|
|
|
*@brief Serialization of signed integral types
|
|
|
*
|
|
|
* Use <a href="https://developers.google.com/protocol-buffers/docs/encoding">ZigZag encoding</a> first,
|
|
@@ -165,30 +167,30 @@ public:
|
|
|
* @param[out] outFieldIndex Index of the value in parent structure
|
|
|
* @return Byte array with value encoded
|
|
|
*/
|
|
|
- template <typename V,
|
|
|
- typename std::enable_if_t<std::is_integral<V>::value
|
|
|
- && std::is_signed<V>::value, int> = 0>
|
|
|
- static QByteArray serializeBasic(const V &value, int &outFieldIndex) {
|
|
|
- qProtoDebug() << __func__ << "value" << value;
|
|
|
- using UV = typename std::make_unsigned<V>::type;
|
|
|
- UV uValue = 0;
|
|
|
-
|
|
|
- //Use ZigZag convertion first and apply unsigned variant next
|
|
|
- V zigZagValue = (value << 1) ^ (value >> (sizeof(UV) * 8 - 1));
|
|
|
- uValue = static_cast<UV>(zigZagValue);
|
|
|
- return serializeBasic(uValue, outFieldIndex);
|
|
|
- }
|
|
|
+template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_integral<V>::value
|
|
|
+ && std::is_signed<V>::value, int> = 0>
|
|
|
+static QByteArray serializeBasic(const V &value, int &outFieldIndex) {
|
|
|
+ qProtoDebug() << __func__ << "value" << value;
|
|
|
+ using UV = typename std::make_unsigned<V>::type;
|
|
|
+ UV uValue = 0;
|
|
|
+
|
|
|
+ //Use ZigZag convertion first and apply unsigned variant next
|
|
|
+ V zigZagValue = (value << 1) ^ (value >> (sizeof(UV) * 8 - 1));
|
|
|
+ uValue = static_cast<UV>(zigZagValue);
|
|
|
+ return serializeBasic(uValue, outFieldIndex);
|
|
|
+}
|
|
|
|
|
|
- template <typename V,
|
|
|
- typename std::enable_if_t<std::is_same<V, int32>::value
|
|
|
- || std::is_same<V, int64>::value, int> = 0>
|
|
|
- static QByteArray serializeBasic(const V &value, int &outFieldIndex) {
|
|
|
- qProtoDebug() << __func__ << "value" << value;
|
|
|
- using UV = typename std::make_unsigned<V>::type;
|
|
|
- return serializeBasic(static_cast<UV>(value), outFieldIndex);
|
|
|
- }
|
|
|
+template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_same<V, int32>::value
|
|
|
+ || std::is_same<V, int64>::value, int> = 0>
|
|
|
+static QByteArray serializeBasic(const V &value, int &outFieldIndex) {
|
|
|
+ qProtoDebug() << __func__ << "value" << value;
|
|
|
+ using UV = typename std::make_unsigned<V>::type;
|
|
|
+ return serializeBasic(static_cast<UV>(value), outFieldIndex);
|
|
|
+}
|
|
|
|
|
|
- /**
|
|
|
+/**
|
|
|
*@brief Serialization of unsigned integral types
|
|
|
*
|
|
|
* Use <a href="https://developers.google.com/protocol-buffers/docs/encoding">Varint encoding</a>:
|
|
@@ -199,239 +201,240 @@ public:
|
|
|
* @param[out] outFieldIndex Index of the value in parent structure
|
|
|
* @return Byte array with value encoded
|
|
|
*/
|
|
|
- template <typename V,
|
|
|
- typename std::enable_if_t<std::is_integral<V>::value
|
|
|
- && std::is_unsigned<V>::value, int> = 0>
|
|
|
- static QByteArray serializeBasic(const V &value, int &outFieldIndex) {
|
|
|
- qProtoDebug() << __func__ << "value" << value;
|
|
|
- V varint = value;
|
|
|
- QByteArray result;
|
|
|
-
|
|
|
- while (varint != 0) {
|
|
|
- //Put 7 bits to result buffer and mark as "not last" (0b10000000)
|
|
|
- result.append((varint & 0b01111111) | 0b10000000);
|
|
|
- //Divide values to chunks of 7 bits and move to next chunk
|
|
|
- varint >>= 7;
|
|
|
- }
|
|
|
-
|
|
|
- // Invalidate field index in case if serialized result is empty
|
|
|
- // NOTE: the field will not be sent if its index is equal to NotUsedFieldIndex
|
|
|
- if (result.size() == 0) {
|
|
|
- outFieldIndex = NotUsedFieldIndex;
|
|
|
- } else {
|
|
|
- //Mark last chunk as last by clearing last bit
|
|
|
- result.data()[result.size() - 1] &= ~0b10000000;
|
|
|
- }
|
|
|
- return result;
|
|
|
- }
|
|
|
-
|
|
|
- template <typename V,
|
|
|
- typename std::enable_if_t<std::is_same<V, QString>::value, int> = 0>
|
|
|
- static QByteArray serializeBasic(const V &value, int &/*outFieldIndex*/) {
|
|
|
- return serializeLengthDelimited(value.toUtf8());
|
|
|
+template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_integral<V>::value
|
|
|
+ && std::is_unsigned<V>::value, int> = 0>
|
|
|
+static QByteArray serializeBasic(const V &value, int &outFieldIndex) {
|
|
|
+ qProtoDebug() << __func__ << "value" << value;
|
|
|
+ V varint = value;
|
|
|
+ QByteArray result;
|
|
|
+
|
|
|
+ while (varint != 0) {
|
|
|
+ //Put 7 bits to result buffer and mark as "not last" (0b10000000)
|
|
|
+ result.append((varint & 0b01111111) | 0b10000000);
|
|
|
+ //Divide values to chunks of 7 bits and move to next chunk
|
|
|
+ varint >>= 7;
|
|
|
}
|
|
|
|
|
|
- template <typename V,
|
|
|
- typename std::enable_if_t<std::is_same<V, QByteArray>::value, int> = 0>
|
|
|
- static QByteArray serializeBasic(const V &value, int &/*outFieldIndex*/) {
|
|
|
- return serializeLengthDelimited(value);
|
|
|
+ // Invalidate field index in case if serialized result is empty
|
|
|
+ // NOTE: the field will not be sent if its index is equal to NotUsedFieldIndex
|
|
|
+ if (result.size() == 0) {
|
|
|
+ outFieldIndex = NotUsedFieldIndex;
|
|
|
+ } else {
|
|
|
+ //Mark last chunk as last by clearing last bit
|
|
|
+ result.data()[result.size() - 1] &= ~0b10000000;
|
|
|
}
|
|
|
+ return result;
|
|
|
+}
|
|
|
|
|
|
- //---------------Deserialize basic integral and floating point---------------
|
|
|
- template <typename V,
|
|
|
- typename std::enable_if_t<std::is_floating_point<V>::value
|
|
|
- || std::is_same<V, fixed32>::value
|
|
|
- || std::is_same<V, fixed64>::value
|
|
|
- || std::is_same<V, sfixed32>::value
|
|
|
- || std::is_same<V, sfixed64>::value, int> = 0>
|
|
|
- static QVariant deserializeBasic(SelfcheckIterator &it) {
|
|
|
- qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
+template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_same<V, QString>::value, int> = 0>
|
|
|
+static QByteArray serializeBasic(const V &value, int &/*outFieldIndex*/) {
|
|
|
+ return serializeLengthDelimited(value.toUtf8());
|
|
|
+}
|
|
|
|
|
|
- QVariant newPropertyValue(QVariant::fromValue(*(V *)((QByteArray::const_iterator&)it)));
|
|
|
- it += sizeof(V);
|
|
|
- return newPropertyValue;
|
|
|
- }
|
|
|
+template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_same<V, QByteArray>::value, int> = 0>
|
|
|
+static QByteArray serializeBasic(const V &value, int &/*outFieldIndex*/) {
|
|
|
+ return serializeLengthDelimited(value);
|
|
|
+}
|
|
|
|
|
|
- template <typename V,
|
|
|
- typename std::enable_if_t<std::is_integral<V>::value
|
|
|
- && std::is_unsigned<V>::value, int> = 0>
|
|
|
- static QVariant deserializeBasic(SelfcheckIterator &it) {
|
|
|
- qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
+//---------------Deserialize basic integral and floating point---------------
|
|
|
+template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_floating_point<V>::value
|
|
|
+ || std::is_same<V, fixed32>::value
|
|
|
+ || std::is_same<V, fixed64>::value
|
|
|
+ || std::is_same<V, sfixed32>::value
|
|
|
+ || std::is_same<V, sfixed64>::value, int> = 0>
|
|
|
+static QVariant deserializeBasic(SelfcheckIterator &it) {
|
|
|
+ qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
+
|
|
|
+ QVariant newPropertyValue(QVariant::fromValue(*(V *)((QByteArray::const_iterator&)it)));
|
|
|
+ it += sizeof(V);
|
|
|
+ return newPropertyValue;
|
|
|
+}
|
|
|
|
|
|
- return QVariant::fromValue(deserializeVarintCommon<V>(it));
|
|
|
- }
|
|
|
+template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_integral<V>::value
|
|
|
+ && std::is_unsigned<V>::value, int> = 0>
|
|
|
+static QVariant deserializeBasic(SelfcheckIterator &it) {
|
|
|
+ qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
|
|
|
- template <typename V,
|
|
|
- typename std::enable_if_t<std::is_integral<V>::value
|
|
|
- && std::is_signed<V>::value,int> = 0>
|
|
|
- static QVariant deserializeBasic(SelfcheckIterator &it) {
|
|
|
- qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
- using UV = typename std::make_unsigned<V>::type;
|
|
|
- UV unsignedValue = deserializeVarintCommon<UV>(it);
|
|
|
- V value = (unsignedValue >> 1) ^ (-1 * (unsignedValue & 1));
|
|
|
- return QVariant::fromValue<V>(value);
|
|
|
- }
|
|
|
+ return QVariant::fromValue(deserializeVarintCommon<V>(it));
|
|
|
+}
|
|
|
|
|
|
- template <typename V,
|
|
|
- typename std::enable_if_t<std::is_same<int32, V>::value
|
|
|
- || std::is_same<int64, V>::value, int> = 0>
|
|
|
- static QVariant deserializeBasic(SelfcheckIterator &it) {
|
|
|
- qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
- using UV = typename std::make_unsigned<V>::type;
|
|
|
- UV unsignedValue = deserializeVarintCommon<UV>(it);
|
|
|
- V value = static_cast<V>(unsignedValue);
|
|
|
- return QVariant::fromValue(value);
|
|
|
- }
|
|
|
+template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_integral<V>::value
|
|
|
+ && std::is_signed<V>::value,int> = 0>
|
|
|
+static QVariant deserializeBasic(SelfcheckIterator &it) {
|
|
|
+ qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
+ using UV = typename std::make_unsigned<V>::type;
|
|
|
+ UV unsignedValue = deserializeVarintCommon<UV>(it);
|
|
|
+ V value = (unsignedValue >> 1) ^ (-1 * (unsignedValue & 1));
|
|
|
+ return QVariant::fromValue<V>(value);
|
|
|
+}
|
|
|
|
|
|
- template <typename V,
|
|
|
- typename std::enable_if_t<std::is_same<QByteArray, V>::value, int> = 0>
|
|
|
- static QVariant deserializeBasic(SelfcheckIterator &it) {
|
|
|
- return QVariant::fromValue(deserializeLengthDelimited(it));
|
|
|
- }
|
|
|
+template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_same<int32, V>::value
|
|
|
+ || std::is_same<int64, V>::value, int> = 0>
|
|
|
+static QVariant deserializeBasic(SelfcheckIterator &it) {
|
|
|
+ qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
+ using UV = typename std::make_unsigned<V>::type;
|
|
|
+ UV unsignedValue = deserializeVarintCommon<UV>(it);
|
|
|
+ V value = static_cast<V>(unsignedValue);
|
|
|
+ return QVariant::fromValue(value);
|
|
|
+}
|
|
|
|
|
|
- template <typename V,
|
|
|
- typename std::enable_if_t<std::is_same<QString, V>::value, int> = 0>
|
|
|
- static QVariant deserializeBasic(SelfcheckIterator &it) {
|
|
|
- return QVariant::fromValue(QString::fromUtf8(deserializeLengthDelimited(it)));
|
|
|
- }
|
|
|
+template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_same<QByteArray, V>::value, int> = 0>
|
|
|
+static QVariant deserializeBasic(SelfcheckIterator &it) {
|
|
|
+ return QVariant::fromValue(deserializeLengthDelimited(it));
|
|
|
+}
|
|
|
|
|
|
- template<typename V,
|
|
|
- typename std::enable_if_t<!(std::is_same<V, QString>::value
|
|
|
- || std::is_same<V, QByteArray>::value
|
|
|
- || std::is_base_of<QObject, V>::value), int> = 0>
|
|
|
- static QByteArray serializeListType(const QList<V> &listValue, int &outFieldIndex) {
|
|
|
- qProtoDebug() << __func__ << "listValue.count" << listValue.count() << "outFiledIndex" << outFieldIndex;
|
|
|
+template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_same<QString, V>::value, int> = 0>
|
|
|
+static QVariant deserializeBasic(SelfcheckIterator &it) {
|
|
|
+ return QVariant::fromValue(QString::fromUtf8(deserializeLengthDelimited(it)));
|
|
|
+}
|
|
|
|
|
|
- if (listValue.count() <= 0) {
|
|
|
- outFieldIndex = NotUsedFieldIndex;
|
|
|
- return QByteArray();
|
|
|
- }
|
|
|
+template<typename V,
|
|
|
+ typename std::enable_if_t<!(std::is_same<V, QString>::value
|
|
|
+ || std::is_same<V, QByteArray>::value
|
|
|
+ || std::is_base_of<QObject, V>::value), int> = 0>
|
|
|
+static QByteArray serializeListType(const QList<V> &listValue, int &outFieldIndex) {
|
|
|
+ qProtoDebug() << __func__ << "listValue.count" << listValue.count() << "outFiledIndex" << outFieldIndex;
|
|
|
|
|
|
- int empty = NotUsedFieldIndex;
|
|
|
- QByteArray serializedList;
|
|
|
- for (auto &value : listValue) {
|
|
|
- serializedList.append(serializeBasic<V>(value, empty));
|
|
|
- }
|
|
|
- //If internal field type is not LengthDelimited, exact amount of fields to be specified
|
|
|
- serializedList = prependLengthDelimitedSize(serializedList);
|
|
|
- return serializedList;
|
|
|
+ if (listValue.count() <= 0) {
|
|
|
+ outFieldIndex = NotUsedFieldIndex;
|
|
|
+ return QByteArray();
|
|
|
}
|
|
|
|
|
|
- template<typename V,
|
|
|
- typename std::enable_if_t<std::is_same<V, QString>::value, int> = 0>
|
|
|
- static QByteArray serializeListType(const QList<V> &listValue, int &outFieldIndex) {
|
|
|
- qProtoDebug() << __func__ << "listValue.count" << listValue.count() << "outFiledIndex" << outFieldIndex;
|
|
|
-
|
|
|
- if (listValue.count() <= 0) {
|
|
|
- outFieldIndex = NotUsedFieldIndex;
|
|
|
- return QByteArray();
|
|
|
- }
|
|
|
+ int empty = NotUsedFieldIndex;
|
|
|
+ QByteArray serializedList;
|
|
|
+ for (auto &value : listValue) {
|
|
|
+ serializedList.append(serializeBasic<V>(value, empty));
|
|
|
+ }
|
|
|
+ //If internal field type is not LengthDelimited, exact amount of fields to be specified
|
|
|
+ serializedList = prependLengthDelimitedSize(serializedList);
|
|
|
+ return serializedList;
|
|
|
+}
|
|
|
|
|
|
- QByteArray serializedList;
|
|
|
- for (auto &value : listValue) {
|
|
|
- serializedList.append(QProtobufSerializerPrivate::encodeHeader(outFieldIndex, LengthDelimited));
|
|
|
- serializedList.append(serializeLengthDelimited(value.toUtf8()));
|
|
|
- }
|
|
|
+template<typename V,
|
|
|
+ typename std::enable_if_t<std::is_same<V, QString>::value, int> = 0>
|
|
|
+static QByteArray serializeListType(const QList<V> &listValue, int &outFieldIndex) {
|
|
|
+ qProtoDebug() << __func__ << "listValue.count" << listValue.count() << "outFiledIndex" << outFieldIndex;
|
|
|
|
|
|
+ if (listValue.count() <= 0) {
|
|
|
outFieldIndex = NotUsedFieldIndex;
|
|
|
- return serializedList;
|
|
|
+ return QByteArray();
|
|
|
}
|
|
|
|
|
|
- template<typename V,
|
|
|
- typename std::enable_if_t<std::is_same<V, QByteArray>::value, int> = 0>
|
|
|
- static QByteArray serializeListType(const QList<V> &listValue, int &outFieldIndex) {
|
|
|
- qProtoDebug() << __func__ << "listValue.count" << listValue.count() << "outFiledIndex" << outFieldIndex;
|
|
|
+ QByteArray serializedList;
|
|
|
+ for (auto &value : listValue) {
|
|
|
+ serializedList.append(QProtobufSerializerPrivate::encodeHeader(outFieldIndex, LengthDelimited));
|
|
|
+ serializedList.append(serializeLengthDelimited(value.toUtf8()));
|
|
|
+ }
|
|
|
|
|
|
- if (listValue.count() <= 0) {
|
|
|
- outFieldIndex = NotUsedFieldIndex;
|
|
|
- return QByteArray();
|
|
|
- }
|
|
|
+ outFieldIndex = NotUsedFieldIndex;
|
|
|
+ return serializedList;
|
|
|
+}
|
|
|
|
|
|
- QByteArray serializedList;
|
|
|
- for (auto &value : listValue) {
|
|
|
- serializedList.append(QProtobufSerializerPrivate::encodeHeader(outFieldIndex, LengthDelimited));
|
|
|
- serializedList.append(serializeLengthDelimited(value));
|
|
|
- }
|
|
|
+template<typename V,
|
|
|
+ typename std::enable_if_t<std::is_same<V, QByteArray>::value, int> = 0>
|
|
|
+static QByteArray serializeListType(const QList<V> &listValue, int &outFieldIndex) {
|
|
|
+ qProtoDebug() << __func__ << "listValue.count" << listValue.count() << "outFiledIndex" << outFieldIndex;
|
|
|
|
|
|
+ if (listValue.count() <= 0) {
|
|
|
outFieldIndex = NotUsedFieldIndex;
|
|
|
- return serializedList;
|
|
|
+ return QByteArray();
|
|
|
}
|
|
|
|
|
|
- template <typename V,
|
|
|
- typename std::enable_if_t<std::is_same<V, QByteArray>::value, int> = 0>
|
|
|
- static void deserializeList(SelfcheckIterator &it, QVariant &previous) {
|
|
|
- qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
-
|
|
|
- QByteArrayList list = previous.value<QByteArrayList>();
|
|
|
- list.append(deserializeLengthDelimited(it));
|
|
|
- previous.setValue(list);
|
|
|
+ QByteArray serializedList;
|
|
|
+ for (auto &value : listValue) {
|
|
|
+ serializedList.append(QProtobufSerializerPrivate::encodeHeader(outFieldIndex, LengthDelimited));
|
|
|
+ serializedList.append(serializeLengthDelimited(value));
|
|
|
}
|
|
|
|
|
|
- template <typename V,
|
|
|
- typename std::enable_if_t<std::is_same<V, QString>::value, int> = 0>
|
|
|
- static void deserializeList(SelfcheckIterator &it, QVariant &previous) {
|
|
|
- qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
+ outFieldIndex = NotUsedFieldIndex;
|
|
|
+ return serializedList;
|
|
|
+}
|
|
|
|
|
|
- QStringList list = previous.value<QStringList>();
|
|
|
- QByteArray value = deserializeLengthDelimited(it);
|
|
|
- list.append(QString::fromUtf8(value));
|
|
|
- previous.setValue(list);
|
|
|
- }
|
|
|
+template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_same<V, QByteArray>::value, int> = 0>
|
|
|
+static void deserializeList(SelfcheckIterator &it, QVariant &previous) {
|
|
|
+ qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
|
|
|
- template <typename V,
|
|
|
- typename std::enable_if_t<!(std::is_same<V, QString>::value
|
|
|
- || std::is_same<V, QByteArray>::value
|
|
|
- || std::is_base_of<QObject, V>::value), int> = 0>
|
|
|
- static void deserializeList(SelfcheckIterator &it, QVariant &previous) {
|
|
|
- qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
+ QByteArrayList list = previous.value<QByteArrayList>();
|
|
|
+ list.append(deserializeLengthDelimited(it));
|
|
|
+ previous.setValue(list);
|
|
|
+}
|
|
|
|
|
|
- QList<V> out;
|
|
|
- unsigned int count = deserializeVarintCommon<uint32>(it);
|
|
|
- SelfcheckIterator lastVarint = it + count;
|
|
|
- while (it != lastVarint) {
|
|
|
- QVariant variant = deserializeBasic<V>(it);
|
|
|
- out.append(variant.value<V>());
|
|
|
- }
|
|
|
- previous.setValue(out);
|
|
|
- }
|
|
|
+template <typename V,
|
|
|
+ typename std::enable_if_t<std::is_same<V, QString>::value, int> = 0>
|
|
|
+static void deserializeList(SelfcheckIterator &it, QVariant &previous) {
|
|
|
+ qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
|
|
|
- static QByteArray deserializeLengthDelimited(SelfcheckIterator &it) {
|
|
|
- qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
+ QStringList list = previous.value<QStringList>();
|
|
|
+ QByteArray value = deserializeLengthDelimited(it);
|
|
|
+ list.append(QString::fromUtf8(value));
|
|
|
+ previous.setValue(list);
|
|
|
+}
|
|
|
|
|
|
- unsigned int length = deserializeVarintCommon<uint32>(it);
|
|
|
- QByteArray result((QByteArray::const_iterator&)it, length); //TODO it's possible to void buffeer copying by setupimg new "end of QByteArray";
|
|
|
- it += length;
|
|
|
- return result;
|
|
|
+template <typename V,
|
|
|
+ typename std::enable_if_t<!(std::is_same<V, QString>::value
|
|
|
+ || std::is_same<V, QByteArray>::value
|
|
|
+ || std::is_base_of<QObject, V>::value), int> = 0>
|
|
|
+static void deserializeList(SelfcheckIterator &it, QVariant &previous) {
|
|
|
+ qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
+
|
|
|
+ QList<V> out;
|
|
|
+ unsigned int count = deserializeVarintCommon<uint32>(it);
|
|
|
+ SelfcheckIterator lastVarint = it + count;
|
|
|
+ while (it != lastVarint) {
|
|
|
+ QVariant variant = deserializeBasic<V>(it);
|
|
|
+ out.append(variant.value<V>());
|
|
|
}
|
|
|
+ previous.setValue(out);
|
|
|
+}
|
|
|
|
|
|
- static QByteArray serializeLengthDelimited(const QByteArray &data) {
|
|
|
- qProtoDebug() << __func__ << "data.size" << data.size() << "data" << data.toHex();
|
|
|
- QByteArray result(data);
|
|
|
- //Varint serialize field size and apply result as starting point
|
|
|
- result = prependLengthDelimitedSize(result);
|
|
|
- return result;
|
|
|
- }
|
|
|
+static QByteArray deserializeLengthDelimited(SelfcheckIterator &it) {
|
|
|
+ qProtoDebug() << __func__ << "currentByte:" << QString::number((*it), 16);
|
|
|
+
|
|
|
+ unsigned int length = deserializeVarintCommon<uint32>(it);
|
|
|
+ QByteArray result((QByteArray::const_iterator&)it, length); //TODO it's possible to void buffeer copying by setupimg new "end of QByteArray";
|
|
|
+ it += length;
|
|
|
+ return result;
|
|
|
+}
|
|
|
|
|
|
- static bool decodeHeader(SelfcheckIterator &it, int &fieldIndex, WireTypes &wireType);
|
|
|
- static QByteArray encodeHeader(int fieldIndex, WireTypes wireType);
|
|
|
+static QByteArray serializeLengthDelimited(const QByteArray &data) {
|
|
|
+ qProtoDebug() << __func__ << "data.size" << data.size() << "data" << data.toHex();
|
|
|
+ QByteArray result(data);
|
|
|
+ //Varint serialize field size and apply result as starting point
|
|
|
+ result = prependLengthDelimitedSize(result);
|
|
|
+ return result;
|
|
|
+}
|
|
|
+
|
|
|
+static bool decodeHeader(SelfcheckIterator &it, int &fieldIndex, WireTypes &wireType);
|
|
|
+static QByteArray encodeHeader(int fieldIndex, WireTypes wireType);
|
|
|
|
|
|
- /**
|
|
|
+/**
|
|
|
* @brief Gets length of a byte-array and prepends to it its serialized length value
|
|
|
* using the appropriate serialization algorithm
|
|
|
*
|
|
|
*
|
|
|
* @param[in, out] serializedList Byte-array to be prepended
|
|
|
*/
|
|
|
- static QByteArray prependLengthDelimitedSize(const QByteArray &data)
|
|
|
- {
|
|
|
- return serializeVarintCommon<uint32_t>(data.size()) + data;
|
|
|
- }
|
|
|
+static QByteArray prependLengthDelimitedSize(const QByteArray &data)
|
|
|
+{
|
|
|
+ return serializeVarintCommon<uint32_t>(data.size()) + data;
|
|
|
+}
|
|
|
|
|
|
- // this set of 3 methods is used to skip bytes corresponding to an unexpected property
|
|
|
- // in a serialized message met while the message being deserialized
|
|
|
- static void skipVarint(SelfcheckIterator &it);
|
|
|
- static void skipLengthDelimited(SelfcheckIterator &it);
|
|
|
- static int skipSerializedFieldBytes(SelfcheckIterator &it, WireTypes type);
|
|
|
+// this set of 3 methods is used to skip bytes corresponding to an unexpected property
|
|
|
+// in a serialized message met while the message being deserialized
|
|
|
+static void skipVarint(SelfcheckIterator &it);
|
|
|
+static void skipLengthDelimited(SelfcheckIterator &it);
|
|
|
+static int skipSerializedFieldBytes(SelfcheckIterator &it, WireTypes type);
|
|
|
+static void deserializeMapField(QVariant &value, SelfcheckIterator &it);
|
|
|
};
|
|
|
|
|
|
//###########################################################################
|
|
@@ -472,48 +475,9 @@ inline bool QProtobufSerializerPrivate::decodeHeader(SelfcheckIterator &it, int
|
|
|
|
|
|
constexpr int maxFieldIndex = (1 << 29) - 1;
|
|
|
return fieldIndex <= maxFieldIndex && fieldIndex > 0 && (wireType == Varint
|
|
|
- || wireType == Fixed64
|
|
|
- || wireType == Fixed32
|
|
|
- || wireType == LengthDelimited);
|
|
|
-}
|
|
|
-
|
|
|
-void QProtobufSerializerPrivate::skipVarint(SelfcheckIterator &it)
|
|
|
-{
|
|
|
- while ((*it) & 0x80) {
|
|
|
- ++it;
|
|
|
- }
|
|
|
- ++it;
|
|
|
-}
|
|
|
-
|
|
|
-void QProtobufSerializerPrivate::skipLengthDelimited(SelfcheckIterator &it)
|
|
|
-{
|
|
|
- //Get length of lenght-delimited field
|
|
|
- unsigned int length = QProtobufSerializerPrivate::deserializeBasic<uint32>(it).toUInt();
|
|
|
- it += length;
|
|
|
-}
|
|
|
-
|
|
|
-int QProtobufSerializerPrivate::skipSerializedFieldBytes(SelfcheckIterator &it, WireTypes type)
|
|
|
-{
|
|
|
- const auto initialIt = QByteArray::const_iterator(it);
|
|
|
- switch (type) {
|
|
|
- case WireTypes::Varint:
|
|
|
- skipVarint(it);
|
|
|
- break;
|
|
|
- case WireTypes::Fixed32:
|
|
|
- it += sizeof(decltype(fixed32::_t));
|
|
|
- break;
|
|
|
- case WireTypes::Fixed64:
|
|
|
- it += sizeof(decltype(fixed64::_t));
|
|
|
- break;
|
|
|
- case WireTypes::LengthDelimited:
|
|
|
- skipLengthDelimited(it);
|
|
|
- break;
|
|
|
- case WireTypes::UnknownWireType:
|
|
|
- default:
|
|
|
- throw std::invalid_argument("Cannot skip due to undefined length of the redundant field.");
|
|
|
- }
|
|
|
-
|
|
|
- return std::distance(initialIt, QByteArray::const_iterator(it));
|
|
|
+ || wireType == Fixed64
|
|
|
+ || wireType == Fixed32
|
|
|
+ || wireType == LengthDelimited);
|
|
|
}
|
|
|
|
|
|
}
|