Browse Source

Implement varint for unsigned integers

- Implement varint for unsigned integers
- Implement couple tests for varint
Alexey Edelev 6 years ago
parent
commit
75fb5bbb21
4 changed files with 73 additions and 8 deletions
  1. 27 2
      src/lib/protobufobject.h
  2. 1 1
      tests/proto/simpletest.proto
  3. 44 4
      tests/serializationtest.cpp
  4. 1 1
      tests/simpletest.cpp

+ 27 - 2
src/lib/protobufobject.h

@@ -32,6 +32,7 @@
 #include <QBitArray>
 
 #include <unordered_map>
+#include <type_traits>
 
 namespace qtprotobuf {
 
@@ -58,7 +59,7 @@ public:
             const char* propertyName = T::staticMetaObject.property(propertyIndex).name();
             switch(T::staticMetaObject.property(propertyIndex).type()) {
             case QVariant::Int:
-                result.append(serializeInt(instance->property(propertyName).toInt(), fieldIndex));
+                result.append(serializeVarint(instance->property(propertyName).toInt(), fieldIndex));
                 break;
             }
         }
@@ -71,10 +72,34 @@ public:
         //TODO
     }
 
-    QByteArray serializeInt(int value, int fieldIndex) {
+    template <typename V, typename = typename std::enable_if<std::is_integral<V>::value>::type>
+    QByteArray serializeVarint(V value, int fieldIndex) {
+        /*  Header byte
+         *  bits    | 7 6 5 4   3 | 2 1 0
+         *  ----------------------------
+         *  meaning | Field index | Type
+         */
         char typeByte = (fieldIndex << 3) | Varint;
         QByteArray result;
+        //Reserve maximum required amount of bytes
+        result.reserve(sizeof(V) + 1);
+        //Put type byte at beginning
         result.append(typeByte);
+
+        while(value > 0) {
+            //Put first 7 bits to result buffer and mark as not last
+            result.append(value & 0x7F | 0x80);
+            //Devide values to chunks of 7 bits, move to next chunk
+            value >>= 7;
+        }
+
+        //Zero case
+        if (result.size() == 1) {
+            result.append('\0');
+        }
+
+        //Mark last chunk as last
+        result.data()[result.size() - 1] &= ~0x80;
         return result;
     }
 };

+ 1 - 1
tests/proto/simpletest.proto

@@ -3,7 +3,7 @@ syntax = "proto3";
 package qtprotobuf.tests;
 
 message SimpleIntMessage {
-    int32 testFieldInt = 5;
+    int32 testFieldInt = 1;
 }
 
 message SimpleStringMessage {

+ 44 - 4
tests/serializationtest.cpp

@@ -38,14 +38,54 @@ TEST_F(SerializationTest, IntMessageSrializeTest)
     SimpleIntMessage test;
     test.setTestFieldInt(15);
     QByteArray result = test.serialize();
-    ASSERT_EQ(result.at(0), 40);
+    qDebug() << "Out result:" << result.toHex();
+    ASSERT_EQ(result.size(), 2);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), 0x0F);
 
-    test.setTestFieldInt(315);
+    test.setTestFieldInt(300);
     result = test.serialize();
-    ASSERT_EQ(result.at(0), 40);
+    qDebug() << "Out result:" << result.toHex();
+    ASSERT_EQ(result.size(), 3);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\xAC');
+    ASSERT_EQ(result.at(2), 0x02);
 
     test.setTestFieldInt(65545);
     result = test.serialize();
-    ASSERT_EQ(result.at(0), 40);
+    qDebug() << "Out result:" << result.toHex();
+    ASSERT_EQ(result.size(), 4);
+    ASSERT_EQ(result.at(0), 0x08);
+    ASSERT_EQ(result.at(1), '\x89');
+    ASSERT_EQ(result.at(2), '\x80');
+    ASSERT_EQ(result.at(3), '\x04');
+
+    test.setTestFieldInt(0);
+    result = test.serialize();
+    qDebug() << "Out result:" << result.toHex();
+
+    test.setTestFieldInt(INT8_MAX + 1);
+    result = test.serialize();
+    qDebug() << "Out result:" << result.toHex();
+
+    test.setTestFieldInt(INT16_MAX + 1);
+    result = test.serialize();
+    qDebug() << "Out result:" << result.toHex();
+
+    test.setTestFieldInt(INT8_MAX);
+    result = test.serialize();
+    qDebug() << "Out result:" << result.toHex();
+
+    test.setTestFieldInt(INT16_MAX);
+    result = test.serialize();
+    qDebug() << "Out result:" << result.toHex();
+
+    test.setTestFieldInt(INT32_MAX);
+    result = test.serialize();
+    qDebug() << "Out result:" << result.toHex();
+
+    test.setTestFieldInt(INT32_MIN);
+    result = test.serialize();
+    qDebug() << "Out result:" << result.toHex();
 }
 

+ 1 - 1
tests/simpletest.cpp

@@ -42,7 +42,7 @@ TEST_F(SimpleTest, SimpleIntMessageTest)
 {
     const char* propertyName = "testFieldInt";
     SimpleIntMessage test;
-    int propertyNumber = SimpleIntMessage::propertyOrdering.at(5); //See simpletest.proto
+    int propertyNumber = SimpleIntMessage::propertyOrdering.at(1); //See simpletest.proto
     ASSERT_EQ(SimpleIntMessage::staticMetaObject.property(propertyNumber).type(), QVariant::Int);
     ASSERT_STREQ(SimpleIntMessage::staticMetaObject.property(propertyNumber).name(), propertyName);
     ASSERT_TRUE(test.setProperty(propertyName, QVariant::fromValue(1)));