Skip to content

Commit

Permalink
Implicitly duplicate String in the JsonBuffer (issue #84, #87)
Browse files Browse the repository at this point in the history
  • Loading branch information
bblanchon committed Jul 25, 2015
1 parent 92e6873 commit c161f69
Show file tree
Hide file tree
Showing 20 changed files with 758 additions and 249 deletions.
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ ArduinoJson: change log
v5.0 (currently in beta)
----

* Added support of `String` class (issue #55, #56, #70, #77)
* Added support of `String` class (issues #55, #56, #70, #77)
* Added `JsonBuffer::strdup()` to make a copy of a string (issues #10, #57)
* Implicitly call `strdup()` for `String` but not for `char*` (issues #84, #87)
* Added support of non standard JSON input (issue #44)
* Redesigned `JsonVariant` to leverage converting constructors instead of assignment operators
* Redesigned `JsonVariant` to leverage converting constructors instead of assignment operators (issue #66)
* Switched to new the library layout (requires Arduino 1.0.6 or above)

**BREAKING CHANGES**:
Expand Down
5 changes: 0 additions & 5 deletions include/ArduinoJson/Internals/JsonVariantContent.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,6 @@ 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
45 changes: 42 additions & 3 deletions include/ArduinoJson/JsonArray.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,46 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
: Internals::List<JsonVariant>(buffer) {}

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

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

// Adds the specified value at the end of the array.
FORCE_INLINE bool add(const JsonVariant value);
FORCE_INLINE bool add(bool value);
FORCE_INLINE bool add(float value, uint8_t decimals = 2);
FORCE_INLINE bool add(double value, uint8_t decimals = 2);
FORCE_INLINE bool add(signed char value);
FORCE_INLINE bool add(signed long value);
FORCE_INLINE bool add(signed int value);
FORCE_INLINE bool add(signed short value);
FORCE_INLINE bool add(unsigned char value);
FORCE_INLINE bool add(unsigned long value);
FORCE_INLINE bool add(unsigned int value);
FORCE_INLINE bool add(unsigned short value);
FORCE_INLINE bool add(const char *value);
FORCE_INLINE bool add(const String &value);
FORCE_INLINE bool add(JsonArray &array);
FORCE_INLINE bool add(JsonObject &object);
FORCE_INLINE bool add(const JsonVariant &object);

// Sets the value at specified index.
FORCE_INLINE void set(size_t index, const JsonVariant value);
FORCE_INLINE void set(size_t index, bool value);
FORCE_INLINE void set(size_t index, float value, uint8_t decimals = 2);
FORCE_INLINE void set(size_t index, double value, uint8_t decimals = 2);
FORCE_INLINE void set(size_t index, signed char value);
FORCE_INLINE void set(size_t index, signed long value);
FORCE_INLINE void set(size_t index, signed int value);
FORCE_INLINE void set(size_t index, signed short value);
FORCE_INLINE void set(size_t index, unsigned char value);
FORCE_INLINE void set(size_t index, unsigned long value);
FORCE_INLINE void set(size_t index, unsigned int value);
FORCE_INLINE void set(size_t index, unsigned short value);
FORCE_INLINE void set(size_t index, const char *value);
FORCE_INLINE void set(size_t index, const String &value);
FORCE_INLINE void set(size_t index, JsonArray &array);
FORCE_INLINE void set(size_t index, JsonObject &object);
FORCE_INLINE void set(size_t index, const JsonVariant &object);

// Gets the value at the specified index.
FORCE_INLINE JsonVariant get(size_t index) const;
Expand Down Expand Up @@ -86,6 +116,15 @@ class JsonArray : public Internals::JsonPrintable<JsonArray>,
private:
node_type *getNodeAt(size_t index) const;

template <typename TValue>
void setNodeAt(size_t index, TValue value);

template <typename TValue>
bool addNode(TValue);

template <typename T>
FORCE_INLINE void setNodeValue(node_type *, T value);

// The instance returned by JsonArray::invalid()
static JsonArray _invalid;
};
Expand Down
160 changes: 150 additions & 10 deletions include/ArduinoJson/JsonArray.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,159 @@ inline JsonArraySubscript JsonArray::operator[](size_t index) {
return JsonArraySubscript(*this, index);
}

inline const JsonArraySubscript JsonArray::operator[](size_t index) const {
return JsonArraySubscript(*const_cast<JsonArray *>(this), index);
inline JsonVariant JsonArray::operator[](size_t index) const {
return get(index);
}

inline bool JsonArray::add(const JsonVariant value) {
inline bool JsonArray::add(bool value) { return addNode<bool>(value); }

inline bool JsonArray::add(float value, uint8_t decimals) {
return addNode<const JsonVariant &>(JsonVariant(value, decimals));
}

inline bool JsonArray::add(double value, uint8_t decimals) {
return addNode<const JsonVariant &>(JsonVariant(value, decimals));
}

inline bool JsonArray::add(signed char value) {
return addNode<signed char>(value);
}

inline bool JsonArray::add(signed long value) {
return addNode<signed long>(value);
}

inline bool JsonArray::add(signed int value) {
return addNode<signed int>(value);
}

inline bool JsonArray::add(signed short value) {
return addNode<signed short>(value);
}

inline bool JsonArray::add(unsigned char value) {
return addNode<unsigned char>(value);
}

inline bool JsonArray::add(unsigned long value) {
return addNode<unsigned long>(value);
}

inline bool JsonArray::add(unsigned int value) {
return addNode<unsigned int>(value);
}

inline bool JsonArray::add(unsigned short value) {
return addNode<unsigned short>(value);
}

inline bool JsonArray::add(const char *value) {
return addNode<const char *>(value);
}

inline bool JsonArray::add(const String &value) {
return addNode<const String &>(value);
}

inline bool JsonArray::add(JsonArray &array) {
return addNode<JsonArray &>(array);
}

inline bool JsonArray::add(JsonObject &object) {
return addNode<JsonObject &>(object);
}

inline bool JsonArray::add(const JsonVariant &object) {
return addNode<const JsonVariant &>(object);
}

template <typename TValue>
inline bool JsonArray::addNode(TValue value) {
node_type *node = addNewNode();
if (node) node->content = value;
return node != NULL;
if (node == NULL) return false;
setNodeValue<TValue>(node, value);
return true;
}

inline void JsonArray::set(size_t index, bool value) {
return setNodeAt<bool>(index, value);
}

inline void JsonArray::set(size_t index, float value, uint8_t decimals) {
return setNodeAt<const JsonVariant &>(index, JsonVariant(value, decimals));
}

inline void JsonArray::set(size_t index, double value, uint8_t decimals) {
return setNodeAt<const JsonVariant &>(index, JsonVariant(value, decimals));
}

inline void JsonArray::set(size_t index, signed char value) {
return setNodeAt<signed char>(index, value);
}

inline void JsonArray::set(size_t index, signed long value) {
return setNodeAt<signed long>(index, value);
}

inline void JsonArray::set(size_t index, signed int value) {
return setNodeAt<signed int>(index, value);
}

inline void JsonArray::set(size_t index, signed short value) {
return setNodeAt<signed short>(index, value);
}

inline void JsonArray::set(size_t index, unsigned char value) {
return setNodeAt<unsigned char>(index, value);
}

inline void JsonArray::set(size_t index, unsigned long value) {
return setNodeAt<unsigned long>(index, value);
}

inline void JsonArray::set(size_t index, unsigned int value) {
return setNodeAt<unsigned int>(index, value);
}

inline void JsonArray::set(size_t index, unsigned short value) {
return setNodeAt<unsigned short>(index, value);
}

inline void JsonArray::set(size_t index, const char *value) {
return setNodeAt<const char *>(index, value);
}

inline void JsonArray::set(size_t index, const String &value) {
return setNodeAt<const String &>(index, value);
}

inline void JsonArray::set(size_t index, JsonArray &array) {
return setNodeAt<JsonArray &>(index, array);
}

inline void JsonArray::set(size_t index, JsonObject &object) {
return setNodeAt<JsonObject &>(index, object);
}

inline void JsonArray::set(size_t index, const JsonVariant &object) {
return setNodeAt<const JsonVariant &>(index, object);
}

template <typename TValue>
inline void JsonArray::setNodeAt(size_t index, TValue value) {
node_type *node = getNodeAt(index);
if (node == NULL) return;
setNodeValue<TValue>(node, value);
}

template <typename TValue>
inline void JsonArray::setNodeValue(node_type *node, TValue value) {
node->content = value;
}

template <>
inline void JsonArray::setNodeValue(node_type *node, const String &value) {
node->content = _buffer->strdup(value);
}

inline JsonVariant JsonArray::get(size_t index) const {
Expand All @@ -42,11 +187,6 @@ inline T JsonArray::is(size_t index) const {
return node ? node->content.is<T>() : false;
}

inline void JsonArray::set(size_t index, const JsonVariant value) {
node_type *node = getNodeAt(index);
if (node) node->content = value;
}

template <typename TImplem>
inline const JsonArraySubscript JsonVariantBase<TImplem>::operator[](
int index) const {
Expand Down
21 changes: 12 additions & 9 deletions include/ArduinoJson/JsonArraySubscript.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,15 @@

#pragma once

#include "JsonVariantBase.hpp"
#include "JsonSubscriptBase.hpp"

namespace ArduinoJson {
class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
class JsonArraySubscript : public JsonSubscriptBase<JsonArraySubscript> {
public:
FORCE_INLINE JsonArraySubscript(JsonArray& array, size_t index)
: _array(array), _index(index) {}

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

FORCE_INLINE JsonArraySubscript& operator=(const JsonArraySubscript& other) {
// to prevent Visual Studio warning C4512: assignment operator could not be
Expand All @@ -40,19 +37,25 @@ class JsonArraySubscript : public JsonVariantBase<JsonArraySubscript> {
return _array.is<T>(_index);
}

void writeTo(Internals::JsonWriter &writer) const {
void writeTo(Internals::JsonWriter& writer) const {
_array.get(_index).writeTo(writer);
}

template <typename TValue>
void set(TValue value) {
_array.set(_index, value);
}

private:
JsonArray& _array;
const size_t _index;
};

#ifdef ARDUINOJSON_ENABLE_STD_STREAM
inline std::ostream& operator<<(std::ostream& os, const JsonArraySubscript& source) {
inline std::ostream& operator<<(std::ostream& os,
const JsonArraySubscript& source) {
return source.printTo(os);
}
#endif

} // namespace ArduinoJson
} // namespace ArduinoJson
14 changes: 10 additions & 4 deletions include/ArduinoJson/JsonBuffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@

#include <stddef.h> // for size_t
#include <stdint.h> // for uint8_t
#include <string.h>

#include "Arduino/String.hpp"
#include "JsonVariant.hpp"

#if defined(__clang__)
#pragma clang diagnostic ignored "-Wnon-virtual-dtor"
Expand Down Expand Up @@ -59,7 +61,7 @@ class JsonBuffer {

// 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);
return parseArray(strdup(json), nesting);
}

// Allocates and populate a JsonObject from a JSON string.
Expand All @@ -75,11 +77,15 @@ class JsonBuffer {
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);
JsonObject &parseObject(const String &json, uint8_t nesting = DEFAULT_LIMIT) {
return parseObject(strdup(json), nesting);
}

// Duplicate a string
char *strdup(const char *src) { return strdup(src, strlen(src)); }
char *strdup(const String &src) { return strdup(src.c_str(), src.length()); }
char *strdup(const char *, size_t);

// 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
Loading

0 comments on commit c161f69

Please sign in to comment.