Added support of non standard JSON input (issue #44)

This commit is contained in:
Benoit Blanchon
2015-07-10 22:11:26 +02:00
parent 78ae0b8aee
commit 92e687303d
30 changed files with 406 additions and 398 deletions

View File

@ -0,0 +1,39 @@
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "../Arduino/Print.hpp"
namespace ArduinoJson {
namespace Internals {
class Encoding {
public:
// Optimized for code size on a 8-bit AVR
static char escapeChar(char c) {
const char *p = _escapeTable;
while (p[0] && p[1] != c) {
p += 2;
}
return p[0];
}
// Optimized for code size on a 8-bit AVR
static char unescapeChar(char c) {
const char *p = _escapeTable + 4;
for (;;) {
if (p[0] == '\0') return c;
if (p[0] == c) return p[1];
p += 2;
}
}
private:
static const char _escapeTable[];
};
}
}

View File

@ -18,7 +18,10 @@ namespace Internals {
class JsonParser {
public:
JsonParser(JsonBuffer *buffer, char *json, uint8_t nestingLimit)
: _buffer(buffer), _ptr(json), _nestingLimit(nestingLimit) {}
: _buffer(buffer),
_readPtr(json),
_writePtr(json),
_nestingLimit(nestingLimit) {}
JsonArray &parseArray();
JsonObject &parseObject();
@ -26,12 +29,10 @@ class JsonParser {
private:
bool skip(char charToSkip);
bool skip(const char *wordToSkip);
void skipSpaces();
bool parseAnythingTo(JsonVariant *destination);
FORCE_INLINE bool parseAnythingToUnsafe(JsonVariant *destination);
const char *parseString();
bool parseAnythingTo(JsonVariant *destination);
FORCE_INLINE bool parseAnythingToUnsafe(JsonVariant *destination);
inline bool parseArrayTo(JsonVariant *destination);
inline bool parseBooleanTo(JsonVariant *destination);
@ -41,7 +42,8 @@ class JsonParser {
inline bool parseStringTo(JsonVariant *destination);
JsonBuffer *_buffer;
char *_ptr;
const char *_readPtr;
char *_writePtr;
uint8_t _nestingLimit;
};
}

View File

@ -12,6 +12,10 @@
#include "Prettyfier.hpp"
#include "StringBuilder.hpp"
#ifdef ARDUINOJSON_ENABLE_STD_STREAM
#include "StreamPrintAdapter.hpp"
#endif
namespace ArduinoJson {
namespace Internals {
@ -28,6 +32,14 @@ class JsonPrintable {
return writer.bytesWritten();
}
#ifdef ARDUINOJSON_ENABLE_STD_STREAM
std::ostream& printTo(std::ostream &os) const {
StreamPrintAdapter adapter(os);
printTo(adapter);
return os;
}
#endif
size_t printTo(char *buffer, size_t bufferSize) const {
StringBuilder sb(buffer, bufferSize);
return printTo(sb);
@ -61,5 +73,13 @@ class JsonPrintable {
private:
const T &downcast() const { return *static_cast<const T *>(this); }
};
#ifdef ARDUINOJSON_ENABLE_STD_STREAM
template<typename T>
inline std::ostream& operator<<(std::ostream& os, const JsonPrintable<T>& v) {
return v.printTo(os);
}
#endif
}
}

View File

@ -7,7 +7,7 @@
#pragma once
#include "../Arduino/Print.hpp"
#include "QuotedString.hpp"
#include "Encoding.hpp"
namespace ArduinoJson {
namespace Internals {
@ -26,7 +26,7 @@ class JsonWriter {
// Returns the number of bytes sent to the Print implementation.
// This is very handy for implementations of printTo() that must return the
// number of bytes written.
size_t bytesWritten() { return _length; }
size_t bytesWritten() const { return _length; }
void beginArray() { write('['); }
void endArray() { write(']'); }
@ -37,15 +37,32 @@ class JsonWriter {
void writeColon() { write(':'); }
void writeComma() { write(','); }
void writeBoolean(bool value) {
write(value ? "true" : "false");
}
void writeString(const char *value) {
_length += QuotedString::printTo(value, _sink);
if (!value) {
write("null");
} else {
write('\"');
while (*value) writeChar(*value++);
write('\"');
}
}
void writeChar(char c) {
char specialChar = Encoding::escapeChar(c);
if (specialChar) {
write('\\');
write(specialChar);
} else {
write(c);
}
}
void writeLong(long value) { _length += _sink.print(value); }
void writeBoolean(bool value) {
_length += _sink.print(value ? "true" : "false");
}
void writeDouble(double value, uint8_t decimals) {
_length += _sink.print(value, decimals);
}

View File

@ -1,29 +0,0 @@
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#include "../Arduino/Print.hpp"
namespace ArduinoJson {
namespace Internals {
// An helper class to print and extract doubly-quoted strings
class QuotedString {
public:
// Writes a doubly-quote string to a Print implementation.
// It adds the double quotes (") at the beginning and the end of the string.
// It escapes the special characters as required by the JSON specifications.
static size_t printTo(const char *, Print &);
// Reads a doubly-quoted string from a buffer.
// It removes the double quotes (").
// It unescapes the special character as required by the JSON specification,
// with the exception of the Unicode characters (\u0000).
static char *extractFrom(char *input, char **end);
};
}
}

View File

@ -0,0 +1,34 @@
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
#pragma once
#ifdef ARDUINOJSON_ENABLE_STD_STREAM
#include "../Arduino/Print.hpp"
namespace ArduinoJson {
namespace Internals {
class StreamPrintAdapter : public Print {
public:
explicit StreamPrintAdapter(std::ostream& os) : _os(os) {}
virtual size_t write(uint8_t c) {
_os << static_cast<char>(c);
return 1;
}
private:
// cannot be assigned
StreamPrintAdapter& operator=(const StreamPrintAdapter&);
std::ostream& _os;
};
}
}
#endif // ARDUINOJSON_ENABLE_STD_STREAM

View File

@ -40,8 +40,19 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
return _array.is<T>(_index);
}
void writeTo(Internals::JsonWriter &writer) const {
_array.get(_index).writeTo(writer);
}
private:
JsonArray& _array;
const size_t _index;
};
#ifdef ARDUINOJSON_ENABLE_STD_STREAM
inline std::ostream& operator<<(std::ostream& os, const JsonArraySubscript& source) {
return source.printTo(os);
}
#endif
} // namespace ArduinoJson

View File

@ -41,8 +41,18 @@ class JsonObjectSubscript : public JsonVariantBase<JsonObjectSubscript> {
return _object.is<T>(_key);
}
void writeTo(Internals::JsonWriter &writer) const {
_object.get(_key).writeTo(writer);
}
private:
JsonObject& _object;
JsonObjectKey _key;
};
#ifdef ARDUINOJSON_ENABLE_STD_STREAM
inline std::ostream& operator<<(std::ostream& os, const JsonObjectSubscript& source) {
return source.printTo(os);
}
#endif
}

View File

@ -28,8 +28,7 @@ class JsonObject;
// - a char, short, int or a long (signed or unsigned)
// - a string (const char*)
// - a reference to a JsonArray or JsonObject
class JsonVariant : public Internals::JsonPrintable<JsonVariant>,
public JsonVariantBase<JsonVariant> {
class JsonVariant : public JsonVariantBase<JsonVariant> {
public:
// Creates an uninitialized JsonVariant
FORCE_INLINE JsonVariant() : _type(Internals::JSON_UNDEFINED) {}

View File

@ -186,4 +186,11 @@ template <>
inline bool JsonVariant::is<unsigned short>() const {
return _type == Internals::JSON_LONG;
}
#ifdef ARDUINOJSON_ENABLE_STD_STREAM
inline std::ostream& operator<<(std::ostream& os, const JsonVariant& source) {
return source.printTo(os);
}
#endif
} // namespace ArduinoJson

View File

@ -16,7 +16,7 @@ class JsonArraySubscript;
class JsonObjectSubscript;
template <typename TImpl>
class JsonVariantBase {
class JsonVariantBase : public Internals::JsonPrintable<TImpl> {
public:
// Gets the variant as a boolean value.
// Returns false if the variant is not a boolean value.
@ -79,6 +79,9 @@ class JsonVariantBase {
FORCE_INLINE const JsonObjectSubscript operator[](const char *key) const;
FORCE_INLINE const JsonObjectSubscript operator[](const String &key) const;
// Serialize the variant to a JsonWriter
void writeTo(Internals::JsonWriter &writer) const;
private:
const TImpl *impl() const { return static_cast<const TImpl *>(this); }
};