Skip to content

Commit

Permalink
Added support of String class (issue #55, #56, #70, #77)
Browse files Browse the repository at this point in the history
  • Loading branch information
bblanchon committed May 25, 2015
1 parent 756c279 commit 1b5be89
Show file tree
Hide file tree
Showing 22 changed files with 351 additions and 119 deletions.
12 changes: 10 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
ArduinoJson: change log
=======================

v5.0 (currently in development)
v5.0 (currently under development)
----

* Added support of `String` class (issue #55, #56, #70, #77)
* Redesigned `JsonVariant` to leverage converting constructors instead of assignment operators.

**BREAKING CHANGES**:
- `JsonObject::add()` was renamed to `set()`
- `JsonArray::at()` and `JsonObject::at()` were renamed to `get()`
- Number of digits of floating point value are now set with `double_with_n_digits()`

**Personal note about the `String` class**:
Support of the `String` class has been added to the library because many people use it in their programs.
However, you should not see this as an invitation to use the `String` class.
The `String` class is **bad** because it uses dynamic memory allocation.
Compared to static allocation, it compiles to a bigger, slower program, and is less predicate.
You certainly don't want that in an embedded environment!

v4.4
----

Expand Down Expand Up @@ -143,4 +151,4 @@ v1.1
v1.0
----

Initial release
Initial release
19 changes: 19 additions & 0 deletions include/ArduinoJson/Arduino/String.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson

#pragma once

#ifndef ARDUINO

#include <string>

typedef std::string String;

#else

#include <WString.h>

#endif
4 changes: 2 additions & 2 deletions include/ArduinoJson/Internals/ForceInline.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#pragma once

#ifdef _MSC_VER
#define JSON_FORCE_INLINE __forceinline
#define FORCE_INLINE __forceinline
#else
#define JSON_FORCE_INLINE __attribute__((always_inline))
#define FORCE_INLINE __attribute__((always_inline))
#endif
2 changes: 1 addition & 1 deletion include/ArduinoJson/Internals/JsonParser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class JsonParser {
void skipSpaces();

bool parseAnythingTo(JsonVariant *destination);
JSON_FORCE_INLINE bool parseAnythingToUnsafe(JsonVariant *destination);
FORCE_INLINE bool parseAnythingToUnsafe(JsonVariant *destination);

const char *parseString();

Expand Down
5 changes: 5 additions & 0 deletions include/ArduinoJson/Internals/JsonVariantContent.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ inline char const* JsonVariantContent::as<char const*>() const {
return asString;
}

template <>
inline String JsonVariantContent::as<String>() const {
return asString;
}

template <>
inline double JsonVariantContent::as<double>() const {
return asDouble;
Expand Down
17 changes: 1 addition & 16 deletions include/ArduinoJson/Internals/List.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,22 +48,7 @@ class List {
const_iterator end() const { return const_iterator(NULL); }

protected:
node_type *addNewNode() {
if (!_buffer) return NULL;

node_type *newNode = new (_buffer) node_type();

if (_firstNode) {
node_type *lastNode = _firstNode;
while (lastNode->next) lastNode = lastNode->next;
lastNode->next = newNode;
} else {
_firstNode = newNode;
}

return newNode;
}

node_type *addNewNode();
void removeNode(node_type *nodeToRemove);

JsonBuffer *_buffer;
Expand Down
14 changes: 7 additions & 7 deletions include/ArduinoJson/JsonArray.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,27 +42,27 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
: Internals::List<JsonVariant>(buffer) {}

// Gets the value at the specified index
JSON_FORCE_INLINE const JsonArraySubscript operator[](size_t index) const;
FORCE_INLINE const JsonArraySubscript operator[](size_t index) const;

// Gets or sets the value at specified index
JSON_FORCE_INLINE JsonArraySubscript operator[](size_t index);
FORCE_INLINE JsonArraySubscript operator[](size_t index);

// Adds the specified value at the end of the array.
JSON_FORCE_INLINE bool add(const JsonVariant value);
FORCE_INLINE bool add(const JsonVariant value);

// Sets the value at specified index.
JSON_FORCE_INLINE void set(size_t index, const JsonVariant value);
FORCE_INLINE void set(size_t index, const JsonVariant value);

// Gets the value at the specified index.
JSON_FORCE_INLINE JsonVariant get(size_t index) const;
FORCE_INLINE JsonVariant get(size_t index) const;

// Gets the value at the specified index.
template <typename T>
JSON_FORCE_INLINE T get(size_t index) const;
FORCE_INLINE T get(size_t index) const;

// Check the type of the value at specified index.
template <typename T>
JSON_FORCE_INLINE T is(size_t index) const;
FORCE_INLINE T is(size_t index) const;

// Creates a JsonArray and adds a reference at the end of the array.
// It's a shortcut for JsonBuffer::createArray() and JsonArray::add()
Expand Down
19 changes: 13 additions & 6 deletions include/ArduinoJson/JsonArraySubscript.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,32 @@
namespace ArduinoJson {
class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
public:
JSON_FORCE_INLINE JsonArraySubscript(JsonArray& array, size_t index)
FORCE_INLINE JsonArraySubscript(JsonArray& array, size_t index)
: _array(array), _index(index) {}

JSON_FORCE_INLINE JsonArraySubscript& operator=(const JsonVariant& value) {
FORCE_INLINE JsonArraySubscript& operator=(const JsonVariant& value) {
_array.set(_index, value);
return *this;
}

JSON_FORCE_INLINE bool success() const { return _index < _array.size(); }
FORCE_INLINE JsonArraySubscript& operator=(const JsonArraySubscript& other) {
// to prevent Visual Studio warning C4512: assignment operator could not be
// generated
_array.set(_index, other._array.get(other._index));
return *this;
}

FORCE_INLINE bool success() const { return _index < _array.size(); }

JSON_FORCE_INLINE operator JsonVariant() const { return _array.get(_index); }
FORCE_INLINE operator JsonVariant() const { return _array.get(_index); }

template <typename T>
JSON_FORCE_INLINE T as() const {
FORCE_INLINE T as() const {
return _array.get<T>(_index);
}

template <typename T>
JSON_FORCE_INLINE T is() const {
FORCE_INLINE T is() const {
return _array.is<T>(_index);
}

Expand Down
13 changes: 13 additions & 0 deletions include/ArduinoJson/JsonBuffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include <stddef.h> // for size_t
#include <stdint.h> // for uint8_t

#include "Arduino/String.hpp"

#if defined(__clang__)
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
#elif defined(__GNUC__)
Expand Down Expand Up @@ -55,6 +57,11 @@ class JsonBuffer {
// allocation fails.
JsonArray &parseArray(char *json, uint8_t nestingLimit = DEFAULT_LIMIT);

// Same as above with a String class
JsonArray &parseArray(const String &json, uint8_t nesting = DEFAULT_LIMIT) {
return parseArray(const_cast<char *>(json.c_str()), nesting);
}

// Allocates and populate a JsonObject from a JSON string.
//
// The First argument is a pointer to the JSON string, the memory must be
Expand All @@ -67,6 +74,12 @@ class JsonBuffer {
// allocation fails.
JsonObject &parseObject(char *json, uint8_t nestingLimit = DEFAULT_LIMIT);

// Same as above with a String class
JsonObject &parseObject(const String &json,
uint8_t nestingLimit = DEFAULT_LIMIT) {
return parseObject(const_cast<char *>(json.c_str()), nestingLimit);
}

// Allocates n bytes in the JsonBuffer.
// Return a pointer to the allocated memory or NULL if allocation fails.
virtual void *alloc(size_t size) = 0;
Expand Down
34 changes: 16 additions & 18 deletions include/ArduinoJson/JsonObject.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#pragma once

#include "Arduino/String.hpp"
#include "Internals/JsonBufferAllocated.hpp"
#include "Internals/JsonPrintable.hpp"
#include "Internals/List.hpp"
Expand Down Expand Up @@ -35,62 +36,59 @@ class JsonObject : public Internals::JsonPrintable<JsonObject>,
public Internals::List<JsonPair>,
public Internals::JsonBufferAllocated {
public:
typedef const char *key_type;
typedef JsonPair value_type;

// Create an empty JsonArray attached to the specified JsonBuffer.
// You should not use this constructor directly.
// Instead, use JsonBuffer::createObject() or JsonBuffer.parseObject().
JSON_FORCE_INLINE explicit JsonObject(JsonBuffer *buffer)
FORCE_INLINE explicit JsonObject(JsonBuffer* buffer)
: Internals::List<JsonPair>(buffer) {}

// Gets or sets the value associated with the specified key.
JSON_FORCE_INLINE JsonObjectSubscript operator[](key_type key);
FORCE_INLINE JsonObjectSubscript operator[](JsonObjectKey key);

// Gets the value associated with the specified key.
JSON_FORCE_INLINE const JsonObjectSubscript operator[](key_type key) const;
FORCE_INLINE const JsonObjectSubscript operator[](JsonObjectKey key) const;

// Sets the specified key with the specified value.
JSON_FORCE_INLINE bool set(key_type key, const JsonVariant value);
FORCE_INLINE bool set(JsonObjectKey key, JsonVariant value);

// Gets the value associated with the specified key.
JSON_FORCE_INLINE JsonVariant get(key_type key) const;
FORCE_INLINE JsonVariant get(JsonObjectKey) const;

// Gets the value associated with the specified key.
template <typename T>
JSON_FORCE_INLINE T get(key_type key) const;
FORCE_INLINE T get(JsonObjectKey) const;

// Checks the type of the value associated with the specified key.
template <typename T>
JSON_FORCE_INLINE T is(key_type key) const;
FORCE_INLINE bool is(JsonObjectKey) const;

// Creates and adds a JsonArray.
// This is a shortcut for JsonBuffer::createArray() and JsonObject::add().
JsonArray &createNestedArray(key_type key);
JsonArray& createNestedArray(JsonObjectKey key);

// Creates and adds a JsonObject.
// This is a shortcut for JsonBuffer::createObject() and JsonObject::add().
JsonObject &createNestedObject(key_type key);
JsonObject& createNestedObject(JsonObjectKey key);

// Tells weither the specified key is present and associated with a value.
JSON_FORCE_INLINE bool containsKey(key_type key) const;
FORCE_INLINE bool containsKey(JsonObjectKey key) const;

// Removes the specified key and the associated value.
void remove(key_type key);
void remove(JsonObjectKey key);

// Returns a reference an invalid JsonObject.
// This object is meant to replace a NULL pointer.
// This is used when memory allocation or JSON parsing fail.
static JsonObject &invalid() { return _invalid; }
static JsonObject& invalid() { return _invalid; }

// Serialize the object to the specified JsonWriter
void writeTo(Internals::JsonWriter &writer) const;
void writeTo(Internals::JsonWriter& writer) const;

private:
// Returns the list node that matches the specified key.
node_type *getNodeAt(key_type key) const;
node_type* getNodeAt(JsonObjectKey key) const;

node_type *getOrCreateNodeAt(const char *key);
node_type* getOrCreateNodeAt(JsonObjectKey key);

// The instance returned by JsonObject::invalid()
static JsonObject _invalid;
Expand Down
25 changes: 17 additions & 8 deletions include/ArduinoJson/JsonObject.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -11,38 +11,41 @@

namespace ArduinoJson {

inline JsonVariant JsonObject::get(key_type key) const {
inline JsonVariant JsonObject::get(JsonObjectKey key) const {
node_type *node = getNodeAt(key);
return node ? node->content.value : JsonVariant();
}

template <typename T>
inline T JsonObject::get(key_type key) const {
inline T JsonObject::get(JsonObjectKey key) const {
node_type *node = getNodeAt(key);
return node ? node->content.value.as<T>() : JsonVariant::invalid<T>();
}

template <typename T>
inline T JsonObject::is(key_type key) const {
inline bool JsonObject::is(JsonObjectKey key) const {
node_type *node = getNodeAt(key);
return node ? node->content.value.is<T>() : false;
}

inline JsonObjectSubscript JsonObject::operator[](key_type key) {
inline JsonObjectSubscript JsonObject::operator[](JsonObjectKey key) {
return JsonObjectSubscript(*this, key);
}

inline const JsonObjectSubscript JsonObject::operator[](key_type key) const {
inline const JsonObjectSubscript JsonObject::operator[](
JsonObjectKey key) const {
return JsonObjectSubscript(*const_cast<JsonObject *>(this), key);
}

inline bool JsonObject::containsKey(key_type key) const {
inline bool JsonObject::containsKey(JsonObjectKey key) const {
return getNodeAt(key) != NULL;
}

inline void JsonObject::remove(key_type key) { removeNode(getNodeAt(key)); }
inline void JsonObject::remove(JsonObjectKey key) {
removeNode(getNodeAt(key));
}

inline bool JsonObject::set(const char *key, const JsonVariant value) {
inline bool JsonObject::set(JsonObjectKey key, const JsonVariant value) {
node_type *node = getOrCreateNodeAt(key);
if (!node) return false;

Expand All @@ -57,6 +60,12 @@ inline const JsonObjectSubscript JsonVariantBase<TImplem>::operator[](
return asObject()[key];
}

template <typename TImplem>
inline const JsonObjectSubscript JsonVariantBase<TImplem>::operator[](
const String &key) const {
return asObject()[key];
}

template <>
inline JsonObject const &JsonVariant::invalid<JsonObject const &>() {
return JsonObject::invalid();
Expand Down
24 changes: 24 additions & 0 deletions include/ArduinoJson/JsonObjectKey.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright Benoit Blanchon 2014-2015
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson

#pragma once

#include "Arduino/String.hpp"

namespace ArduinoJson {

class JsonObjectKey {
public:
JsonObjectKey() {}
JsonObjectKey(const char* key) : _data(key) {}
JsonObjectKey(const String& key) : _data(key.c_str()) {}

operator const char*() const { return _data; }

private:
const char* _data;
};
}
Loading

0 comments on commit 1b5be89

Please sign in to comment.