[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-6.4' - 2 commits - include/tools tools/qa tools/source
Noel Grandin (via logerrit)
logerrit at kemper.freedesktop.org
Mon Aug 10 21:07:53 UTC 2020
include/tools/json_writer.hxx | 66 +++++++++++++++++---
tools/qa/cppunit/test_json_writer.cxx | 38 ++++++++++-
tools/source/misc/json_writer.cxx | 112 ++++++++++++++++++++++++++++++----
3 files changed, 190 insertions(+), 26 deletions(-)
New commits:
commit f271eca1eb24ed28658afe4c73d71cbf77a78dec
Author: Noel Grandin <noel.grandin at collabora.co.uk>
AuthorDate: Wed Jun 24 18:24:37 2020 +0200
Commit: Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Mon Aug 10 23:07:32 2020 +0200
fix JsonWriter::reallocBuffer
was not updating mSpaceAllocated
Change-Id: Ie5404e58c6520d32b72c19ddfa58b2ab2b895199
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/97049
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin at collabora.co.uk>
(cherry picked from commit 3fb5c11ac69e6687e579d4129cb892c5ae746a5e)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100445
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
diff --git a/tools/source/misc/json_writer.cxx b/tools/source/misc/json_writer.cxx
index 251c44c0246f..f2b008ea6fd2 100644
--- a/tools/source/misc/json_writer.cxx
+++ b/tools/source/misc/json_writer.cxx
@@ -320,6 +320,7 @@ void JsonWriter::reallocBuffer(int noMoreBytesRequired)
free(mpBuffer);
mpBuffer = pNew;
mPos = mpBuffer + currentUsed;
+ mSpaceAllocated = newSize;
}
/** Hands ownership of the underlying storage buffer to the caller,
commit 29954dbeb16ef206940a8fe7ed94e487f842d17a
Author: Noel Grandin <noelgrandin at gmail.com>
AuthorDate: Thu Jun 18 21:39:30 2020 +0200
Commit: Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Mon Aug 10 23:07:20 2020 +0200
improvements to JSON Writer
part of the master commit cb95276e6e6bf12a1c06d5c252551e55c788fcb2
Change-Id: Icf18fb4b3ebced375196a8cdbd2a543acf4e43c5
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/100444
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice at gmail.com>
Reviewed-by: Tomaž Vajngerl <quikee at gmail.com>
diff --git a/include/tools/json_writer.hxx b/include/tools/json_writer.hxx
index 588577d41303..bf07aa0aaa35 100644
--- a/include/tools/json_writer.hxx
+++ b/include/tools/json_writer.hxx
@@ -13,6 +13,11 @@
#include <memory>
#include <algorithm>
+namespace rtl
+{
+class OStringBuffer;
+}
+
/** Simple JSON encoder designed specifically for LibreOfficeKit purposes.
*
* (1) Minimal allocations/re-allocations/copying
@@ -22,10 +27,14 @@
namespace tools
{
class ScopedJsonWriterNode;
+class ScopedJsonWriterArray;
+class ScopedJsonWriterStruct;
class TOOLS_DLLPUBLIC JsonWriter
{
friend class ScopedJsonWriterNode;
+ friend class ScopedJsonWriterArray;
+ friend class ScopedJsonWriterStruct;
int mSpaceAllocated;
char* mpBuffer;
@@ -38,33 +47,36 @@ public:
~JsonWriter();
[[nodiscard]] ScopedJsonWriterNode startNode(const char*);
+ [[nodiscard]] ScopedJsonWriterArray startArray(const char*);
+ [[nodiscard]] ScopedJsonWriterStruct startStruct();
void put(const char* pPropName, const OUString& rPropValue);
void put(const char* pPropName, const OString& rPropValue);
void put(const char* pPropName, const char* pPropVal);
void put(const char*, int);
- /** Hands ownership of the the underlying storage buffer to the caller,
+ /// This assumes that this data belongs at this point in the stream, and is valid, and properly encoded
+ void putRaw(const rtl::OStringBuffer&);
+
+ /** Hands ownership of the underlying storage buffer to the caller,
* after this no more document modifications may be written. */
char* extractData();
OString extractAsOString();
private:
void endNode();
+ void endArray();
+ void endStruct();
void addCommaBeforeField();
+ void reallocBuffer(int noMoreBytesRequired);
+ // this part inline to speed up the fast path
inline void ensureSpace(int noMoreBytesRequired)
{
+ assert(mpBuffer && "already extracted data");
int currentUsed = mPos - mpBuffer;
if (currentUsed + noMoreBytesRequired >= mSpaceAllocated)
- {
- auto newSize = std::max(mSpaceAllocated * 2, (currentUsed + noMoreBytesRequired) * 2);
- char* pNew = static_cast<char*>(malloc(newSize));
- memcpy(pNew, mpBuffer, currentUsed);
- free(mpBuffer);
- mpBuffer = pNew;
- mPos = mpBuffer;
- }
+ reallocBuffer(noMoreBytesRequired);
}
};
@@ -85,5 +97,41 @@ class ScopedJsonWriterNode
public:
~ScopedJsonWriterNode() { mrWriter.endNode(); }
};
+
+/**
+ * Auto-closes the node.
+ */
+class ScopedJsonWriterArray
+{
+ friend class JsonWriter;
+
+ JsonWriter& mrWriter;
+
+ ScopedJsonWriterArray(JsonWriter& rWriter)
+ : mrWriter(rWriter)
+ {
+ }
+
+public:
+ ~ScopedJsonWriterArray() { mrWriter.endArray(); }
+};
+
+/**
+ * Auto-closes the node.
+ */
+class ScopedJsonWriterStruct
+{
+ friend class JsonWriter;
+
+ JsonWriter& mrWriter;
+
+ ScopedJsonWriterStruct(JsonWriter& rWriter)
+ : mrWriter(rWriter)
+ {
+ }
+
+public:
+ ~ScopedJsonWriterStruct() { mrWriter.endStruct(); }
+};
};
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/tools/qa/cppunit/test_json_writer.cxx b/tools/qa/cppunit/test_json_writer.cxx
index e27afc95f712..6a2cc7813574 100644
--- a/tools/qa/cppunit/test_json_writer.cxx
+++ b/tools/qa/cppunit/test_json_writer.cxx
@@ -30,12 +30,19 @@ public:
virtual void setUp() override {}
void test1();
+ void test2();
CPPUNIT_TEST_SUITE(JsonWriterTest);
CPPUNIT_TEST(test1);
+ CPPUNIT_TEST(test2);
CPPUNIT_TEST_SUITE_END();
};
+struct Free
+{
+ void operator()(void* p) const { std::free(p); }
+};
+
void JsonWriterTest::test1()
{
tools::JsonWriter aJson;
@@ -48,10 +55,6 @@ void JsonWriterTest::test1()
aJson.put("int", 12);
}
- struct Free
- {
- void operator()(void* p) const { std::free(p); }
- };
std::unique_ptr<char, Free> result(aJson.extractData());
CPPUNIT_ASSERT_EQUAL(std::string("{ \"node\": { \"oustring\": \"val1\", \"ostring\": \"val2\", "
@@ -59,6 +62,33 @@ void JsonWriterTest::test1()
std::string(result.get()));
}
+void JsonWriterTest::test2()
+{
+ tools::JsonWriter aJson;
+
+ {
+ auto testNode = aJson.startNode("node");
+ aJson.put("field1", OUString("val1"));
+ aJson.put("field2", OUString("val2"));
+ {
+ auto testNode2 = aJson.startNode("node");
+ aJson.put("field3", OUString("val3"));
+ {
+ auto testNode3 = aJson.startNode("node");
+ aJson.put("field4", OUString("val4"));
+ aJson.put("field5", OUString("val5"));
+ }
+ }
+ }
+
+ std::unique_ptr<char, Free> result(aJson.extractData());
+
+ CPPUNIT_ASSERT_EQUAL(std::string("{ \"node\": { \"field1\": \"val1\", \"field2\": \"val2\", "
+ "\"node\": { \"field3\": \"val3\", \"node\": { \"field4\": "
+ "\"val4\", \"field5\": \"val5\"}}}}"),
+ std::string(result.get()));
+}
+
CPPUNIT_TEST_SUITE_REGISTRATION(JsonWriterTest);
}
diff --git a/tools/source/misc/json_writer.cxx b/tools/source/misc/json_writer.cxx
index ab109dae669c..251c44c0246f 100644
--- a/tools/source/misc/json_writer.cxx
+++ b/tools/source/misc/json_writer.cxx
@@ -10,6 +10,7 @@
#include <tools/json_writer.hxx>
#include <stdio.h>
#include <cstring>
+#include <rtl/strbuf.hxx>
namespace tools
{
@@ -22,6 +23,7 @@ JsonWriter::JsonWriter()
, mpBuffer(static_cast<char*>(malloc(mSpaceAllocated)))
, mStartNodeCount(0)
, mPos(mpBuffer)
+ , mbFirstFieldInNode(true)
{
*mPos = '{';
++mPos;
@@ -38,7 +40,10 @@ JsonWriter::~JsonWriter()
ScopedJsonWriterNode JsonWriter::startNode(const char* pNodeName)
{
auto len = strlen(pNodeName);
- ensureSpace(len + 4);
+ ensureSpace(len + 6);
+
+ addCommaBeforeField();
+
*mPos = '"';
++mPos;
memcpy(mPos, pNodeName, len);
@@ -57,15 +62,70 @@ void JsonWriter::endNode()
ensureSpace(1);
*mPos = '}';
++mPos;
+ mbFirstFieldInNode = false;
}
-void JsonWriter::put(const char* pPropName, const OUString& rPropVal)
+ScopedJsonWriterArray JsonWriter::startArray(const char* pNodeName)
+{
+ auto len = strlen(pNodeName);
+ ensureSpace(len + 6);
+
+ addCommaBeforeField();
+
+ *mPos = '"';
+ ++mPos;
+ memcpy(mPos, pNodeName, len);
+ mPos += len;
+ strncpy(mPos, "\": [ ", 5);
+ mPos += 5;
+ mStartNodeCount++;
+ mbFirstFieldInNode = true;
+ return ScopedJsonWriterArray(*this);
+}
+
+void JsonWriter::endArray()
{
+ assert(mStartNodeCount && "mismatched StartNode/EndNode somewhere");
+ --mStartNodeCount;
+ ensureSpace(1);
+ *mPos = ']';
+ ++mPos;
+ mbFirstFieldInNode = false;
+}
+
+ScopedJsonWriterStruct JsonWriter::startStruct()
+{
+ ensureSpace(6);
+
addCommaBeforeField();
+ *mPos = '{';
+ ++mPos;
+ *mPos = ' ';
+ ++mPos;
+ mStartNodeCount++;
+ mbFirstFieldInNode = true;
+ return ScopedJsonWriterStruct(*this);
+}
+
+void JsonWriter::endStruct()
+{
+ assert(mStartNodeCount && "mismatched StartNode/EndNode somewhere");
+ --mStartNodeCount;
+ ensureSpace(1);
+ *mPos = '}';
+ ++mPos;
+ mbFirstFieldInNode = false;
+}
+
+void JsonWriter::put(const char* pPropName, const OUString& rPropVal)
+{
auto nPropNameLength = strlen(pPropName);
auto nWorstCasePropValLength = rPropVal.getLength() * 2;
- ensureSpace(nPropNameLength + nWorstCasePropValLength + 6);
+ ensureSpace(nPropNameLength + nWorstCasePropValLength + 8);
+
+ addCommaBeforeField();
+
*mPos = '"';
++mPos;
memcpy(mPos, pPropName, nPropNameLength);
@@ -120,11 +180,12 @@ void JsonWriter::put(const char* pPropName, const OUString& rPropVal)
void JsonWriter::put(const char* pPropName, const OString& rPropVal)
{
- addCommaBeforeField();
-
auto nPropNameLength = strlen(pPropName);
auto nWorstCasePropValLength = rPropVal.getLength();
- ensureSpace(nPropNameLength + nWorstCasePropValLength + 6);
+ ensureSpace(nPropNameLength + nWorstCasePropValLength + 8);
+
+ addCommaBeforeField();
+
*mPos = '"';
++mPos;
memcpy(mPos, pPropName, nPropNameLength);
@@ -163,12 +224,13 @@ void JsonWriter::put(const char* pPropName, const OString& rPropVal)
void JsonWriter::put(const char* pPropName, const char* pPropVal)
{
- addCommaBeforeField();
-
auto nPropNameLength = strlen(pPropName);
auto nPropValLength = strlen(pPropVal);
auto nWorstCasePropValLength = nPropValLength * 2;
- ensureSpace(nPropNameLength + nWorstCasePropValLength + 6);
+ ensureSpace(nPropNameLength + nWorstCasePropValLength + 8);
+
+ addCommaBeforeField();
+
*mPos = '"';
++mPos;
memcpy(mPos, pPropName, nPropNameLength);
@@ -210,11 +272,12 @@ void JsonWriter::put(const char* pPropName, const char* pPropVal)
void JsonWriter::put(const char* pPropName, int nPropVal)
{
- addCommaBeforeField();
-
auto nPropNameLength = strlen(pPropName);
auto nWorstCasePropValLength = 32;
- ensureSpace(nPropNameLength + nWorstCasePropValLength + 6);
+ ensureSpace(nPropNameLength + nWorstCasePropValLength + 8);
+
+ addCommaBeforeField();
+
*mPos = '"';
++mPos;
memcpy(mPos, pPropName, nPropNameLength);
@@ -225,6 +288,16 @@ void JsonWriter::put(const char* pPropName, int nPropVal)
mPos += sprintf(mPos, "%d", nPropVal);
}
+void JsonWriter::putRaw(const rtl::OStringBuffer& rRawBuf)
+{
+ ensureSpace(rRawBuf.getLength() + 2);
+
+ addCommaBeforeField();
+
+ memcpy(mPos, rRawBuf.getStr(), rRawBuf.getLength());
+ mPos += rRawBuf.getLength();
+}
+
void JsonWriter::addCommaBeforeField()
{
if (mbFirstFieldInNode)
@@ -238,12 +311,24 @@ void JsonWriter::addCommaBeforeField()
}
}
-/** Hands ownership of the the underlying storage buffer to the caller,
+void JsonWriter::reallocBuffer(int noMoreBytesRequired)
+{
+ int currentUsed = mPos - mpBuffer;
+ auto newSize = std::max<int>(mSpaceAllocated * 2, (currentUsed + noMoreBytesRequired) * 2);
+ char* pNew = static_cast<char*>(malloc(newSize));
+ memcpy(pNew, mpBuffer, currentUsed);
+ free(mpBuffer);
+ mpBuffer = pNew;
+ mPos = mpBuffer + currentUsed;
+}
+
+/** Hands ownership of the underlying storage buffer to the caller,
* after this no more document modifications may be written. */
char* JsonWriter::extractData()
{
assert(mStartNodeCount == 0 && "did not close all nodes");
assert(mpBuffer && "data already extracted");
+ ensureSpace(2);
// add closing brace
*mPos = '}';
++mPos;
More information about the Libreoffice-commits
mailing list