summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorNoel Grandin <noelgrandin@gmail.com>2020-06-18 21:39:30 +0200
committerTomaž Vajngerl <quikee@gmail.com>2020-08-10 23:07:20 +0200
commit29954dbeb16ef206940a8fe7ed94e487f842d17a (patch)
treef2f11352b7df4e3cfc68e8afdb86e894cb59d1e2 /tools
parentcf6388b6a5f3e3baa54ed8b02020e9a25487b32b (diff)
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@gmail.com> Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/qa/cppunit/test_json_writer.cxx38
-rw-r--r--tools/source/misc/json_writer.cxx111
2 files changed, 132 insertions, 17 deletions
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;