Compare commits

...

9 Commits
v3.1 ... v3.2

10 changed files with 196 additions and 56 deletions

13
BuildArduinoPackage.sh Normal file
View File

@ -0,0 +1,13 @@
#!/bin/bash
ZIP="C:\Program Files\7-Zip\7z.exe"
TAG=$(git describe)
OUTPUT="ArduinoJson-$TAG.zip"
cd ..
INPUT=$(find ArduinoJson -regex ".*\.\(cpp\|h\|md\|txt\|ino\)$" -not -regex ".*Tests/.*")
rm -f $OUTPUT
"$ZIP" a $OUTPUT $INPUT

View File

@ -1,6 +1,11 @@
Arduino JSON: change log
========================
v3.2
----
* Fixed a bug when adding nested object in `JsonArray` (bug introduced in v3.1).
v3.1
----

View File

@ -20,12 +20,34 @@ namespace ArduinoJson
}
template<typename T>
void add(T value)
void add(const Printable& value)
{
if (count >= capacity) return;
addIfPossible<const Printable&>(value);
}
items[count++] = value;
void add(bool value)
{
addIfPossible<bool>(value);
}
void add(int value)
{
addIfPossible<long>(value);
}
void add(long value)
{
addIfPossible<long>(value);
}
void add(double value)
{
addIfPossible<double>(value);
}
void add(const char* value)
{
addIfPossible<const char*>(value);
}
template<int DIGITS>
@ -44,6 +66,13 @@ namespace ArduinoJson
private:
JsonValue* items;
int capacity, count;
template<typename T>
void addIfPossible(T value)
{
if (count < capacity)
items[count++] = value;
}
};
}
}

View File

@ -35,7 +35,7 @@ namespace ArduinoJson
content.asLong = value;
}
void operator=(Printable& value)
void operator=(const Printable& value)
{
printToImpl = &printPrintableTo;
content.asPrintable = &value;
@ -89,7 +89,7 @@ namespace ArduinoJson
return content.asLong;
}
operator Printable&()
operator const Printable&()
{
return *content.asPrintable;
}
@ -109,11 +109,11 @@ namespace ArduinoJson
private:
union Content
{
bool asBool;
double asDouble;
long asLong;
Printable* asPrintable;
const char* asString;
bool asBool;
double asDouble;
long asLong;
const Printable* asPrintable;
const char* asString;
};
Content content;

View File

@ -101,6 +101,33 @@ or
JsonObject<8> nestedObject;
array.add(nestedObject);
> ##### CAUTION! Nested objects must be in memory
> Calling `add()` makes the `JsonArray` store a pointer to the nested object.
> This is designed to avoid memory duplication.
> But it can only work if the object is in memory when `printTo()` is executed.
> For instance, don't do this:
>
> void addNestedObject()
> {
> JsonObject<2> nestedObject;
> // ...
> array.add(nestedObject); // <- DON'T !!
>
> // array now contains a pointer to a local variable that will be
> // discarded as soon as the function exits
> }
>
> For the same reason, don't do this either:
>
> for( int i=0; i<100; i++)
> {
> JsonObject<2> nestedObject;
> // ...
> array.add(nestedObject); // <- DON'T !!
> }
> // array now contains 100 pointers to the same a local variable
> // that is out of the scope anyway
#### JSON Object
You create a JSON object (ie hash-table/dictionary) with the following line:

View File

@ -0,0 +1,73 @@
#include "CppUnitTest.h"
#include "JsonArray.h"
#include "JsonObject.h"
using namespace ArduinoJson::Generator;
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace JsonGeneratorTests
{
TEST_CLASS(Issue10)
{
struct Person {
int id;
char name[32];
};
Person persons[2];
public:
TEST_METHOD_INITIALIZE(Initialize)
{
Person boss;
boss.id = 1;
strcpy(boss.name, "Jeff");
Person employee;
employee.id = 2;
strcpy(employee.name, "John");
persons[0] = boss;
persons[1] = employee;
}
TEST_METHOD(WrongWayToAddObjectInAnArray)
{
JsonArray<2> json;
for (int i = 0; i < 2; i++)
{
JsonObject<2> object;
object["id"] = persons[i].id;
object["name"] = persons[i].name;
json.add(object); // <- Adding a reference to a temporary variable
}
char buffer[256];
json.printTo(buffer, sizeof(buffer));
// the same values are repeated, that's normal
Assert::AreEqual("[{\"id\":2,\"name\":\"John\"},{\"id\":2,\"name\":\"John\"}]", buffer);
}
TEST_METHOD(RightWayToAddObjectInAnArray)
{
JsonArray<2> json;
JsonObject<2> object[2];
for (int i = 0; i < 2; i++)
{
object[i]["id"] = persons[i].id;
object[i]["name"] = persons[i].name;
json.add(object[i]);
}
char buffer[256];
json.printTo(buffer, sizeof(buffer));
Assert::AreEqual("[{\"id\":1,\"name\":\"Jeff\"},{\"id\":2,\"name\":\"John\"}]", buffer);
}
};
}

View File

@ -14,7 +14,7 @@ namespace JsonGeneratorTests
{
TEST_CLASS(JsonArrayTests)
{
JsonArray<2> arr;
JsonArray<2> array;
char buffer[256];
public:
@ -26,111 +26,117 @@ namespace JsonGeneratorTests
TEST_METHOD(Null)
{
add((char*)0);
array.add((char*) 0);
outputMustBe("[null]");
}
TEST_METHOD(OneString)
{
add("hello");
array.add("hello");
outputMustBe("[\"hello\"]");
}
TEST_METHOD(TwoStrings)
{
add("hello");
add("world");
array.add("hello");
array.add("world");
outputMustBe("[\"hello\",\"world\"]");
}
TEST_METHOD(OneStringOverCapacity)
{
add("hello");
add("world");
add("lost");
array.add("hello");
array.add("world");
array.add("lost");
outputMustBe("[\"hello\",\"world\"]");
}
TEST_METHOD(OneDoubleDefaultDigits)
{
add(3.14159265358979323846);
array.add(3.14159265358979323846);
outputMustBe("[3.14]");
}
TEST_METHOD(OneDoubleFourDigits)
{
add<4>(3.14159265358979323846);
array.add<4>(3.14159265358979323846);
outputMustBe("[3.1416]");
}
TEST_METHOD(OneInteger)
{
add(1);
array.add(1);
outputMustBe("[1]");
}
TEST_METHOD(TwoIntegers)
{
add(1);
add(2);
array.add(1);
array.add(2);
outputMustBe("[1,2]");
}
TEST_METHOD(OneIntegerOverCapacity)
{
add(1);
add(2);
add(3);
array.add(1);
array.add(2);
array.add(3);
outputMustBe("[1,2]");
}
TEST_METHOD(OneTrue)
{
add(true);
array.add(true);
outputMustBe("[true]");
}
TEST_METHOD(OneFalse)
{
add(false);
array.add(false);
outputMustBe("[false]");
}
TEST_METHOD(TwoBooleans)
{
add(false);
add(true);
array.add(false);
array.add(true);
outputMustBe("[false,true]");
}
TEST_METHOD(OneBooleanOverCapacity)
{
add(false);
add(true);
add(false);
array.add(false);
array.add(true);
array.add(false);
outputMustBe("[false,true]");
}
TEST_METHOD(OneEmptyNestedArray)
{
addNested(JsonArray<1>());
JsonArray<1> nestedArray;
array.add(nestedArray);
outputMustBe("[[]]");
}
TEST_METHOD(OneEmptyNestedHash)
{
addNested(JsonHashTable<1>());
JsonObject<1> nestedObject;
array.add(nestedObject);
outputMustBe("[{}]");
}
@ -139,33 +145,16 @@ namespace JsonGeneratorTests
JsonArray<1> nestedArray;
nestedArray.add(1);
addNested(nestedArray);
array.add(nestedArray);
outputMustBe("[[1]]");
}
private:
void addNested(Printable& value)
{
arr.add<Printable&>(value);
}
template<typename T>
void add(T value)
{
arr.add(value);
}
template<int DIGITS>
void add(double value)
{
arr.add<DIGITS>(value);
}
void outputMustBe(const char* expected)
{
size_t n = arr.printTo(buffer, sizeof(buffer));
size_t n = array.printTo(buffer, sizeof(buffer));
Assert::AreEqual(expected, buffer);
Assert::AreEqual(strlen(expected), n);
}

View File

@ -85,6 +85,7 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="EscapedStringTests.cpp" />
<ClCompile Include="Issue10.cpp" />
<ClCompile Include="JsonArrayTests.cpp" />
<ClCompile Include="JsonObject_Indexer_Tests.cpp" />
<ClCompile Include="JsonObject_PrintTo_Tests.cpp" />

View File

@ -36,5 +36,8 @@
<ClCompile Include="JsonValue_Cast_Tests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Issue10.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -71,7 +71,7 @@ namespace JsonGeneratorTests
void setValueAndCheckCast(JsonArray<N>& expected)
{
value = expected;
Printable& actual = value;
const Printable& actual = value;
Assert::AreEqual((void*) &expected, (void*) &actual);
}
};