Added JSON_PROXY to copy arrays and objects by reference

This commit is contained in:
Benoit Blanchon
2014-10-09 18:20:40 +02:00
parent bf2d726746
commit 35eaa55b3a
12 changed files with 138 additions and 66 deletions

View File

@ -3,11 +3,16 @@
#include "JsonWriter.h"
#include "../JsonArray.h"
#include "../JsonObject.h"
#include "../JsonBuffer.h"
void JsonNode::writeTo(JsonWriter& writer)
{
switch (type)
{
case JSON_PROXY:
content.asProxy.target->writeTo(writer);
break;
case JSON_ARRAY:
writeArrayTo(writer);
break;
@ -36,7 +41,11 @@ void JsonNode::writeTo(JsonWriter& writer)
void JsonNode::addChild(JsonNode* childToAdd)
{
if (type != JSON_ARRAY && type != JSON_OBJECT) return;
if (type == JSON_PROXY)
return content.asProxy.target->addChild(childToAdd);
if (type != JSON_ARRAY && type != JSON_OBJECT)
return;
JsonNode* lastChild = content.asContainer.child;
@ -54,6 +63,9 @@ void JsonNode::addChild(JsonNode* childToAdd)
void JsonNode::removeChild(JsonNode* childToRemove)
{
if (type == JSON_PROXY)
return content.asProxy.target->removeChild(childToRemove);
if (type != JSON_ARRAY && type != JSON_OBJECT) return;
if (content.asContainer.child == childToRemove)
@ -121,4 +133,17 @@ void JsonNode::writeObjectTo(JsonWriter& writer)
{
writer.writeEmptyObject();
}
}
void JsonNode::setAsProxyOfSelf()
{
JsonBuffer* buffer = content.asContainer.buffer;
if (!buffer) return;
JsonNode* newNode = buffer->createNode();
if (!newNode) return;
*newNode = *this;
setAsProxyOf(newNode);
}

View File

@ -18,6 +18,7 @@ class JsonNode
JSON_BOOLEAN,
JSON_STRING,
JSON_LONG,
JSON_PROXY,
JSON_DOUBLE_0_DECIMALS,
JSON_DOUBLE_1_DECIMAL,
JSON_DOUBLE_2_DECIMALS,
@ -126,11 +127,13 @@ public:
JsonBuffer* getContainerBuffer()
{
if (type == JSON_PROXY) return content.asProxy.target->getContainerBuffer();
return type == JSON_ARRAY || type == JSON_OBJECT ? content.asContainer.buffer : 0;
}
JsonNode* getContainerChild()
{
if (type == JSON_PROXY) return content.asProxy.target->getContainerChild();
return type == JSON_ARRAY || type == JSON_OBJECT ? content.asContainer.child : 0;
}
@ -148,6 +151,23 @@ public:
void removeChild(JsonNode* childToRemove);
void duplicate(JsonNode* other)
{
if (!other)
{
type = JSON_UNDEFINED;
}
else if (other->type == JSON_ARRAY || other->type==JSON_OBJECT)
{
other->setAsProxyOfSelf();
setAsProxyOf(other->content.asProxy.target);
}
else
{
*this = *other;
}
}
private:
JsonNode* next;
JsonNodeContent content;
@ -155,4 +175,12 @@ private:
inline void writeArrayTo(JsonWriter&);// TODO: <- move in JsonNodeSerializer
inline void writeObjectTo(JsonWriter&);// TODO: <- move in JsonNodeSerializer
void setAsProxyOfSelf();
void setAsProxyOf(JsonNode* target)
{
type = JSON_PROXY;
content.asProxy.target = target;
}
};

View File

@ -0,0 +1,37 @@
#pragma once
#include "JsonNode.h"
class JsonValue;
class JsonNodeWrapper
{
friend JsonValue;
public:
JsonNodeWrapper()
: _node(0)
{
}
explicit JsonNodeWrapper(JsonNode* node)
: _node(node)
{
}
protected:
void duplicate(const JsonNodeWrapper& other)
{
if (!_node)
{
_node = other._node;
}
else
{
_node->duplicate(other._node);
}
}
JsonNode* _node;
};

View File

@ -50,6 +50,7 @@ void JsonArray::add(long value)
addChild(node);
}
// TODO: we should have the same issue as in JsonValue
void JsonArray::add(JsonContainer nestedContainer)
{
JsonNode* node = createNode();

View File

@ -6,6 +6,7 @@
class JsonBuffer
{
friend class JsonContainer;
friend class JsonNode;
public:
virtual ~JsonBuffer() {};

View File

@ -4,24 +4,23 @@
#include "Internals/JsonNodeIterator.h"
#include "Internals/JsonNode.h"
#include "Internals/IndentedPrint.h"
#include "Internals/JsonNodeWrapper.h"
class JsonArray;
class JsonObject;
class JsonValue;
class JsonContainer : public Printable
class JsonContainer : public Printable, public JsonNodeWrapper
{
friend JsonValue;
// friend JsonValue;
friend JsonArray;
public:
JsonContainer()
: _node(0)
{
}
JsonContainer(JsonNode* node)
: _node(node)
JsonContainer() {}
explicit JsonContainer(JsonNode* node)
: JsonNodeWrapper(node)
{
}
@ -54,7 +53,5 @@ protected:
void addChild(JsonNode*);
void removeChild(JsonNode*);
JsonNode* createNode();
JsonNode* _node;
};

View File

@ -28,32 +28,6 @@ void JsonValue::operator=(int value)
_node->setAsLong(value);
}
// TODO: it's a duplicate
void JsonValue::operator=(const JsonContainer& object)
{
if (!_node)
{
_node = object._node;
}
else
{
*_node = *object._node;
}
}
// TODO: it's a duplicate
void JsonValue::operator=(JsonValue const& value)
{
if (!_node)
{
_node = value._node;
}
else
{
*_node = *value._node;
}
}
JsonValue::operator bool() const
{
return _node ? _node->getAsBoolean() : false;

View File

@ -1,21 +1,19 @@
#pragma once
#include "Internals/JsonNodeWrapper.h"
class JsonArray;
class JsonContainer;
class JsonObject;
class JsonNode;
class JsonValue
class JsonValue : public JsonNodeWrapper
{
public:
explicit JsonValue()
: _node(0)
{
}
JsonValue() {}
explicit JsonValue(JsonNode* node)
: _node(node)
: JsonNodeWrapper(node)
{
}
@ -23,9 +21,9 @@ public:
void operator=(const char*);
void operator=(double x) { set(x, 2); }
void operator=(int);
void operator=(const JsonContainer&);
void operator=(const JsonValue&);
void operator=(const JsonValue& value) { duplicate(value); }
void operator=(const JsonNodeWrapper& object) { duplicate(object); }
operator bool() const;
operator const char*() const;
operator double() const;
@ -35,7 +33,4 @@ public:
operator JsonObject() const;
void set(double value, int decimals);
private:
JsonNode* _node;
};

View File

@ -83,6 +83,7 @@
<ClInclude Include="Internals\JsonWriter.h" />
<ClInclude Include="JsonContainer.h" />
<ClInclude Include="Internals\JsonNodeIterator.h" />
<ClInclude Include="Internals\JsonNodeWrapper.h" />
<ClInclude Include="JsonObject.h" />
<ClInclude Include="JsonValue.h" />
<ClInclude Include="Arduino\Print.h" />

View File

@ -63,6 +63,9 @@
<ClInclude Include="Internals\IndentedPrint.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Internals\JsonNodeWrapper.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="JsonObject.cpp">

View File

@ -123,21 +123,35 @@ TEST_F(JsonObject_Serialization_Tests, OneFalse)
object["key"] = false;
outputMustBe("{\"key\":false}");
}
/*
TEST_F(JsonObject_Serialization_Tests, OneEmptyNestedArray)
TEST_F(JsonObject_Serialization_Tests, OneEmptyNestedArrayViaProxy)
{
auto nestedArray = JsonArray<1>();
auto nestedArray = json.createArray();
object["key"] = nestedArray;
outputMustBe("{\"key\":[]}");
}
*/
TEST_F(JsonObject_Serialization_Tests, OneEmptyNestedObject)
{
auto nestedObject = json.createObject();
object["key"] = nestedObject;
TEST_F(JsonObject_Serialization_Tests, OneEmptyNestedObjectViaProxy)
{
auto nestedArray = json.createObject();
object["key"] = nestedArray;
outputMustBe("{\"key\":{}}");
}
TEST_F(JsonObject_Serialization_Tests, OneEmptyNestedObject)
{
object.createNestedObject("key");
outputMustBe("{\"key\":{}}");
}
TEST_F(JsonObject_Serialization_Tests, OneEmptyNestedArray)
{
object.createNestedArray("key");
outputMustBe("{\"key\":[]}");
}

View File

@ -101,12 +101,10 @@ TEST_F(JsonValueTests, ObjectsAreCopiedByReference)
JsonObject object = json.createObject();
jsonValue1 = object;
jsonValue2 = jsonValue1;
object["hello"] = "world";
jsonValue1 = 0;
EXPECT_EQ(1, ((JsonObject) jsonValue2).size());
EXPECT_EQ(1, ((JsonObject) jsonValue1).size());
}
TEST_F(JsonValueTests, ArraysAreCopiedByReference)
@ -114,10 +112,8 @@ TEST_F(JsonValueTests, ArraysAreCopiedByReference)
JsonArray array = json.createArray();
jsonValue1 = array;
jsonValue2 = jsonValue1;
jsonValue1 = 0;
array.add("world");
EXPECT_EQ(1, ((JsonObject) jsonValue2).size());
EXPECT_EQ(1, ((JsonObject) jsonValue1).size());
}