[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [dferry] /: Help reduce boilerplate when copying from Reader to Writer.
From:       Andreas Hartmetz <ahartmetz () gmail ! com>
Date:       2016-11-17 1:34:24
Message-ID: E1c7Baq-0002rY-Sl () code ! kde ! org
[Download RAW message or body]

Git commit 73cef05cdc1655cb0d1e0f6cbe8873d5548c82c7 by Andreas Hartmetz.
Committed on 17/11/2016 at 00:46.
Pushed by ahartmetz into branch 'master'.

Help reduce boilerplate when copying from Reader to Writer.

This is not only useful in the tests.

M  +107  -0    serialization/arguments.cpp
M  +5    -0    serialization/arguments.h
M  +14   -46   tests/serialization/tst_arguments.cpp

http://commits.kde.org/dferry/73cef05cdc1655cb0d1e0f6cbe8873d5548c82c7

diff --git a/serialization/arguments.cpp b/serialization/arguments.cpp
index 731f23b..3d61e3d 100644
--- a/serialization/arguments.cpp
+++ b/serialization/arguments.cpp
@@ -51,6 +51,113 @@ static byte alignmentLog2(uint32 alignment)
     return alignLog[alignment];
 }
 
+// When using this to iterate over the reader, it will make an exact copy \
using the Writer. +// You need to do something only in states where \
something special should happen. +// To check errors, "simply" (sorry!) \
check the reader->state() and writer()->state(). +// Note that you don't \
have to check the state before each element, it is fine to call +// read / \
write functions in error state, including with garbage data from the \
possibly +// invalid reader, and the reader / writer state will remain \
frozen in the state in which +// the first error occurred
+// TODO: that text above belongs into a "Reader and Writer state / errors" \
explanation of the docs +
+// static
+void Arguments::copyOneElement(Arguments::Reader *reader, \
Arguments::Writer *writer) +{
+    switch(reader->state()) {
+    case Arguments::BeginStruct:
+        reader->beginStruct();
+        writer->beginStruct();
+        break;
+    case Arguments::EndStruct:
+        reader->endStruct();
+        writer->endStruct();
+        break;
+    case Arguments::BeginVariant:
+        reader->beginVariant();
+        writer->beginVariant();
+        break;
+    case Arguments::EndVariant:
+        reader->endVariant();
+        writer->endVariant();
+        break;
+    case Arguments::BeginArray: {
+        // Application note: to avoid handling arrays as primitive (where \
applicable), just don't +        // call this function in BeginArray state \
and do as in the else case. +        const Arguments::IoState primitiveType \
= reader->peekPrimitiveArray(); +        if (primitiveType != BeginArray) { \
// InvalidData can't happen because the state *is* BeginArray +            \
const std::pair<Arguments::IoState, chunk> arrayData = \
reader->readPrimitiveArray(); +            \
writer->writePrimitiveArray(arrayData.first, arrayData.second); +        } \
else { +            const bool hasData = \
reader->beginArray(Arguments::Reader::ReadTypesOnlyIfEmpty); +            \
writer->beginArray(hasData ? Arguments::Writer::NonEmptyArray +             \
: Arguments::Writer::WriteTypesOfEmptyArray); +        }
+        break; }
+    case Arguments::EndArray:
+        reader->endArray();
+        writer->endArray();
+        break;
+    case Arguments::BeginDict: {
+        const bool hasData = \
reader->beginDict(Arguments::Reader::ReadTypesOnlyIfEmpty); +        \
writer->beginDict(hasData ? Arguments::Writer::NonEmptyArray +              \
: Arguments::Writer::WriteTypesOfEmptyArray); +        break; }
+    case Arguments::EndDict:
+        reader->endDict();
+        writer->endDict();
+        break;
+    case Arguments::Byte:
+        writer->writeByte(reader->readByte());
+        break;
+    case Arguments::Boolean:
+        writer->writeBoolean(reader->readBoolean());
+        break;
+    case Arguments::Int16:
+        writer->writeInt16(reader->readInt16());
+        break;
+    case Arguments::Uint16:
+        writer->writeUint16(reader->readUint16());
+        break;
+    case Arguments::Int32:
+        writer->writeInt32(reader->readInt32());
+        break;
+    case Arguments::Uint32:
+        writer->writeUint32(reader->readUint32());
+        break;
+    case Arguments::Int64:
+        writer->writeInt64(reader->readInt64());
+        break;
+    case Arguments::Uint64:
+        writer->writeUint64(reader->readUint64());
+        break;
+    case Arguments::Double:
+        writer->writeDouble(reader->readDouble());
+        break;
+    case Arguments::String: {
+        const cstring s = reader->readString();
+        writer->writeString(s);
+        break; }
+    case Arguments::ObjectPath: {
+        const cstring objectPath = reader->readObjectPath();
+        writer->writeObjectPath(objectPath);
+        break; }
+    case Arguments::Signature: {
+        const cstring signature = reader->readSignature();
+        writer->writeSignature(signature);
+        break; }
+    case Arguments::UnixFd:
+        writer->writeUnixFd(reader->readUnixFd());
+        break;
+    // special cases follow
+    case Arguments::Finished:
+        break; // You *probably* want to handle that one in the caller, \
but you don't have to +    case Arguments::NeedMoreData:
+        break; // No way to handle that one here
+    default:
+        break; // dito
+    }
+}
+
 // helper to verify the max nesting requirements of the d-bus spec
 struct Nesting
 {
diff --git a/serialization/arguments.h b/serialization/arguments.h
index 5d86866..781baed 100644
--- a/serialization/arguments.h
+++ b/serialization/arguments.h
@@ -37,6 +37,9 @@ class Message;
 class DFERRY_EXPORT Arguments
 {
 public:
+    class Reader;
+    class Writer;
+
     enum SignatureType
     {
         MethodSignature = 0,
@@ -126,6 +129,8 @@ public:
     static bool isObjectPathElementValid(cstring pathElement);
     static bool isSignatureValid(cstring signature, SignatureType type = \
MethodSignature);  
+    static void copyOneElement(Reader *reader, Writer *writer);
+
 private:
     struct podCstring // Same as cstring but without ctor.
                       // Can't put the cstring type into a union because \
                it has a constructor :/
diff --git a/tests/serialization/tst_arguments.cpp \
b/tests/serialization/tst_arguments.cpp index c8a04fd..d2dabf9 100644
--- a/tests/serialization/tst_arguments.cpp
+++ b/tests/serialization/tst_arguments.cpp
@@ -288,66 +288,34 @@ static void defaultReadToWrite(Arguments::Reader \
*reader, Arguments::Writer *wri  {
     switch(reader->state()) {
     case Arguments::BeginStruct:
-        reader->beginStruct();
-        writer->beginStruct();
-        break;
     case Arguments::EndStruct:
-        reader->endStruct();
-        writer->endStruct();
-        break;
     case Arguments::BeginVariant:
-        reader->beginVariant();
-        writer->beginVariant();
-        break;
     case Arguments::EndVariant:
-        reader->endVariant();
-        writer->endVariant();
-        break;
-    case Arguments::BeginArray: {
-        const bool hasData = \
                reader->beginArray(Arguments::Reader::ReadTypesOnlyIfEmpty);
                
-        writer->beginArray(hasData ? Arguments::Writer::NonEmptyArray
-                                    : \
                Arguments::Writer::WriteTypesOfEmptyArray);
-        break; }
     case Arguments::EndArray:
-        reader->endArray();
-        writer->endArray();
-        break;
-    case Arguments::BeginDict: {
-        const bool hasData = \
                reader->beginDict(Arguments::Reader::ReadTypesOnlyIfEmpty);
-        writer->beginDict(hasData ? Arguments::Writer::NonEmptyArray
-                                    : \
                Arguments::Writer::WriteTypesOfEmptyArray);
-        break; }
     case Arguments::EndDict:
-        reader->endDict();
-        writer->endDict();
-        break;
     case Arguments::Byte:
-        writer->writeByte(reader->readByte());
-        break;
     case Arguments::Boolean:
-        writer->writeBoolean(reader->readBoolean());
-        break;
     case Arguments::Int16:
-        writer->writeInt16(reader->readInt16());
-        break;
     case Arguments::Uint16:
-        writer->writeUint16(reader->readUint16());
-        break;
     case Arguments::Int32:
-        writer->writeInt32(reader->readInt32());
-        break;
     case Arguments::Uint32:
-        writer->writeUint32(reader->readUint32());
-        break;
     case Arguments::Int64:
-        writer->writeInt64(reader->readInt64());
-        break;
     case Arguments::Uint64:
-        writer->writeUint64(reader->readUint64());
-        break;
     case Arguments::Double:
-        writer->writeDouble(reader->readDouble());
+    case Arguments::UnixFd:
+        Arguments::copyOneElement(reader, writer);
         break;
+    // special handling for BeginArray and BeginDict to avoid "fast copy" \
for primitive arrays +    case Arguments::BeginArray: {
+        const bool hasData = \
reader->beginArray(Arguments::Reader::ReadTypesOnlyIfEmpty); +        \
writer->beginArray(hasData ? Arguments::Writer::NonEmptyArray +             \
: Arguments::Writer::WriteTypesOfEmptyArray); +        break; }
+    case Arguments::BeginDict: {
+        const bool hasData = \
reader->beginDict(Arguments::Reader::ReadTypesOnlyIfEmpty); +        \
writer->beginDict(hasData ? Arguments::Writer::NonEmptyArray +              \
: Arguments::Writer::WriteTypesOfEmptyArray); +        break; }
     case Arguments::String: {
         const cstring s = reader->readString();
         if (!reader->isInsideEmptyArray()) {
@@ -369,7 +337,7 @@ static void defaultReadToWrite(Arguments::Reader \
*reader, Arguments::Writer *wri  }
         writer->writeSignature(signature);
         break; }
-    case Arguments::UnixFd:
+
         writer->writeUnixFd(reader->readUnixFd());
         break;
     // special cases follow


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic