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

List:       kde-commits
Subject:    [dferry] /: Allow to restart an array / dict as empty if not yet written to.
From:       Andreas Hartmetz <ahartmetz () gmail ! com>
Date:       2016-11-04 23:33:44
Message-ID: E1c2nzU-0004G9-Un () code ! kde ! org
[Download RAW message or body]

Git commit 71b024e3cddec25750592df20eee2315f981a771 by Andreas Hartmetz.
Committed on 28/10/2016 at 18:21.
Pushed by ahartmetz into branch 'master'.

Allow to restart an array / dict as empty if not yet written to.

This is needed in client code where the number of elements is not
known at the time beginArray/Dict() is called, but there is
enough information for a late fix-up. As happens to be the case
in QtDBus.
This is just a little hack to solve a specific problem and should
not be the first choice when writing possibly empty arrays.

M  +32   -7    serialization/arguments.cpp
M  +3    -2    serialization/arguments.h
M  +1    -0    util/error.h

http://commits.kde.org/dferry/71b024e3cddec25750592df20eee2315f981a771

diff --git a/serialization/arguments.cpp b/serialization/arguments.cpp
index 8bd2ffd..0e87009 100644
--- a/serialization/arguments.cpp
+++ b/serialization/arguments.cpp
@@ -2228,9 +2228,34 @@ void Arguments::Writer::advanceState(cstring \
signatureFragment, IoState newState  m_state = AnyData;
 }
 
-void Arguments::Writer::beginArrayOrDict(bool isDict, bool isEmpty)
+void Arguments::Writer::beginArrayOrDict(IoState beginWhat, ArrayOption option)
 {
-    isEmpty = isEmpty || d->m_nilArrayNesting;
+    assert(beginWhat == BeginArray || beginWhat == BeginDict);
+    if (unlikely(option == RestartEmptyArrayToWriteTypes)) {
+        if (!d->m_aggregateStack.empty()) {
+            Private::AggregateInfo &aggregateInfo = d->m_aggregateStack.back();
+            if (aggregateInfo.aggregateType == beginWhat) {
+                // No writes to the array or dict may have occurred yet
+                if (d->m_signature.length == aggregateInfo.arr.containedTypeBegin) {
+                    // Fix up state as if beginArray/Dict() had been called with \
WriteTypesOfEmptyArray +                    // in the first place. After that small \
fixup we're done and return. +                    // The code is a slightly modified \
version of code below under: if (isEmpty) { +                    if \
(!d->m_nilArrayNesting) { +                        d->m_nilArrayNesting = 1;
+                        d->m_dataElementsCountBeforeNilArray = d->m_elements.size() \
+ 1; +                        d->m_dataPositionBeforeNilArray = d->m_dataPosition;
+                    } else {
+                        // The array may be implicitly nil (so our poor API client \
doesn't notice) because +                        // an array below in the aggregate \
stack is nil, so just allow this as a no-op. +                    }
+                    return;
+                }
+            }
+        }
+        VALID_IF(false, Error::InvalidStateToRestartEmptyArray);
+    }
+
+    const bool isEmpty = (option != NonEmptyArray) || d->m_nilArrayNesting;
     if (isEmpty) {
         if (!d->m_nilArrayNesting++) {
             // For simplictiy and performance in the fast path, we keep storing the \
data chunks and any @@ -2241,16 +2266,16 @@ void \
Arguments::Writer::beginArrayOrDict(bool isDict, bool isEmpty)  \
d->m_dataPositionBeforeNilArray = d->m_dataPosition;  }
     }
-    if (isDict) {
-        advanceState(cstring("a{", strlen("a{")), BeginDict);
+    if (beginWhat == BeginArray) {
+        advanceState(cstring("a", strlen("a")), beginWhat);
     } else {
-        advanceState(cstring("a", strlen("a")), BeginArray);
+        advanceState(cstring("a{", strlen("a{")), beginWhat);
     }
 }
 
 void Arguments::Writer::beginArray(ArrayOption option)
 {
-    beginArrayOrDict(false, option == WriteTypesOfEmptyArray);
+    beginArrayOrDict(BeginArray, option);
 }
 
 void Arguments::Writer::endArray()
@@ -2260,7 +2285,7 @@ void Arguments::Writer::endArray()
 
 void Arguments::Writer::beginDict(ArrayOption option)
 {
-    beginArrayOrDict(true, option == WriteTypesOfEmptyArray);
+    beginArrayOrDict(BeginDict, option);
 }
 
 void Arguments::Writer::endDict()
diff --git a/serialization/arguments.h b/serialization/arguments.h
index 5eb6087..4081e26 100644
--- a/serialization/arguments.h
+++ b/serialization/arguments.h
@@ -296,7 +296,8 @@ public:
         enum ArrayOption
         {
             NonEmptyArray = 0,
-            WriteTypesOfEmptyArray
+            WriteTypesOfEmptyArray,
+            RestartEmptyArrayToWriteTypes
         };
 
         void beginArray(ArrayOption option = NonEmptyArray);
@@ -340,7 +341,7 @@ public:
         void doWritePrimitiveType(uint32 alignAndSize);
         void doWriteString(uint32 lengthPrefixSize);
         void advanceState(cstring signatureFragment, IoState newState);
-        void beginArrayOrDict(bool isDict, bool isEmpty);
+        void beginArrayOrDict(IoState beginWhat, ArrayOption option);
         void finishInternal();
 
         Private *d;
diff --git a/util/error.h b/util/error.h
index 38c283d..247da72 100644
--- a/util/error.h
+++ b/util/error.h
@@ -72,6 +72,7 @@ public:
         CannotEndArrayOrDictHere,
         TooFewTypesInArrayOrDict,
         ExtraIterationInEmptyArray,
+        InvalidStateToRestartEmptyArray,
         InvalidKeyTypeInDict,
         GreaterTwoTypesInDict,
         ArrayOrDictTooLong,


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

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