diff --git a/include/ArduinoJson/JsonArray.hpp b/include/ArduinoJson/JsonArray.hpp index 88bde904..0d944ef6 100644 --- a/include/ArduinoJson/JsonArray.hpp +++ b/include/ArduinoJson/JsonArray.hpp @@ -14,16 +14,16 @@ namespace ArduinoJson { class JsonArray : public JsonPrintable { + friend class JsonBuffer; + public: typedef JsonValue value_type; typedef JsonArrayIterator iterator; typedef JsonArrayConstIterator const_iterator; - JsonArray(JsonBuffer *buffer = NULL) : _buffer(buffer), _firstNode(NULL) {} - int size() const; - bool success() {return _buffer != NULL;} + bool success() { return _buffer != NULL; } value_type &operator[](int index) const; value_type &add(); @@ -33,13 +33,9 @@ class JsonArray : public JsonPrintable { add().set(value); } - void add(JsonArray &nestedArray) { - add().set(nestedArray); - } - - void add(JsonObject&nestedObject){ - add().set(nestedObject); - } + void add(double value, int decimals) { add().set(value, decimals); } + void add(JsonArray &nestedArray) { add().set(nestedArray); } + void add(JsonObject &nestedObject) { add().set(nestedObject); } JsonArray &createNestedArray(); JsonObject &createNestedObject(); @@ -55,8 +51,12 @@ class JsonArray : public JsonPrintable { virtual void writeTo(Internals::JsonWriter &writer) const; private: - JsonArray(const JsonArray&); // copy is forbidden, use a reference instead - JsonArray& operator=(const JsonArray&); // copy is forbidden, use a reference instead + // constructor is private: instance must be created via a JsonBuffer + JsonArray(JsonBuffer *buffer) : _buffer(buffer), _firstNode(NULL) {} + + JsonArray(const JsonArray &); // copy is forbidden, use a reference instead + JsonArray &operator=( + const JsonArray &); // copy is forbidden, use a reference instead inline void addNode(Internals::JsonArrayNode *node); diff --git a/include/ArduinoJson/JsonObject.hpp b/include/ArduinoJson/JsonObject.hpp index 9bfc8b59..cff469e3 100644 --- a/include/ArduinoJson/JsonObject.hpp +++ b/include/ArduinoJson/JsonObject.hpp @@ -14,14 +14,14 @@ namespace ArduinoJson { class JsonObject : public JsonPrintable { + friend class JsonBuffer; + public: typedef const char *key_type; typedef JsonPair value_type; typedef JsonObjectIterator iterator; typedef JsonObjectConstIterator const_iterator; - JsonObject(JsonBuffer *buffer) : _buffer(buffer), _firstNode(NULL) {} - int size() const; JsonValue &operator[](key_type key); @@ -29,16 +29,11 @@ class JsonObject : public JsonPrintable { template void add(key_type key, T value) { - (*this)[key] = value; + add(key).set(value); } - void add(key_type key, JsonArray &nestedArray) { - (*this)[key] = nestedArray; - } - - void add(key_type key, JsonObject &nestedObject) { - (*this)[key] = nestedObject; - } + void add(key_type key, JsonArray &array) { add(key).set(array); } + void add(key_type key, JsonObject &object) { add(key).set(object); } JsonArray &createNestedArray(key_type key); JsonObject &createNestedObject(key_type key); @@ -54,9 +49,14 @@ class JsonObject : public JsonPrintable { virtual void writeTo(Internals::JsonWriter &writer) const; private: - JsonObject(const JsonObject&); // copy is forbidden, use a reference instead - JsonObject& operator=(const JsonObject&); // copy is forbidden, use a reference instead + // constructor is private, instance must be created via JsonBuffer + JsonObject(JsonBuffer *buffer) : _buffer(buffer), _firstNode(NULL) {} + JsonObject(const JsonObject &); // copy is forbidden, use a reference instead + JsonObject &operator=( + const JsonObject &); // copy is forbidden, use a reference instead + + JsonValue &add(key_type key) { return (*this)[key]; } void addNode(Internals::JsonObjectNode *nodeToAdd); void removeNode(Internals::JsonObjectNode *nodeToRemove); diff --git a/include/ArduinoJson/JsonValue.hpp b/include/ArduinoJson/JsonValue.hpp index 4f598bee..df90a9be 100644 --- a/include/ArduinoJson/JsonValue.hpp +++ b/include/ArduinoJson/JsonValue.hpp @@ -32,25 +32,30 @@ class JsonValue { return *this; } - JsonValue &operator=(JsonArray& array) { + JsonValue &operator=(JsonArray &array) { set(array); return *this; } - JsonValue &operator=(JsonObject& object) { + JsonValue &operator=(JsonObject &object) { set(object); return *this; } - JsonArray &asArray(); - JsonObject &asObject(); - bool asBool() const; - const char *asString() const; - double asDouble() const; - long asLong() const; + operator bool() const; + operator const char *() const; + operator double() const; + operator long() const; + operator JsonArray &() const; + operator JsonObject &() const; + + JsonArray &asArray() { return static_cast(*this); }; + JsonObject &asObject() { return static_cast(*this); }; template - T as(){} + T as() { + return static_cast(*this); + } static JsonValue &invalid() { return _invalid; } @@ -63,8 +68,3 @@ class JsonValue { Internals::JsonValueContent _content; static JsonValue _invalid; }; - -template <> -int JsonValue::as() { return asLong(); } - -} diff --git a/src/JsonValue.cpp b/src/JsonValue.cpp index 4d64b221..06cb26b9 100644 --- a/src/JsonValue.cpp +++ b/src/JsonValue.cpp @@ -12,27 +12,27 @@ using namespace ArduinoJson; using namespace ArduinoJson::Internals; -JsonArray &JsonValue::asArray() { +JsonValue::operator JsonArray &() const { return _type == JSON_ARRAY ? *_content.asArray : JsonArray::invalid(); } -JsonObject &JsonValue::asObject() { +JsonValue::operator JsonObject &() const { return _type == JSON_OBJECT ? *_content.asObject : JsonObject::invalid(); } -bool JsonValue::asBool() const { +JsonValue::operator bool() const { return _type == JSON_BOOLEAN ? _content.asBoolean : false; } -const char *JsonValue::asString() const { +JsonValue::operator const char *() const { return _type == JSON_STRING ? _content.asString : NULL; } -double JsonValue::asDouble() const { +JsonValue::operator double() const { return _type >= JSON_DOUBLE_0_DECIMALS ? _content.asDouble : 0; } -long JsonValue::asLong() const { +JsonValue::operator long() const { return _type == JSON_LONG ? _content.asInteger : 0; } @@ -98,4 +98,4 @@ void JsonValue::writeTo(JsonWriter &writer) const { writer.writeDouble(_content.asDouble, _type - JSON_DOUBLE_0_DECIMALS); break; } -} \ No newline at end of file +} diff --git a/test/JsonArray_Container_Tests.cpp b/test/JsonArray_Container_Tests.cpp index a6b25802..7d0e5530 100644 --- a/test/JsonArray_Container_Tests.cpp +++ b/test/JsonArray_Container_Tests.cpp @@ -15,30 +15,43 @@ using namespace ArduinoJson; class JsonArray_Container_Tests : public ::testing::Test { protected: - JsonArray_Container_Tests() - : array(json.createArray()) { + JsonArray_Container_Tests() : array(json.createArray()) {} + + template + void firstMustEqual(T expected) { + itemMustEqual(0, expected); } template - void firstElementMustBe(T expected) { - elementAtIndexMustBe(0, expected); + void secondMustEqual(T expected) { + itemMustEqual(1, expected); } template - void secondElementMustBe(T expected) { - elementAtIndexMustBe(1, expected); + void firstMustReference(const T& expected) { + itemMustReference(0, expected); + } + + template + void secondMustReference(const T& expected) { + itemMustReference(1, expected); } void sizeMustBe(int expected) { EXPECT_EQ(expected, array.size()); } StaticJsonBuffer<256> json; - JsonArray &array; + JsonArray& array; private: template - void elementAtIndexMustBe(int index, T expected) { + void itemMustEqual(int index, T expected) { EXPECT_EQ(expected, array[index].as()); } + + template + void itemMustReference(int index, const T& expected) { + EXPECT_EQ(&expected, &array[index].as()); + } }; TEST_F(JsonArray_Container_Tests, SuccessIsTrue) { @@ -59,24 +72,24 @@ TEST_F(JsonArray_Container_Tests, CanStoreIntegers) { array.add(123); array.add(456); - firstElementMustBe(123); - secondElementMustBe(456); + firstMustEqual(123); + secondMustEqual(456); } TEST_F(JsonArray_Container_Tests, CanStoreDoubles) { array.add(123.45); array.add(456.78); - firstElementMustBe(123.45); - secondElementMustBe(456.78); + firstMustEqual(123.45); + secondMustEqual(456.78); } TEST_F(JsonArray_Container_Tests, CanStoreBooleans) { array.add(true); array.add(false); - firstElementMustBe(true); - secondElementMustBe(false); + firstMustEqual(true); + secondMustEqual(false); } TEST_F(JsonArray_Container_Tests, CanStoreStrings) { @@ -86,44 +99,44 @@ TEST_F(JsonArray_Container_Tests, CanStoreStrings) { array.add(firstString); array.add(secondString); - firstElementMustBe(firstString); - secondElementMustBe(secondString); + firstMustEqual(firstString); + secondMustEqual(secondString); } TEST_F(JsonArray_Container_Tests, CanStoreNestedArrays) { - JsonArray &innerarray1 = json.createArray(); - JsonArray &innerarray2 = json.createArray(); + JsonArray& innerarray1 = json.createArray(); + JsonArray& innerarray2 = json.createArray(); array.add(innerarray1); array.add(innerarray2); - firstElementMustBe(innerarray1); - secondElementMustBe(innerarray2); + firstMustReference(innerarray1); + secondMustReference(innerarray2); } TEST_F(JsonArray_Container_Tests, CanStoreNestedObjects) { - JsonObject innerObject1 = json.createObject(); - JsonObject innerObject2 = json.createObject(); + JsonObject& innerObject1 = json.createObject(); + JsonObject& innerObject2 = json.createObject(); array.add(innerObject1); array.add(innerObject2); - firstElementMustBe(innerObject1); - secondElementMustBe(innerObject2); + firstMustReference(innerObject1); + secondMustReference(innerObject2); } TEST_F(JsonArray_Container_Tests, CanCreateNestedArrays) { - JsonArray innerarray1 = array.createNestedArray(); - JsonArray innerarray2 = array.createNestedArray(); + JsonArray& innerarray1 = array.createNestedArray(); + JsonArray& innerarray2 = array.createNestedArray(); - firstElementMustBe(innerarray1); - secondElementMustBe(innerarray2); + firstMustReference(innerarray1); + secondMustReference(innerarray2); } TEST_F(JsonArray_Container_Tests, CanCreateNestedObjects) { - JsonObject innerObject1 = array.createNestedObject(); - JsonObject innerObject2 = array.createNestedObject(); + JsonObject& innerObject1 = array.createNestedObject(); + JsonObject& innerObject2 = array.createNestedObject(); - firstElementMustBe(innerObject1); - secondElementMustBe(innerObject2); + firstMustReference(innerObject1); + secondMustReference(innerObject2); } diff --git a/test/JsonArray_PrettyPrintTo_Tests.cpp b/test/JsonArray_PrettyPrintTo_Tests.cpp index 7f9930be..b045bd42 100644 --- a/test/JsonArray_PrettyPrintTo_Tests.cpp +++ b/test/JsonArray_PrettyPrintTo_Tests.cpp @@ -13,13 +13,14 @@ using namespace ArduinoJson; class JsonArray_PrettyPrintTo_Tests : public testing::Test { + public: + JsonArray_PrettyPrintTo_Tests() : array(json.createArray()) {} + protected: - JsonArray array; + JsonArray& array; StaticJsonBuffer<30> json; - virtual void SetUp() { array = json.createArray(); } - - void outputMustBe(const char *expected) { + void outputMustBe(const char* expected) { size_t n = array.prettyPrintTo(buffer, sizeof(buffer)); EXPECT_STREQ(expected, buffer); EXPECT_EQ(strlen(expected), n); @@ -63,11 +64,11 @@ TEST_F(JsonArray_PrettyPrintTo_Tests, EmptyNestedArrays) { } TEST_F(JsonArray_PrettyPrintTo_Tests, NestedArrays) { - JsonArray nested1 = array.createNestedArray(); + JsonArray& nested1 = array.createNestedArray(); nested1.add(1); nested1.add(2); - JsonObject nested2 = array.createNestedObject(); + JsonObject& nested2 = array.createNestedObject(); nested2["key"] = 3; outputMustBe( diff --git a/test/JsonArray_PrintTo_Tests.cpp b/test/JsonArray_PrintTo_Tests.cpp index 7a0974e7..2b197d1e 100644 --- a/test/JsonArray_PrintTo_Tests.cpp +++ b/test/JsonArray_PrintTo_Tests.cpp @@ -12,11 +12,12 @@ using namespace ArduinoJson; class JsonArray_PrintTo_Tests : public testing::Test { - protected: - JsonArray array; - StaticJsonBuffer<3> json; + public: + JsonArray_PrintTo_Tests() : array(json.createArray()) {} - virtual void SetUp() { array = json.createArray(); } + protected: + JsonArray &array; + StaticJsonBuffer<3> json; void outputMustBe(const char *expected) { size_t n = array.printTo(buffer, sizeof(buffer)); diff --git a/test/JsonObject_Container_Tests.cpp b/test/JsonObject_Container_Tests.cpp index 399edbe1..62de2d1c 100644 --- a/test/JsonObject_Container_Tests.cpp +++ b/test/JsonObject_Container_Tests.cpp @@ -14,11 +14,12 @@ using namespace ArduinoJson; class JsonObject_Container_Tests : public ::testing::Test { - protected: - virtual void SetUp() { object = json.createObject(); } + public: + JsonObject_Container_Tests() : object(json.createObject()) {} + protected: StaticJsonBuffer<42> json; - JsonObject object; + JsonObject& object; }; TEST_F(JsonObject_Container_Tests, InitialSizeIsZero) { @@ -95,23 +96,23 @@ TEST_F(JsonObject_Container_Tests, CanStoreStrings) { } TEST_F(JsonObject_Container_Tests, CanStoreInnerArrays) { - JsonArray innerarray1 = json.createArray(); - JsonArray innerarray2 = json.createArray(); + JsonArray& innerarray1 = json.createArray(); + JsonArray& innerarray2 = json.createArray(); object["hello"] = innerarray1; object["world"] = innerarray2; - EXPECT_EQ(innerarray1, object["hello"].as()); - EXPECT_EQ(innerarray2, object["world"].as()); + EXPECT_EQ(&innerarray1, &object["hello"].asArray()); + EXPECT_EQ(&innerarray2, &object["world"].asArray()); } TEST_F(JsonObject_Container_Tests, CanStoreInnerObjects) { - JsonObject innerObject1 = json.createObject(); - JsonObject innerObject2 = json.createObject(); + JsonObject& innerObject1 = json.createObject(); + JsonObject& innerObject2 = json.createObject(); object["hello"] = innerObject1; object["world"] = innerObject2; - EXPECT_EQ(innerObject1, object["hello"].as()); - EXPECT_EQ(innerObject2, object["world"].as()); + EXPECT_EQ(&innerObject1, &object["hello"].asObject()); + EXPECT_EQ(&innerObject2, &object["world"].asObject()); } diff --git a/test/JsonObject_Iterator_Tests.cpp b/test/JsonObject_Iterator_Tests.cpp index 4df10990..02425980 100644 --- a/test/JsonObject_Iterator_Tests.cpp +++ b/test/JsonObject_Iterator_Tests.cpp @@ -13,7 +13,7 @@ using namespace ArduinoJson; TEST(JsonObject_Iterator_Test, SimpleTest) { StaticJsonBuffer<42> jsonBuffer; - JsonObject object = jsonBuffer.createObject(); + JsonObject &object = jsonBuffer.createObject(); object["ab"] = 12; object["cd"] = 34; @@ -21,12 +21,12 @@ TEST(JsonObject_Iterator_Test, SimpleTest) { JsonObject::iterator end = object.end(); EXPECT_NE(end, it); - EXPECT_STREQ("ab", it->key()); - EXPECT_EQ(12, it->value().as()); + EXPECT_STREQ("ab", it->key); + EXPECT_EQ(12, it->value.as()); ++it; EXPECT_NE(end, it); - EXPECT_STREQ("cd", it->key()); - EXPECT_EQ(34, it->value().as()); + EXPECT_STREQ("cd", it->key); + EXPECT_EQ(34, it->value.as()); ++it; EXPECT_EQ(object.end(), it); }