forked from bblanchon/ArduinoJson
Merge branch 'parse-escaped-chars'
This commit is contained in:
12
CHANGELOG.md
12
CHANGELOG.md
@ -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:
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
};
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
@ -23,12 +23,6 @@ namespace ArduinoJsonParserTests
|
||||
|
||||
public:
|
||||
|
||||
TEST_METHOD(EmptyString)
|
||||
{
|
||||
whenInputIs("");
|
||||
parseMustFail();
|
||||
}
|
||||
|
||||
TEST_METHOD(EmptyHashTable)
|
||||
{
|
||||
whenInputIs("{}");
|
||||
|
@ -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">
|
||||
|
@ -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>
|
107
JsonParserTests/JsonStringTests.cpp
Normal file
107
JsonParserTests/JsonStringTests.cpp
Normal 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
README.md
10
README.md
@ -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).
|
||||
|
Reference in New Issue
Block a user