[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