Compare commits

..

10 Commits
v3.3 ... v3.4

10 changed files with 205 additions and 47 deletions

View File

@ -1,10 +1,16 @@
Arduino JSON: change log
========================
v3.4
----
* Fixed escaped char parsing (issue #16)
v3.3
----
* Added indented output for the JSON generator, see example bellow.
* Added indented output for the JSON generator (issue #11), see example bellow.
* Added `IndentedPrint`, a decorator for `Print` to allow indented output
Example:
@ -23,7 +29,7 @@ v3.1
* Calling `Generator::JsonObject::add()` twice with the same `key` now replaces the `value`
* Added `Generator::JsonObject::operator[]`, see bellow the new API
* Added `Generator::JsonObject::remove()`
* Added `Generator::JsonObject::remove()` (issue #9)
Old generator API:
@ -44,7 +50,7 @@ v3.0
* New parser API, see bellow
* Renamed `JsonHashTable` into `JsonObject`
* Added iterators for `JsonArray` and `JsonObject`
* Added iterators for `JsonArray` and `JsonObject` (issue #4)
Old parser API:

View File

@ -7,6 +7,50 @@
using namespace ArduinoJson::Parser;
char* JsonToken::getText()
{
char* s = json + token->start;
json[token->end] = 0;
unescapeString(s);
return s;
}
inline void JsonToken::unescapeString(char* s)
{
char* readPtr = s;
char* writePtr = s;
char c;
do
{
c = *readPtr++;
if (c == '\\')
{
c = unescapeChar(*readPtr++);
}
*writePtr++ = c;
} while (c != 0);
}
inline char JsonToken::unescapeChar(char c)
{
// Optimized for code size on a 8-bit AVR
const char* p = "b\bf\fn\nr\rt\t";
while (true)
{
if (p[0] == 0) return c;
if (p[0] == c) return p[1];
p += 2;
}
}
JsonToken JsonToken::nextSibling() const
{
// start with current token

View File

@ -29,11 +29,7 @@ namespace ArduinoJson
}
// Get content of the JSON token
char* getText()
{
json[token->end] = 0;
return json + token->start;
}
char* getText();
// Get the number of children tokens
int childrenCount()
@ -95,6 +91,9 @@ namespace ArduinoJson
private:
char* json;
jsmntok_t* token;
static char unescapeChar(char c);
static void unescapeString(char* s);
};
}
}

View File

@ -11,33 +11,27 @@ using namespace ArduinoJson::Parser;
namespace ArduinoJsonParserTests
{
TEST_CLASS(JsonArrayTests)
{
TEST_CLASS(JsonArrayTests)
{
JsonArray array;
char json[256];
jsmntok_t tokens[32];
JsonParserBase parser = JsonParserBase(tokens, 32);
public:
TEST_METHOD(EmptyString)
{
whenInputIs("");
parseMustFail();
}
TEST_METHOD(TooFewClosingBrackets)
{
public:
TEST_METHOD(TooFewClosingBrackets)
{
whenInputIs("[[]");
parseMustFail();
}
}
TEST_METHOD(TooManyClosingBrackets)
{
TEST_METHOD(TooManyClosingBrackets)
{
whenInputIs("[]]");
parseMustFail();
}
}
TEST_METHOD(EmptyArray)
{
whenInputIs("[]");
@ -55,8 +49,8 @@ namespace ArduinoJsonParserTests
itemMustNotExist(0);
}
TEST_METHOD(TwoIntegers)
{
TEST_METHOD(TwoIntegers)
{
setTokenCountTo(3);
whenInputIs("[1,2]");
@ -66,7 +60,7 @@ namespace ArduinoJsonParserTests
itemMustBe(0, 1L);
itemMustBe(1, 2L);
itemMustNotExist(2);
}
}
TEST_METHOD(TwoBooleans)
{
@ -94,8 +88,8 @@ namespace ArduinoJsonParserTests
itemMustNotExist(2);
}
TEST_METHOD(TwoDimensionsArray)
{
TEST_METHOD(TwoDimensionsArray)
{
setTokenCountTo(7);
whenInputIs("[[1,2],[3,4]]");
@ -107,7 +101,7 @@ namespace ArduinoJsonParserTests
itemMustBe(1, 0, 3L);
itemMustBe(1, 1, 4L);
itemMustNotExist(2);
}
}
TEST_METHOD(ThreeDimensionsArray)
{
@ -127,7 +121,7 @@ namespace ArduinoJsonParserTests
itemMustBe(1, 1, 1, 8L);
itemMustNotExist(2);
}
private:
void setTokenCountTo(int n)
@ -191,5 +185,5 @@ namespace ArduinoJsonParserTests
Assert::AreEqual(0L, array.getLong(index));
Assert::IsNull(array.getString(index));
}
};
};
}

View File

@ -23,12 +23,6 @@ namespace ArduinoJsonParserTests
public:
TEST_METHOD(EmptyString)
{
whenInputIs("");
parseMustFail();
}
TEST_METHOD(EmptyHashTable)
{
whenInputIs("{}");

View File

@ -90,6 +90,7 @@
<ClCompile Include="JsonArrayIteratorTests.cpp" />
<ClCompile Include="JsonObjectTests.cpp" />
<ClCompile Include="GbathreeBug.cpp" />
<ClCompile Include="JsonStringTests.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\JsonParser\JsonParser.vcxproj">

View File

@ -15,9 +15,6 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="JsonArrayTests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="GbathreeBug.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -30,5 +27,11 @@
<ClCompile Include="JsonObjectIteratorTests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="JsonArrayTests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="JsonStringTests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@ -0,0 +1,107 @@
/*
* Arduino JSON library
* Benoit Blanchon 2014 - MIT License
*/
#include "CppUnitTest.h"
#include "JsonParser.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
using namespace ArduinoJson::Parser;
namespace ArduinoJsonParserTests
{
TEST_CLASS(JsonStringTests)
{
const char* actual;
char json[256];
JsonParser<32> parser;
public:
TEST_METHOD(EmptyString)
{
whenInputIs("");
outputMustBe(0);
}
TEST_METHOD(JustOneQuote)
{
whenInputIs("\"");
outputMustBe(0);
}
TEST_METHOD(SimpleString)
{
whenInputIs("\"Hi!\"");
outputMustBe("Hi!");
}
TEST_METHOD(EscapedQuote)
{
whenInputIs("\"12\\\"34\""); // ie 12\"34
outputMustBe("12\"34");
}
TEST_METHOD(EscapedReverseSolidus)
{
whenInputIs("\"12\\\\34\""); // ie 12\\34
outputMustBe("12\\34");
}
TEST_METHOD(EscapedSolidus)
{
whenInputIs("\"12\\/34\"");
outputMustBe("12/34");
}
TEST_METHOD(EscapedBackspace)
{
whenInputIs("\"12\\b34\"");
outputMustBe("12\b34");
}
TEST_METHOD(EscapedFormfeed)
{
whenInputIs("\"12\\f34\"");
outputMustBe("12\f34");
}
TEST_METHOD(EscapedNewline)
{
whenInputIs("\"12\\n34\"");
outputMustBe("12\n34");
}
TEST_METHOD(EscapedCarriageReturn)
{
whenInputIs("\"12\\r34\"");
outputMustBe("12\r34");
}
TEST_METHOD(EscapedTab)
{
whenInputIs("\"12\\t34\"");
outputMustBe("12\t34");
}
TEST_METHOD(AllEscapedCharsTogether)
{
whenInputIs("\"1\\\"2\\\\3\\/4\\b5\\f6\\n7\\r8\\t9\"");
outputMustBe("1\"2\\3/4\b5\f6\n7\r8\t9");
}
private:
void whenInputIs(const char* input)
{
strcpy(json, input);
actual = parser.parse(json);
}
void outputMustBe(const char* expected)
{
Assert::AreEqual(expected, actual);
}
};
}

10
LICENSE.md Normal file
View File

@ -0,0 +1,10 @@
The MIT License (MIT)
---------------------
Copyright © 2014 Benoit BLANCHON
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -10,8 +10,8 @@ It has been written with Arduino in mind, but it isn't linked to Arduino librari
Features
--------
* JSON decoding: [more details here](/JsonParser/)
* JSON encoding: [more details here](/JsonGenerator/)
* JSON decoding: [see documentation here](/JsonParser/)
* JSON encoding: [see documentation here](/JsonGenerator/)
* Elegant API, very easy to use
* Fixed memory allocation (no malloc)
* Small footprint
@ -22,9 +22,9 @@ Feature comparison
| Library | Memory allocation | Nested objects | Parser size | Encoder size |
| ------------ | ----------------- | -------------- | ----------- | ------------- |
| Arduino JSON | static | yes | 2642 Bytes | 862 bytes |
| json-arduino | dynamic | no | 3348 (+27%) | not supported |
| aJson | dynamic | yes | 5088 (+93%) | 4678 (+540%) |
| Arduino JSON | static | yes | 2760 Bytes | 862 bytes |
| json-arduino | dynamic | no | 3348 (+21%) | not supported |
| aJson | dynamic | yes | 5088 (+84%) | 4678 (+540%) |
"Parser size" was measured with a program parsing `{"sensor":"outdoor","value":25.6}`.
For each library, I wrote a program that extracts a string and a float. I subtracted the size of a program doing the same without any JSON parsing involved. [Source files are here](https://gist.github.com/bblanchon/e8ba914a7109f3642c0f).