diff options
author | Noel Grandin <noelgrandin@gmail.com> | 2020-06-18 21:39:30 +0200 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2020-08-10 23:07:20 +0200 |
commit | 29954dbeb16ef206940a8fe7ed94e487f842d17a (patch) | |
tree | f2f11352b7df4e3cfc68e8afdb86e894cb59d1e2 /tools | |
parent | cf6388b6a5f3e3baa54ed8b02020e9a25487b32b (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.cxx | 38 | ||||
-rw-r--r-- | tools/source/misc/json_writer.cxx | 111 |
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; |