Ver código fonte

Implement floating point fixed types deserialization

- Add deserialixation for float and double
- Add basic varint deserializer
Alexey Edelev 6 anos atrás
pai
commit
7b7402076b
3 arquivos alterados com 109 adições e 9 exclusões
  1. 60 8
      src/lib/protobufobject.h
  2. 49 0
      tests/deserializationtest.cpp
  3. 0 1
      tests/serializationtest.cpp

+ 60 - 8
src/lib/protobufobject.h

@@ -338,27 +338,79 @@ public:
             QMetaProperty metaProperty = T::staticMetaObject.property(propertyIndex);
 
             ++it;
-            deserializeProperty(metaProperty, it);
+            deserializeProperty(wireType, metaProperty, it);
         }
     }
 
-    void deserializeProperty(const QMetaProperty &metaProperty, QByteArray::const_iterator &it)
+    void deserializeProperty(WireTypes wireType, const QMetaProperty &metaProperty, QByteArray::const_iterator &it)
     {
         QVariant newPropertyValue;
         switch(metaProperty.userType()) {
         case QMetaType::UInt:
-            //TODO: replace with template function for all fixed types
-            newPropertyValue.setValue(*(unsigned int*)it);
-            it += sizeof(unsigned int);
+            if (wireType == Fixed32) {
+                newPropertyValue = deserializeFixed<FixedInt32>(it);
+            } else {
+                newPropertyValue = deserializeVarint<unsigned int>(it);
+            }
             break;
         case QMetaType::ULongLong:
-            //TODO: replace with template function for all fixed types
-            newPropertyValue.setValue(*(qulonglong*)it);
-            it += sizeof(qulonglong);
+            if (wireType == Fixed64) {
+                newPropertyValue = deserializeFixed<FixedInt64>(it);
+            } else {
+                //TODO: deserialize varint
+            }
+            break;
+        case QMetaType::Float:
+            newPropertyValue = deserializeFixed<float>(it);
+            break;
+        case QMetaType::Double:
+            newPropertyValue = deserializeFixed<double>(it);
+            break;
+        case QMetaType::Int:
+            newPropertyValue = deserializeVarint<int>(it);
+            break;
+        default:
             break;
         }
         setProperty(metaProperty.name(), newPropertyValue);
     }
+
+    template <typename V,
+              typename std::enable_if_t<std::is_floating_point<V>::value
+                                        || std::is_same<V, unsigned int>::value
+                                        || std::is_same<V, qulonglong>::value, int> = 0>
+    QVariant deserializeFixed(QByteArray::const_iterator &it) {
+        QVariant newPropertyValue(QVariant::fromValue(*(V*)it));
+        it += sizeof(V);
+        return newPropertyValue;
+    }
+
+    template <typename V,
+              typename std::enable_if_t<std::is_unsigned<V>::value, int> = 0>
+    QVariant deserializeVarint(QByteArray::const_iterator &it) {
+        V value = 0;
+        while((*it) & 0x80) {
+            value += (*it) & 0x7f;
+            ++it;
+        }
+        value += (*it) & 0x7f;
+        it++;
+        return QVariant::fromValue(value);
+    }
+
+    template <typename V,
+              typename std::enable_if_t<std::is_signed<V>::value, int> = 0>
+    QVariant deserializeVarint(QByteArray::const_iterator &it) {
+        V value = 0;
+        while((*it) & 0x80) {
+            value += (*it) & 0x7f;
+            ++it;
+        }
+        value += (*it) & 0x7f;
+        it++;
+
+        return QVariant::fromValue(value);
+    }
 };
 
 }

+ 49 - 0
tests/deserializationtest.cpp

@@ -27,6 +27,9 @@
 #include "qtprotobuf.h"
 #include "simplefixedint32message.h"
 #include "simplefixedint64message.h"
+#include "simplefloatmessage.h"
+#include "simpledoublemessage.h"
+#include "simpleintmessage.h"
 
 using namespace qtprotobufnamespace::tests;
 using namespace qtprotobuf::tests;
@@ -109,3 +112,49 @@ TEST_F(DeserializationTest, FixedInt64MessageDeserializeTest)
     ASSERT_EQ(test.testFieldFixedInt64(), UINT64_MAX);
 }
 
+
+TEST_F(DeserializationTest, FloatMessageDeserializeTest)
+{
+    SimpleFloatMessage test;
+    test.deserialize(QByteArray::fromHex("3dcdcccc3d"));
+    ASSERT_FLOAT_EQ(test.testFieldFloat(), 0.1f);
+
+    test.deserialize(QByteArray::fromHex("3d00008000"));
+    ASSERT_FLOAT_EQ(test.testFieldFloat(), FLT_MIN);
+
+    test.deserialize(QByteArray::fromHex("3dffff7f7f"));
+    ASSERT_FLOAT_EQ(test.testFieldFloat(), FLT_MAX);
+
+    test.deserialize(QByteArray::fromHex("3d666686c0"));
+    ASSERT_FLOAT_EQ(test.testFieldFloat(), -4.2f);
+
+    test.deserialize(QByteArray::fromHex("3d00000000"));
+    ASSERT_FLOAT_EQ(test.testFieldFloat(), -0.0f);
+}
+
+TEST_F(DeserializationTest, DoubleMessageDeserializeTest)
+{
+    SimpleDoubleMessage test;
+    test.deserialize(QByteArray::fromHex("419a9999999999b93f"));
+    ASSERT_DOUBLE_EQ(0.1, test.testFieldDouble());
+
+    test.deserialize(QByteArray::fromHex("410000000000001000"));
+    ASSERT_DOUBLE_EQ(DBL_MIN, test.testFieldDouble());
+
+    test.deserialize(QByteArray::fromHex("41ffffffffffffef7f"));
+    ASSERT_DOUBLE_EQ(DBL_MAX, test.testFieldDouble());
+
+    test.deserialize(QByteArray::fromHex("41cdcccccccccc10c0"));
+    ASSERT_DOUBLE_EQ(-4.2, test.testFieldDouble());
+
+    test.deserialize(QByteArray::fromHex("410000000000000000"));
+    ASSERT_DOUBLE_EQ(0.0, test.testFieldDouble());
+}
+
+TEST_F(DeserializationTest, IntMessageDeserializeTest)
+{
+    SimpleIntMessage test;
+    test.deserialize(QByteArray::fromHex("081e"));
+    ASSERT_EQ(15, test.testFieldInt());
+}
+

+ 0 - 1
tests/serializationtest.cpp

@@ -140,7 +140,6 @@ TEST_F(SerializationTest, IntMessageSerializeTest)
     ASSERT_EQ(result.at(2), '\xe1');
     ASSERT_EQ(result.at(3), '\x07');
 
-
     test.setTestFieldInt(INT8_MIN);
     result = test.serialize();
     ASSERT_EQ(result.size(), 3);