Added a line-break after each "if" to get more accurate coverage report

This commit is contained in:
Benoit Blanchon
2020-02-16 15:05:23 +01:00
parent 8f8c82d400
commit 0814fc185f
38 changed files with 429 additions and 214 deletions

View File

@ -3,3 +3,6 @@
BasedOnStyle: Google BasedOnStyle: Google
Standard: Cpp03 Standard: Cpp03
AllowShortFunctionsOnASingleLine: Empty AllowShortFunctionsOnASingleLine: Empty
# Always break after if to get accurate coverage
AllowShortIfStatementsOnASingleLine: false

View File

@ -21,9 +21,10 @@ inline void arrayAccept(const CollectionData *arr, Visitor &visitor) {
} }
inline bool arrayEquals(const CollectionData *lhs, const CollectionData *rhs) { inline bool arrayEquals(const CollectionData *lhs, const CollectionData *rhs) {
if (lhs == rhs) return true; if (lhs == rhs)
if (!lhs || !rhs) return false; return true;
if (!lhs || !rhs)
return false;
return lhs->equalsArray(*rhs); return lhs->equalsArray(*rhs);
} }
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@ -66,7 +66,8 @@ class ArrayConstRef : public ArrayRefBase<const CollectionData>,
typedef ArrayConstRefIterator iterator; typedef ArrayConstRefIterator iterator;
FORCE_INLINE iterator begin() const { FORCE_INLINE iterator begin() const {
if (!_data) return iterator(); if (!_data)
return iterator();
return iterator(_data->head()); return iterator(_data->head());
} }
@ -116,7 +117,8 @@ class ArrayRef : public ArrayRefBase<CollectionData>,
} }
FORCE_INLINE iterator begin() const { FORCE_INLINE iterator begin() const {
if (!_data) return iterator(); if (!_data)
return iterator();
return iterator(_pool, _data->head()); return iterator(_pool, _data->head());
} }
@ -126,7 +128,8 @@ class ArrayRef : public ArrayRefBase<CollectionData>,
// Copy a ArrayRef // Copy a ArrayRef
FORCE_INLINE bool set(ArrayConstRef src) const { FORCE_INLINE bool set(ArrayConstRef src) const {
if (!_data || !src._data) return false; if (!_data || !src._data)
return false;
return _data->copyFrom(*src._data, _pool); return _data->copyFrom(*src._data, _pool);
} }
@ -141,13 +144,15 @@ class ArrayRef : public ArrayRefBase<CollectionData>,
// Removes element at specified position. // Removes element at specified position.
FORCE_INLINE void remove(iterator it) const { FORCE_INLINE void remove(iterator it) const {
if (!_data) return; if (!_data)
return;
_data->remove(it.internal()); _data->remove(it.internal());
} }
// Removes element at specified index. // Removes element at specified index.
FORCE_INLINE void remove(size_t index) const { FORCE_INLINE void remove(size_t index) const {
if (!_data) return; if (!_data)
return;
_data->remove(index); _data->remove(index);
} }

View File

@ -11,7 +11,8 @@ namespace ARDUINOJSON_NAMESPACE {
inline VariantSlot* CollectionData::addSlot(MemoryPool* pool) { inline VariantSlot* CollectionData::addSlot(MemoryPool* pool) {
VariantSlot* slot = pool->allocVariant(); VariantSlot* slot = pool->allocVariant();
if (!slot) return 0; if (!slot)
return 0;
if (_tail) { if (_tail) {
_tail->setNextNotNull(slot); _tail->setNextNotNull(slot);
@ -32,7 +33,8 @@ inline VariantData* CollectionData::add(MemoryPool* pool) {
template <typename TAdaptedString> template <typename TAdaptedString>
inline VariantData* CollectionData::add(TAdaptedString key, MemoryPool* pool) { inline VariantData* CollectionData::add(TAdaptedString key, MemoryPool* pool) {
VariantSlot* slot = addSlot(pool); VariantSlot* slot = addSlot(pool);
if (!slotSetKey(slot, key, pool)) return 0; if (!slotSetKey(slot, key, pool))
return 0;
return slot->data(); return slot->data();
} }
@ -59,8 +61,10 @@ inline bool CollectionData::copyFrom(const CollectionData& src,
} else { } else {
var = add(pool); var = add(pool);
} }
if (!var) return false; if (!var)
if (!var->copyFrom(*s->data(), pool)) return false; return false;
if (!var->copyFrom(*s->data(), pool))
return false;
} }
return true; return true;
} }
@ -70,7 +74,8 @@ inline bool CollectionData::equalsObject(const CollectionData& other) const {
for (VariantSlot* slot = _head; slot; slot = slot->next()) { for (VariantSlot* slot = _head; slot; slot = slot->next()) {
VariantData* v1 = slot->data(); VariantData* v1 = slot->data();
VariantData* v2 = other.get(adaptString(slot->key())); VariantData* v2 = other.get(adaptString(slot->key()));
if (!variantEquals(v1, v2)) return false; if (!variantEquals(v1, v2))
return false;
count++; count++;
} }
return count == other.size(); return count == other.size();
@ -80,9 +85,12 @@ inline bool CollectionData::equalsArray(const CollectionData& other) const {
VariantSlot* s1 = _head; VariantSlot* s1 = _head;
VariantSlot* s2 = other._head; VariantSlot* s2 = other._head;
for (;;) { for (;;) {
if (s1 == s2) return true; if (s1 == s2)
if (!s1 || !s2) return false; return true;
if (!variantEquals(s1->data(), s2->data())) return false; if (!s1 || !s2)
return false;
if (!variantEquals(s1->data(), s2->data()))
return false;
s1 = s1->next(); s1 = s1->next();
s2 = s2->next(); s2 = s2->next();
} }
@ -92,7 +100,8 @@ template <typename TAdaptedString>
inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const { inline VariantSlot* CollectionData::getSlot(TAdaptedString key) const {
VariantSlot* slot = _head; VariantSlot* slot = _head;
while (slot) { while (slot) {
if (key.equals(slot->key())) break; if (key.equals(slot->key()))
break;
slot = slot->next(); slot = slot->next();
} }
return slot; return slot;
@ -106,7 +115,8 @@ inline VariantSlot* CollectionData::getPreviousSlot(VariantSlot* target) const {
VariantSlot* current = _head; VariantSlot* current = _head;
while (current) { while (current) {
VariantSlot* next = current->next(); VariantSlot* next = current->next();
if (next == target) return current; if (next == target)
return current;
current = next; current = next;
} }
return 0; return 0;
@ -124,14 +134,16 @@ inline VariantData* CollectionData::get(size_t index) const {
} }
inline void CollectionData::remove(VariantSlot* slot) { inline void CollectionData::remove(VariantSlot* slot) {
if (!slot) return; if (!slot)
return;
VariantSlot* prev = getPreviousSlot(slot); VariantSlot* prev = getPreviousSlot(slot);
VariantSlot* next = slot->next(); VariantSlot* next = slot->next();
if (prev) if (prev)
prev->setNext(next); prev->setNext(next);
else else
_head = next; _head = next;
if (!next) _tail = prev; if (!next)
_tail = prev;
} }
inline void CollectionData::remove(size_t index) { inline void CollectionData::remove(size_t index) {
@ -142,7 +154,8 @@ inline size_t CollectionData::memoryUsage() const {
size_t total = 0; size_t total = 0;
for (VariantSlot* s = _head; s; s = s->next()) { for (VariantSlot* s = _head; s; s = s->next()) {
total += sizeof(VariantSlot) + s->data()->memoryUsage(); total += sizeof(VariantSlot) + s->data()->memoryUsage();
if (s->ownsKey()) total += strlen(s->key()) + 1; if (s->ownsKey())
total += strlen(s->key()) + 1;
} }
return total; return total;
} }
@ -151,7 +164,8 @@ inline size_t CollectionData::nesting() const {
size_t maxChildNesting = 0; size_t maxChildNesting = 0;
for (VariantSlot* s = _head; s; s = s->next()) { for (VariantSlot* s = _head; s; s = s->next()) {
size_t childNesting = s->data()->nesting(); size_t childNesting = s->data()->nesting();
if (childNesting > maxChildNesting) maxChildNesting = childNesting; if (childNesting > maxChildNesting)
maxChildNesting = childNesting;
} }
return maxChildNesting + 1; return maxChildNesting + 1;
} }
@ -162,7 +176,8 @@ inline size_t CollectionData::size() const {
template <typename T> template <typename T>
inline void movePointer(T*& p, ptrdiff_t offset) { inline void movePointer(T*& p, ptrdiff_t offset) {
if (!p) return; if (!p)
return;
p = reinterpret_cast<T*>( p = reinterpret_cast<T*>(
reinterpret_cast<void*>(reinterpret_cast<char*>(p) + offset)); reinterpret_cast<void*>(reinterpret_cast<char*>(p) + offset));
ARDUINOJSON_ASSERT(isAligned(p)); ARDUINOJSON_ASSERT(isAligned(p));

View File

@ -43,7 +43,8 @@ struct BoundedReader<const __FlashStringHelper*, void> {
size_t readBytes(char* buffer, size_t length) { size_t readBytes(char* buffer, size_t length) {
size_t available = static_cast<size_t>(_end - _ptr); size_t available = static_cast<size_t>(_end - _ptr);
if (available < length) length = available; if (available < length)
length = available;
memcpy_P(buffer, _ptr, length); memcpy_P(buffer, _ptr, length);
_ptr += length; _ptr += length;
return length; return length;

View File

@ -77,7 +77,8 @@ class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
void shrinkToFit() { void shrinkToFit() {
ptrdiff_t bytes_reclaimed = _pool.squash(); ptrdiff_t bytes_reclaimed = _pool.squash();
if (bytes_reclaimed == 0) return; if (bytes_reclaimed == 0)
return;
void* old_ptr = _pool.buffer(); void* old_ptr = _pool.buffer();
void* new_ptr = this->reallocate(old_ptr, _pool.capacity()); void* new_ptr = this->reallocate(old_ptr, _pool.capacity());
@ -96,7 +97,8 @@ class BasicJsonDocument : AllocatorOwner<TAllocator>, public JsonDocument {
} }
void reallocPoolIfTooSmall(size_t requiredSize) { void reallocPoolIfTooSmall(size_t requiredSize) {
if (requiredSize <= capacity()) return; if (requiredSize <= capacity())
return;
freePool(); freePool();
replacePool(allocPool(addPadding(requiredSize))); replacePool(allocPool(addPadding(requiredSize)));
} }

View File

@ -23,8 +23,10 @@ class EscapeSequence {
static char unescapeChar(char c) { static char unescapeChar(char c) {
const char *p = escapeTable(true); const char *p = escapeTable(true);
for (;;) { for (;;) {
if (p[0] == '\0') return c; if (p[0] == '\0')
if (p[0] == c) return p[1]; return c;
if (p[0] == c)
return p[1];
p += 2; p += 2;
} }
} }

View File

@ -52,7 +52,8 @@ class JsonDeserializer {
} }
bool eat(char charToSkip) { bool eat(char charToSkip) {
if (current() != charToSkip) return false; if (current() != charToSkip)
return false;
move(); move();
return true; return true;
} }
@ -61,7 +62,8 @@ class JsonDeserializer {
DeserializationError parseVariant(VariantData &variant, TFilter filter, DeserializationError parseVariant(VariantData &variant, TFilter filter,
NestingLimit nestingLimit) { NestingLimit nestingLimit) {
DeserializationError err = skipSpacesAndComments(); DeserializationError err = skipSpacesAndComments();
if (err) return err; if (err)
return err;
switch (current()) { switch (current()) {
case '[': case '[':
@ -93,7 +95,8 @@ class JsonDeserializer {
DeserializationError skipVariant(NestingLimit nestingLimit) { DeserializationError skipVariant(NestingLimit nestingLimit) {
DeserializationError err = skipSpacesAndComments(); DeserializationError err = skipSpacesAndComments();
if (err) return err; if (err)
return err;
switch (current()) { switch (current()) {
case '[': case '[':
@ -114,7 +117,8 @@ class JsonDeserializer {
template <typename TFilter> template <typename TFilter>
DeserializationError parseArray(CollectionData &array, TFilter filter, DeserializationError parseArray(CollectionData &array, TFilter filter,
NestingLimit nestingLimit) { NestingLimit nestingLimit) {
if (nestingLimit.reached()) return DeserializationError::TooDeep; if (nestingLimit.reached())
return DeserializationError::TooDeep;
// Skip opening braket // Skip opening braket
ARDUINOJSON_ASSERT(current() == '['); ARDUINOJSON_ASSERT(current() == '[');
@ -122,10 +126,12 @@ class JsonDeserializer {
// Skip spaces // Skip spaces
DeserializationError err = skipSpacesAndComments(); DeserializationError err = skipSpacesAndComments();
if (err) return err; if (err)
return err;
// Empty array? // Empty array?
if (eat(']')) return DeserializationError::Ok; if (eat(']'))
return DeserializationError::Ok;
TFilter memberFilter = filter[0UL]; TFilter memberFilter = filter[0UL];
@ -134,28 +140,35 @@ class JsonDeserializer {
if (memberFilter.allow()) { if (memberFilter.allow()) {
// Allocate slot in array // Allocate slot in array
VariantData *value = array.add(_pool); VariantData *value = array.add(_pool);
if (!value) return DeserializationError::NoMemory; if (!value)
return DeserializationError::NoMemory;
// 1 - Parse value // 1 - Parse value
err = parseVariant(*value, memberFilter, nestingLimit.decrement()); err = parseVariant(*value, memberFilter, nestingLimit.decrement());
if (err) return err; if (err)
return err;
} else { } else {
err = skipVariant(nestingLimit.decrement()); err = skipVariant(nestingLimit.decrement());
if (err) return err; if (err)
return err;
} }
// 2 - Skip spaces // 2 - Skip spaces
err = skipSpacesAndComments(); err = skipSpacesAndComments();
if (err) return err; if (err)
return err;
// 3 - More values? // 3 - More values?
if (eat(']')) return DeserializationError::Ok; if (eat(']'))
if (!eat(',')) return DeserializationError::InvalidInput; return DeserializationError::Ok;
if (!eat(','))
return DeserializationError::InvalidInput;
} }
} }
DeserializationError skipArray(NestingLimit nestingLimit) { DeserializationError skipArray(NestingLimit nestingLimit) {
if (nestingLimit.reached()) return DeserializationError::TooDeep; if (nestingLimit.reached())
return DeserializationError::TooDeep;
// Skip opening braket // Skip opening braket
ARDUINOJSON_ASSERT(current() == '['); ARDUINOJSON_ASSERT(current() == '[');
@ -165,22 +178,27 @@ class JsonDeserializer {
for (;;) { for (;;) {
// 1 - Skip value // 1 - Skip value
DeserializationError err = skipVariant(nestingLimit.decrement()); DeserializationError err = skipVariant(nestingLimit.decrement());
if (err) return err; if (err)
return err;
// 2 - Skip spaces // 2 - Skip spaces
err = skipSpacesAndComments(); err = skipSpacesAndComments();
if (err) return err; if (err)
return err;
// 3 - More values? // 3 - More values?
if (eat(']')) return DeserializationError::Ok; if (eat(']'))
if (!eat(',')) return DeserializationError::InvalidInput; return DeserializationError::Ok;
if (!eat(','))
return DeserializationError::InvalidInput;
} }
} }
template <typename TFilter> template <typename TFilter>
DeserializationError parseObject(CollectionData &object, TFilter filter, DeserializationError parseObject(CollectionData &object, TFilter filter,
NestingLimit nestingLimit) { NestingLimit nestingLimit) {
if (nestingLimit.reached()) return DeserializationError::TooDeep; if (nestingLimit.reached())
return DeserializationError::TooDeep;
// Skip opening brace // Skip opening brace
ARDUINOJSON_ASSERT(current() == '{'); ARDUINOJSON_ASSERT(current() == '{');
@ -188,22 +206,27 @@ class JsonDeserializer {
// Skip spaces // Skip spaces
DeserializationError err = skipSpacesAndComments(); DeserializationError err = skipSpacesAndComments();
if (err) return err; if (err)
return err;
// Empty object? // Empty object?
if (eat('}')) return DeserializationError::Ok; if (eat('}'))
return DeserializationError::Ok;
// Read each key value pair // Read each key value pair
for (;;) { for (;;) {
// Parse key // Parse key
const char *key; const char *key;
err = parseKey(key); err = parseKey(key);
if (err) return err; if (err)
return err;
// Skip spaces // Skip spaces
err = skipSpacesAndComments(); err = skipSpacesAndComments();
if (err) return err; // Colon if (err)
if (!eat(':')) return DeserializationError::InvalidInput; return err; // Colon
if (!eat(':'))
return DeserializationError::InvalidInput;
TFilter memberFilter = filter[key]; TFilter memberFilter = filter[key];
@ -212,7 +235,8 @@ class JsonDeserializer {
if (!variant) { if (!variant) {
// Allocate slot in object // Allocate slot in object
VariantSlot *slot = object.addSlot(_pool); VariantSlot *slot = object.addSlot(_pool);
if (!slot) return DeserializationError::NoMemory; if (!slot)
return DeserializationError::NoMemory;
slot->setOwnedKey(make_not_null(key)); slot->setOwnedKey(make_not_null(key));
@ -221,29 +245,36 @@ class JsonDeserializer {
// Parse value // Parse value
err = parseVariant(*variant, memberFilter, nestingLimit.decrement()); err = parseVariant(*variant, memberFilter, nestingLimit.decrement());
if (err) return err; if (err)
return err;
} else { } else {
_stringStorage.reclaim(key); _stringStorage.reclaim(key);
err = skipVariant(nestingLimit.decrement()); err = skipVariant(nestingLimit.decrement());
if (err) return err; if (err)
return err;
} }
// Skip spaces // Skip spaces
err = skipSpacesAndComments(); err = skipSpacesAndComments();
if (err) return err; if (err)
return err;
// More keys/values? // More keys/values?
if (eat('}')) return DeserializationError::Ok; if (eat('}'))
if (!eat(',')) return DeserializationError::InvalidInput; return DeserializationError::Ok;
if (!eat(','))
return DeserializationError::InvalidInput;
// Skip spaces // Skip spaces
err = skipSpacesAndComments(); err = skipSpacesAndComments();
if (err) return err; if (err)
return err;
} }
} }
DeserializationError skipObject(NestingLimit nestingLimit) { DeserializationError skipObject(NestingLimit nestingLimit) {
if (nestingLimit.reached()) return DeserializationError::TooDeep; if (nestingLimit.reached())
return DeserializationError::TooDeep;
// Skip opening brace // Skip opening brace
ARDUINOJSON_ASSERT(current() == '{'); ARDUINOJSON_ASSERT(current() == '{');
@ -251,33 +282,42 @@ class JsonDeserializer {
// Skip spaces // Skip spaces
DeserializationError err = skipSpacesAndComments(); DeserializationError err = skipSpacesAndComments();
if (err) return err; if (err)
return err;
// Empty object? // Empty object?
if (eat('}')) return DeserializationError::Ok; if (eat('}'))
return DeserializationError::Ok;
// Read each key value pair // Read each key value pair
for (;;) { for (;;) {
// Skip key // Skip key
err = skipVariant(nestingLimit.decrement()); err = skipVariant(nestingLimit.decrement());
if (err) return err; if (err)
return err;
// Skip spaces // Skip spaces
err = skipSpacesAndComments(); err = skipSpacesAndComments();
if (err) return err; // Colon if (err)
if (!eat(':')) return DeserializationError::InvalidInput; return err; // Colon
if (!eat(':'))
return DeserializationError::InvalidInput;
// Skip value // Skip value
err = skipVariant(nestingLimit.decrement()); err = skipVariant(nestingLimit.decrement());
if (err) return err; if (err)
return err;
// Skip spaces // Skip spaces
err = skipSpacesAndComments(); err = skipSpacesAndComments();
if (err) return err; if (err)
return err;
// More keys/values? // More keys/values?
if (eat('}')) return DeserializationError::Ok; if (eat('}'))
if (!eat(',')) return DeserializationError::InvalidInput; return DeserializationError::Ok;
if (!eat(','))
return DeserializationError::InvalidInput;
} }
} }
@ -292,7 +332,8 @@ class JsonDeserializer {
DeserializationError parseStringValue(VariantData &variant) { DeserializationError parseStringValue(VariantData &variant) {
const char *value; const char *value;
DeserializationError err = parseQuotedString(value); DeserializationError err = parseQuotedString(value);
if (err) return err; if (err)
return err;
variant.setOwnedString(make_not_null(value)); variant.setOwnedString(make_not_null(value));
return DeserializationError::Ok; return DeserializationError::Ok;
} }
@ -308,19 +349,23 @@ class JsonDeserializer {
for (;;) { for (;;) {
char c = current(); char c = current();
move(); move();
if (c == stopChar) break; if (c == stopChar)
break;
if (c == '\0') return DeserializationError::IncompleteInput; if (c == '\0')
return DeserializationError::IncompleteInput;
if (c == '\\') { if (c == '\\') {
c = current(); c = current();
if (c == '\0') return DeserializationError::IncompleteInput; if (c == '\0')
return DeserializationError::IncompleteInput;
if (c == 'u') { if (c == 'u') {
#if ARDUINOJSON_DECODE_UNICODE #if ARDUINOJSON_DECODE_UNICODE
move(); move();
uint16_t codeunit; uint16_t codeunit;
DeserializationError err = parseHex4(codeunit); DeserializationError err = parseHex4(codeunit);
if (err) return err; if (err)
return err;
if (codepoint.append(codeunit)) if (codepoint.append(codeunit))
Utf8::encodeCodepoint(codepoint.value(), builder); Utf8::encodeCodepoint(codepoint.value(), builder);
continue; continue;
@ -330,7 +375,8 @@ class JsonDeserializer {
} }
// replace char // replace char
c = EscapeSequence::unescapeChar(c); c = EscapeSequence::unescapeChar(c);
if (c == '\0') return DeserializationError::InvalidInput; if (c == '\0')
return DeserializationError::InvalidInput;
move(); move();
} }
@ -338,7 +384,8 @@ class JsonDeserializer {
} }
result = builder.complete(); result = builder.complete();
if (!result) return DeserializationError::NoMemory; if (!result)
return DeserializationError::NoMemory;
return DeserializationError::Ok; return DeserializationError::Ok;
} }
@ -346,7 +393,8 @@ class JsonDeserializer {
StringBuilder builder = _stringStorage.startString(); StringBuilder builder = _stringStorage.startString();
char c = current(); char c = current();
if (c == '\0') return DeserializationError::IncompleteInput; if (c == '\0')
return DeserializationError::IncompleteInput;
if (canBeInNonQuotedString(c)) { // no quotes if (canBeInNonQuotedString(c)) { // no quotes
do { do {
@ -359,7 +407,8 @@ class JsonDeserializer {
} }
result = builder.complete(); result = builder.complete();
if (!result) return DeserializationError::NoMemory; if (!result)
return DeserializationError::NoMemory;
return DeserializationError::Ok; return DeserializationError::Ok;
} }
@ -370,10 +419,13 @@ class JsonDeserializer {
for (;;) { for (;;) {
char c = current(); char c = current();
move(); move();
if (c == stopChar) break; if (c == stopChar)
if (c == '\0') return DeserializationError::IncompleteInput; break;
if (c == '\0')
return DeserializationError::IncompleteInput;
if (c == '\\') { if (c == '\\') {
if (current() != '\0') move(); if (current() != '\0')
move();
} }
} }
@ -441,9 +493,11 @@ class JsonDeserializer {
result = 0; result = 0;
for (uint8_t i = 0; i < 4; ++i) { for (uint8_t i = 0; i < 4; ++i) {
char digit = current(); char digit = current();
if (!digit) return DeserializationError::IncompleteInput; if (!digit)
return DeserializationError::IncompleteInput;
uint8_t value = decodeHex(digit); uint8_t value = decodeHex(digit);
if (value > 0x0F) return DeserializationError::InvalidInput; if (value > 0x0F)
return DeserializationError::InvalidInput;
result = uint16_t((result << 4) | value); result = uint16_t((result << 4) | value);
move(); move();
} }
@ -464,7 +518,8 @@ class JsonDeserializer {
} }
static inline uint8_t decodeHex(char c) { static inline uint8_t decodeHex(char c) {
if (c < 'A') return uint8_t(c - '0'); if (c < 'A')
return uint8_t(c - '0');
c = char(c & ~0x20); // uppercase c = char(c & ~0x20); // uppercase
return uint8_t(c - 'A' + 10); return uint8_t(c - 'A' + 10);
} }
@ -495,7 +550,8 @@ class JsonDeserializer {
bool wasStar = false; bool wasStar = false;
for (;;) { for (;;) {
char c = current(); char c = current();
if (c == '\0') return DeserializationError::IncompleteInput; if (c == '\0')
return DeserializationError::IncompleteInput;
if (c == '/' && wasStar) { if (c == '/' && wasStar) {
move(); move();
break; break;
@ -512,8 +568,10 @@ class JsonDeserializer {
for (;;) { for (;;) {
move(); move();
char c = current(); char c = current();
if (c == '\0') return DeserializationError::IncompleteInput; if (c == '\0')
if (c == '\n') break; return DeserializationError::IncompleteInput;
if (c == '\n')
break;
} }
break; break;

View File

@ -25,7 +25,8 @@ class JsonSerializer {
slot->data()->accept(*this); slot->data()->accept(*this);
slot = slot->next(); slot = slot->next();
if (slot == 0) break; if (slot == 0)
break;
write(','); write(',');
} }
@ -44,7 +45,8 @@ class JsonSerializer {
slot->data()->accept(*this); slot->data()->accept(*this);
slot = slot->next(); slot = slot->next();
if (slot == 0) break; if (slot == 0)
break;
write(','); write(',');
} }

View File

@ -37,7 +37,8 @@ class Latch {
ARDUINOJSON_ASSERT(!_ended); ARDUINOJSON_ASSERT(!_ended);
int c = _reader.read(); int c = _reader.read();
#ifdef ARDUINOJSON_DEBUG #ifdef ARDUINOJSON_DEBUG
if (c <= 0) _ended = true; if (c <= 0)
_ended = true;
#endif #endif
_current = static_cast<char>(c > 0 ? c : 0); _current = static_cast<char>(c > 0 ? c : 0);
_loaded = true; _loaded = true;

View File

@ -20,7 +20,8 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> {
void visitArray(const CollectionData &array) { void visitArray(const CollectionData &array) {
VariantSlot *slot = array.head(); VariantSlot *slot = array.head();
if (!slot) return base::write("[]"); if (!slot)
return base::write("[]");
base::write("[\r\n"); base::write("[\r\n");
_nesting++; _nesting++;
@ -38,7 +39,8 @@ class PrettyJsonSerializer : public JsonSerializer<TWriter> {
void visitObject(const CollectionData &object) { void visitObject(const CollectionData &object) {
VariantSlot *slot = object.head(); VariantSlot *slot = object.head();
if (!slot) return base::write("{}"); if (!slot)
return base::write("{}");
base::write("{\r\n"); base::write("{\r\n");
_nesting++; _nesting++;

View File

@ -53,7 +53,8 @@ class TextFormatter {
template <typename T> template <typename T>
void writeFloat(T value) { void writeFloat(T value) {
if (isnan(value)) return writeRaw(ARDUINOJSON_ENABLE_NAN ? "NaN" : "null"); if (isnan(value))
return writeRaw(ARDUINOJSON_ENABLE_NAN ? "NaN" : "null");
#if ARDUINOJSON_ENABLE_INFINITY #if ARDUINOJSON_ENABLE_INFINITY
if (value < 0.0) { if (value < 0.0) {
@ -61,9 +62,11 @@ class TextFormatter {
value = -value; value = -value;
} }
if (isinf(value)) return writeRaw("Infinity"); if (isinf(value))
return writeRaw("Infinity");
#else #else
if (isinf(value)) return writeRaw("null"); if (isinf(value))
return writeRaw("null");
if (value < 0.0) { if (value < 0.0) {
writeRaw('-'); writeRaw('-');
@ -74,7 +77,8 @@ class TextFormatter {
FloatParts<T> parts(value); FloatParts<T> parts(value);
writePositiveInteger(parts.integral); writePositiveInteger(parts.integral);
if (parts.decimalPlaces) writeDecimals(parts.decimal, parts.decimalPlaces); if (parts.decimalPlaces)
writeDecimals(parts.decimal, parts.decimalPlaces);
if (parts.exponent < 0) { if (parts.exponent < 0) {
writeRaw("e-"); writeRaw("e-");

View File

@ -52,7 +52,8 @@ class MemoryPool {
} }
char* allocFrozenString(size_t n) { char* allocFrozenString(size_t n) {
if (!canAlloc(n)) return 0; if (!canAlloc(n))
return 0;
char* s = _left; char* s = _left;
_left += n; _left += n;
checkInvariants(); checkInvariants();
@ -97,7 +98,8 @@ class MemoryPool {
} }
void* allocRight(size_t bytes) { void* allocRight(size_t bytes) {
if (!canAlloc(bytes)) return 0; if (!canAlloc(bytes))
return 0;
_right -= bytes; _right -= bytes;
return _right; return _right;
} }
@ -120,7 +122,8 @@ class MemoryPool {
// This funcion is called before a realloc. // This funcion is called before a realloc.
ptrdiff_t squash() { ptrdiff_t squash() {
char* new_right = addPadding(_left); char* new_right = addPadding(_left);
if (new_right >= _right) return 0; if (new_right >= _right)
return 0;
size_t right_size = static_cast<size_t>(_end - _right); size_t right_size = static_cast<size_t>(_end - _right);
memmove(new_right, _right, right_size); memmove(new_right, _right, right_size);

View File

@ -23,7 +23,8 @@ class StringBuilder {
} }
void append(char c) { void append(char c) {
if (!_slot.value) return; if (!_slot.value)
return;
if (_size >= _slot.size) { if (_size >= _slot.size) {
_slot.value = 0; _slot.value = 0;

View File

@ -31,7 +31,8 @@ class MsgPackDeserializer {
DeserializationError parse(VariantData &variant, NestingLimit nestingLimit) { DeserializationError parse(VariantData &variant, NestingLimit nestingLimit) {
uint8_t code; uint8_t code;
if (!readByte(code)) return DeserializationError::IncompleteInput; if (!readByte(code))
return DeserializationError::IncompleteInput;
if ((code & 0x80) == 0) { if ((code & 0x80) == 0) {
variant.setUnsignedInteger(code); variant.setUnsignedInteger(code);
@ -139,7 +140,8 @@ class MsgPackDeserializer {
bool readByte(uint8_t &value) { bool readByte(uint8_t &value) {
int c = _reader.read(); int c = _reader.read();
if (c < 0) return false; if (c < 0)
return false;
value = static_cast<uint8_t>(c); value = static_cast<uint8_t>(c);
return true; return true;
} }
@ -163,7 +165,8 @@ class MsgPackDeserializer {
template <typename T> template <typename T>
bool readInteger(T &value) { bool readInteger(T &value) {
if (!readBytes(value)) return false; if (!readBytes(value))
return false;
fixEndianess(value); fixEndianess(value);
return true; return true;
} }
@ -171,7 +174,8 @@ class MsgPackDeserializer {
template <typename T> template <typename T>
DeserializationError readInteger(VariantData &variant) { DeserializationError readInteger(VariantData &variant) {
T value; T value;
if (!readInteger(value)) return DeserializationError::IncompleteInput; if (!readInteger(value))
return DeserializationError::IncompleteInput;
variant.setInteger(value); variant.setInteger(value);
return DeserializationError::Ok; return DeserializationError::Ok;
} }
@ -180,7 +184,8 @@ class MsgPackDeserializer {
typename enable_if<sizeof(T) == 4, DeserializationError>::type readFloat( typename enable_if<sizeof(T) == 4, DeserializationError>::type readFloat(
VariantData &variant) { VariantData &variant) {
T value; T value;
if (!readBytes(value)) return DeserializationError::IncompleteInput; if (!readBytes(value))
return DeserializationError::IncompleteInput;
fixEndianess(value); fixEndianess(value);
variant.setFloat(value); variant.setFloat(value);
return DeserializationError::Ok; return DeserializationError::Ok;
@ -190,7 +195,8 @@ class MsgPackDeserializer {
typename enable_if<sizeof(T) == 8, DeserializationError>::type readDouble( typename enable_if<sizeof(T) == 8, DeserializationError>::type readDouble(
VariantData &variant) { VariantData &variant) {
T value; T value;
if (!readBytes(value)) return DeserializationError::IncompleteInput; if (!readBytes(value))
return DeserializationError::IncompleteInput;
fixEndianess(value); fixEndianess(value);
variant.setFloat(value); variant.setFloat(value);
return DeserializationError::Ok; return DeserializationError::Ok;
@ -202,7 +208,8 @@ class MsgPackDeserializer {
uint8_t i[8]; // input is 8 bytes uint8_t i[8]; // input is 8 bytes
T value; // output is 4 bytes T value; // output is 4 bytes
uint8_t *o = reinterpret_cast<uint8_t *>(&value); uint8_t *o = reinterpret_cast<uint8_t *>(&value);
if (!readBytes(i, 8)) return DeserializationError::IncompleteInput; if (!readBytes(i, 8))
return DeserializationError::IncompleteInput;
doubleToFloat(i, o); doubleToFloat(i, o);
fixEndianess(value); fixEndianess(value);
variant.setFloat(value); variant.setFloat(value);
@ -212,21 +219,24 @@ class MsgPackDeserializer {
template <typename T> template <typename T>
DeserializationError readString(VariantData &variant) { DeserializationError readString(VariantData &variant) {
T size; T size;
if (!readInteger(size)) return DeserializationError::IncompleteInput; if (!readInteger(size))
return DeserializationError::IncompleteInput;
return readString(variant, size); return readString(variant, size);
} }
template <typename T> template <typename T>
DeserializationError readString(const char *&str) { DeserializationError readString(const char *&str) {
T size; T size;
if (!readInteger(size)) return DeserializationError::IncompleteInput; if (!readInteger(size))
return DeserializationError::IncompleteInput;
return readString(str, size); return readString(str, size);
} }
DeserializationError readString(VariantData &variant, size_t n) { DeserializationError readString(VariantData &variant, size_t n) {
const char *s; const char *s;
DeserializationError err = readString(s, n); DeserializationError err = readString(s, n);
if (!err) variant.setOwnedString(make_not_null(s)); if (!err)
variant.setOwnedString(make_not_null(s));
return err; return err;
} }
@ -234,11 +244,13 @@ class MsgPackDeserializer {
StringBuilder builder = _stringStorage.startString(); StringBuilder builder = _stringStorage.startString();
for (; n; --n) { for (; n; --n) {
uint8_t c; uint8_t c;
if (!readBytes(c)) return DeserializationError::IncompleteInput; if (!readBytes(c))
return DeserializationError::IncompleteInput;
builder.append(static_cast<char>(c)); builder.append(static_cast<char>(c));
} }
result = builder.complete(); result = builder.complete();
if (!result) return DeserializationError::NoMemory; if (!result)
return DeserializationError::NoMemory;
return DeserializationError::Ok; return DeserializationError::Ok;
} }
@ -246,20 +258,24 @@ class MsgPackDeserializer {
DeserializationError readArray(CollectionData &array, DeserializationError readArray(CollectionData &array,
NestingLimit nestingLimit) { NestingLimit nestingLimit) {
TSize size; TSize size;
if (!readInteger(size)) return DeserializationError::IncompleteInput; if (!readInteger(size))
return DeserializationError::IncompleteInput;
return readArray(array, size, nestingLimit); return readArray(array, size, nestingLimit);
} }
DeserializationError readArray(CollectionData &array, size_t n, DeserializationError readArray(CollectionData &array, size_t n,
NestingLimit nestingLimit) { NestingLimit nestingLimit) {
if (nestingLimit.reached()) return DeserializationError::TooDeep; if (nestingLimit.reached())
return DeserializationError::TooDeep;
for (; n; --n) { for (; n; --n) {
VariantData *value = array.add(_pool); VariantData *value = array.add(_pool);
if (!value) return DeserializationError::NoMemory; if (!value)
return DeserializationError::NoMemory;
DeserializationError err = parse(*value, nestingLimit.decrement()); DeserializationError err = parse(*value, nestingLimit.decrement());
if (err) return err; if (err)
return err;
} }
return DeserializationError::Ok; return DeserializationError::Ok;
@ -269,25 +285,30 @@ class MsgPackDeserializer {
DeserializationError readObject(CollectionData &object, DeserializationError readObject(CollectionData &object,
NestingLimit nestingLimit) { NestingLimit nestingLimit) {
TSize size; TSize size;
if (!readInteger(size)) return DeserializationError::IncompleteInput; if (!readInteger(size))
return DeserializationError::IncompleteInput;
return readObject(object, size, nestingLimit); return readObject(object, size, nestingLimit);
} }
DeserializationError readObject(CollectionData &object, size_t n, DeserializationError readObject(CollectionData &object, size_t n,
NestingLimit nestingLimit) { NestingLimit nestingLimit) {
if (nestingLimit.reached()) return DeserializationError::TooDeep; if (nestingLimit.reached())
return DeserializationError::TooDeep;
for (; n; --n) { for (; n; --n) {
VariantSlot *slot = object.addSlot(_pool); VariantSlot *slot = object.addSlot(_pool);
if (!slot) return DeserializationError::NoMemory; if (!slot)
return DeserializationError::NoMemory;
const char *key; const char *key;
DeserializationError err = parseKey(key); DeserializationError err = parseKey(key);
if (err) return err; if (err)
return err;
slot->setOwnedKey(make_not_null(key)); slot->setOwnedKey(make_not_null(key));
err = parse(*slot->data(), nestingLimit.decrement()); err = parse(*slot->data(), nestingLimit.decrement());
if (err) return err; if (err)
return err;
} }
return DeserializationError::Ok; return DeserializationError::Ok;
@ -295,9 +316,11 @@ class MsgPackDeserializer {
DeserializationError parseKey(const char *&key) { DeserializationError parseKey(const char *&key) {
uint8_t code; uint8_t code;
if (!readByte(code)) return DeserializationError::IncompleteInput; if (!readByte(code))
return DeserializationError::IncompleteInput;
if ((code & 0xe0) == 0xa0) return readString(key, code & 0x1f); if ((code & 0xe0) == 0xa0)
return readString(key, code & 0x1f);
switch (code) { switch (code) {
case 0xd9: case 0xd9:

View File

@ -70,7 +70,8 @@ class MsgPackSerializer {
} }
void visitString(const char* value) { void visitString(const char* value) {
if (!value) return writeByte(0xC0); // nil if (!value)
return writeByte(0xC0); // nil
size_t n = strlen(value); size_t n = strlen(value);

View File

@ -30,13 +30,15 @@ struct FloatTraits<T, 8 /*64bits*/> {
static T make_float(T m, TExponent e) { static T make_float(T m, TExponent e) {
if (e > 0) { if (e > 0) {
for (uint8_t index = 0; e != 0; index++) { for (uint8_t index = 0; e != 0; index++) {
if (e & 1) m *= positiveBinaryPowerOfTen(index); if (e & 1)
m *= positiveBinaryPowerOfTen(index);
e >>= 1; e >>= 1;
} }
} else { } else {
e = TExponent(-e); e = TExponent(-e);
for (uint8_t index = 0; e != 0; index++) { for (uint8_t index = 0; e != 0; index++) {
if (e & 1) m *= negativeBinaryPowerOfTen(index); if (e & 1)
m *= negativeBinaryPowerOfTen(index);
e >>= 1; e >>= 1;
} }
} }
@ -126,13 +128,15 @@ struct FloatTraits<T, 4 /*32bits*/> {
static T make_float(T m, TExponent e) { static T make_float(T m, TExponent e) {
if (e > 0) { if (e > 0) {
for (uint8_t index = 0; e != 0; index++) { for (uint8_t index = 0; e != 0; index++) {
if (e & 1) m *= positiveBinaryPowerOfTen(index); if (e & 1)
m *= positiveBinaryPowerOfTen(index);
e >>= 1; e >>= 1;
} }
} else { } else {
e = -e; e = -e;
for (uint8_t index = 0; e != 0; index++) { for (uint8_t index = 0; e != 0; index++) {
if (e & 1) m *= negativeBinaryPowerOfTen(index); if (e & 1)
m *= negativeBinaryPowerOfTen(index);
e >>= 1; e >>= 1;
} }
} }

View File

@ -73,7 +73,8 @@ inline ParsedNumber<TFloat, TUInt> parseNumber(const char *s) {
} }
#if ARDUINOJSON_ENABLE_NAN #if ARDUINOJSON_ENABLE_NAN
if (*s == 'n' || *s == 'N') return traits::nan(); if (*s == 'n' || *s == 'N')
return traits::nan();
#endif #endif
#if ARDUINOJSON_ENABLE_INFINITY #if ARDUINOJSON_ENABLE_INFINITY
@ -81,7 +82,8 @@ inline ParsedNumber<TFloat, TUInt> parseNumber(const char *s) {
return is_negative ? -traits::inf() : traits::inf(); return is_negative ? -traits::inf() : traits::inf();
#endif #endif
if (!isdigit(*s) && *s != '.') return return_type(); if (!isdigit(*s) && *s != '.')
return return_type();
mantissa_t mantissa = 0; mantissa_t mantissa = 0;
exponent_t exponent_offset = 0; exponent_t exponent_offset = 0;
@ -89,14 +91,17 @@ inline ParsedNumber<TFloat, TUInt> parseNumber(const char *s) {
while (isdigit(*s)) { while (isdigit(*s)) {
uint8_t digit = uint8_t(*s - '0'); uint8_t digit = uint8_t(*s - '0');
if (mantissa > maxUint / 10) break; if (mantissa > maxUint / 10)
break;
mantissa *= 10; mantissa *= 10;
if (mantissa > maxUint - digit) break; if (mantissa > maxUint - digit)
break;
mantissa += digit; mantissa += digit;
s++; s++;
} }
if (*s == '\0') return return_type(TUInt(mantissa), is_negative); if (*s == '\0')
return return_type(TUInt(mantissa), is_negative);
// avoid mantissa overflow // avoid mantissa overflow
while (mantissa > traits::mantissa_max) { while (mantissa > traits::mantissa_max) {
@ -142,12 +147,14 @@ inline ParsedNumber<TFloat, TUInt> parseNumber(const char *s) {
} }
s++; s++;
} }
if (negative_exponent) exponent = -exponent; if (negative_exponent)
exponent = -exponent;
} }
exponent += exponent_offset; exponent += exponent_offset;
// we should be at the end of the string, otherwise it's an error // we should be at the end of the string, otherwise it's an error
if (*s != '\0') return return_type(); if (*s != '\0')
return return_type();
TFloat result = traits::make_float(static_cast<TFloat>(mantissa), exponent); TFloat result = traits::make_float(static_cast<TFloat>(mantissa), exponent);

View File

@ -17,34 +17,41 @@ void objectAccept(const CollectionData *obj, Visitor &visitor) {
} }
inline bool objectEquals(const CollectionData *lhs, const CollectionData *rhs) { inline bool objectEquals(const CollectionData *lhs, const CollectionData *rhs) {
if (lhs == rhs) return true; if (lhs == rhs)
if (!lhs || !rhs) return false; return true;
if (!lhs || !rhs)
return false;
return lhs->equalsObject(*rhs); return lhs->equalsObject(*rhs);
} }
template <typename TAdaptedString> template <typename TAdaptedString>
inline VariantData *objectGet(const CollectionData *obj, TAdaptedString key) { inline VariantData *objectGet(const CollectionData *obj, TAdaptedString key) {
if (!obj) return 0; if (!obj)
return 0;
return obj->get(key); return obj->get(key);
} }
template <typename TAdaptedString> template <typename TAdaptedString>
void objectRemove(CollectionData *obj, TAdaptedString key) { void objectRemove(CollectionData *obj, TAdaptedString key) {
if (!obj) return; if (!obj)
return;
obj->remove(key); obj->remove(key);
} }
template <typename TAdaptedString> template <typename TAdaptedString>
inline VariantData *objectGetOrCreate(CollectionData *obj, TAdaptedString key, inline VariantData *objectGetOrCreate(CollectionData *obj, TAdaptedString key,
MemoryPool *pool) { MemoryPool *pool) {
if (!obj) return 0; if (!obj)
return 0;
// ignore null key // ignore null key
if (key.isNull()) return 0; if (key.isNull())
return 0;
// search a matching key // search a matching key
VariantData *var = obj->get(key); VariantData *var = obj->get(key);
if (var) return var; if (var)
return var;
return obj->add(key, pool); return obj->add(key, pool);
} }

View File

@ -64,7 +64,8 @@ class ObjectConstRef : public ObjectRefBase<const CollectionData>,
ObjectConstRef(const CollectionData* data) : base_type(data) {} ObjectConstRef(const CollectionData* data) : base_type(data) {}
FORCE_INLINE iterator begin() const { FORCE_INLINE iterator begin() const {
if (!_data) return iterator(); if (!_data)
return iterator();
return iterator(_data->head()); return iterator(_data->head());
} }
@ -154,7 +155,8 @@ class ObjectRef : public ObjectRefBase<CollectionData>,
} }
FORCE_INLINE iterator begin() const { FORCE_INLINE iterator begin() const {
if (!_data) return iterator(); if (!_data)
return iterator();
return iterator(_pool, _data->head()); return iterator(_pool, _data->head());
} }
@ -163,12 +165,14 @@ class ObjectRef : public ObjectRefBase<CollectionData>,
} }
void clear() const { void clear() const {
if (!_data) return; if (!_data)
return;
_data->clear(); _data->clear();
} }
FORCE_INLINE bool set(ObjectConstRef src) { FORCE_INLINE bool set(ObjectConstRef src) {
if (!_data || !src._data) return false; if (!_data || !src._data)
return false;
return _data->copyFrom(*src._data, _pool); return _data->copyFrom(*src._data, _pool);
} }
@ -207,7 +211,8 @@ class ObjectRef : public ObjectRefBase<CollectionData>,
} }
FORCE_INLINE void remove(iterator it) const { FORCE_INLINE void remove(iterator it) const {
if (!_data) return; if (!_data)
return;
_data->remove(it.internal()); _data->remove(it.internal());
} }

View File

@ -30,9 +30,12 @@ inline int strncmp_P(const char* a, ARDUINOJSON_NAMESPACE::pgm_p b, size_t n) {
while (n-- > 0) { while (n-- > 0) {
char c1 = *s1++; char c1 = *s1++;
char c2 = static_cast<char>(pgm_read_byte(s2++)); char c2 = static_cast<char>(pgm_read_byte(s2++));
if (c1 < c2) return -1; if (c1 < c2)
if (c1 > c2) return 1; return -1;
if (c1 == 0 /* and c2 as well */) return 0; if (c1 > c2)
return 1;
if (c1 == 0 /* and c2 as well */)
return 0;
} }
return 0; return 0;
} }
@ -45,9 +48,12 @@ inline int strcmp_P(const char* a, ARDUINOJSON_NAMESPACE::pgm_p b) {
for (;;) { for (;;) {
char c1 = *s1++; char c1 = *s1++;
char c2 = static_cast<char>(pgm_read_byte(s2++)); char c2 = static_cast<char>(pgm_read_byte(s2++));
if (c1 < c2) return -1; if (c1 < c2)
if (c1 > c2) return 1; return -1;
if (c1 == 0 /* and c2 as well */) return 0; if (c1 > c2)
return 1;
if (c1 == 0 /* and c2 as well */)
return 0;
} }
} }
#endif #endif

View File

@ -9,16 +9,22 @@
namespace ARDUINOJSON_NAMESPACE { namespace ARDUINOJSON_NAMESPACE {
inline int8_t safe_strcmp(const char* a, const char* b) { inline int8_t safe_strcmp(const char* a, const char* b) {
if (a == b) return 0; if (a == b)
if (!a) return -1; return 0;
if (!b) return 1; if (!a)
return -1;
if (!b)
return 1;
return static_cast<int8_t>(strcmp(a, b)); return static_cast<int8_t>(strcmp(a, b));
} }
inline int8_t safe_strncmp(const char* a, const char* b, size_t n) { inline int8_t safe_strncmp(const char* a, const char* b, size_t n) {
if (a == b) return 0; if (a == b)
if (!a) return -1; return 0;
if (!b) return 1; if (!a)
return -1;
if (!b)
return 1;
return static_cast<int8_t>(strncmp(a, b, n)); return static_cast<int8_t>(strncmp(a, b, n));
} }
} // namespace ARDUINOJSON_NAMESPACE } // namespace ARDUINOJSON_NAMESPACE

View File

@ -24,7 +24,8 @@ class Writer< ::String, void> {
size_t write(uint8_t c) { size_t write(uint8_t c) {
ARDUINOJSON_ASSERT(_size < bufferCapacity); ARDUINOJSON_ASSERT(_size < bufferCapacity);
_buffer[_size++] = static_cast<char>(c); _buffer[_size++] = static_cast<char>(c);
if (_size + 1 >= bufferCapacity) flush(); if (_size + 1 >= bufferCapacity)
flush();
return 1; return 1;
} }

View File

@ -16,7 +16,8 @@ class StaticStringWriter {
} }
size_t write(uint8_t c) { size_t write(uint8_t c) {
if (p >= end) return 0; if (p >= end)
return 0;
*p++ = static_cast<char>(c); *p++ = static_cast<char>(c);
*p = '\0'; *p = '\0';
return 1; return 1;

View File

@ -15,10 +15,12 @@ class ArduinoStringAdapter {
ArduinoStringAdapter(const ::String& str) : _str(&str) {} ArduinoStringAdapter(const ::String& str) : _str(&str) {}
char* save(MemoryPool* pool) const { char* save(MemoryPool* pool) const {
if (isNull()) return NULL; if (isNull())
return NULL;
size_t n = _str->length() + 1; size_t n = _str->length() + 1;
char* dup = pool->allocFrozenString(n); char* dup = pool->allocFrozenString(n);
if (dup) memcpy(dup, _str->c_str(), n); if (dup)
memcpy(dup, _str->c_str(), n);
return dup; return dup;
} }

View File

@ -33,7 +33,8 @@ class ConstRamStringAdapter {
} }
size_t size() const { size_t size() const {
if (!_str) return 0; if (!_str)
return 0;
return strlen(_str); return strlen(_str);
} }

View File

@ -13,9 +13,12 @@ class FlashStringAdapter {
FlashStringAdapter(const __FlashStringHelper* str) : _str(str) {} FlashStringAdapter(const __FlashStringHelper* str) : _str(str) {}
int8_t compare(const char* other) const { int8_t compare(const char* other) const {
if (!other && !_str) return 0; if (!other && !_str)
if (!_str) return -1; return 0;
if (!other) return 1; if (!_str)
return -1;
if (!other)
return 1;
return int8_t(-strcmp_P(other, reinterpret_cast<const char*>(_str))); return int8_t(-strcmp_P(other, reinterpret_cast<const char*>(_str)));
} }
@ -28,10 +31,12 @@ class FlashStringAdapter {
} }
char* save(MemoryPool* pool) const { char* save(MemoryPool* pool) const {
if (!_str) return NULL; if (!_str)
return NULL;
size_t n = size() + 1; // copy the terminator size_t n = size() + 1; // copy the terminator
char* dup = pool->allocFrozenString(n); char* dup = pool->allocFrozenString(n);
if (dup) memcpy_P(dup, reinterpret_cast<const char*>(_str), n); if (dup)
memcpy_P(dup, reinterpret_cast<const char*>(_str), n);
return dup; return dup;
} }
@ -40,7 +45,8 @@ class FlashStringAdapter {
} }
size_t size() const { size_t size() const {
if (!_str) return 0; if (!_str)
return 0;
return strlen_P(reinterpret_cast<const char*>(_str)); return strlen_P(reinterpret_cast<const char*>(_str));
} }

View File

@ -13,10 +13,12 @@ class RamStringAdapter : public ConstRamStringAdapter {
RamStringAdapter(const char* str) : ConstRamStringAdapter(str) {} RamStringAdapter(const char* str) : ConstRamStringAdapter(str) {}
char* save(MemoryPool* pool) const { char* save(MemoryPool* pool) const {
if (!_str) return NULL; if (!_str)
return NULL;
size_t n = size() + 1; size_t n = size() + 1;
char* dup = pool->allocFrozenString(n); char* dup = pool->allocFrozenString(n);
if (dup) memcpy(dup, _str, n); if (dup)
memcpy(dup, _str, n);
return dup; return dup;
} }

View File

@ -14,9 +14,12 @@ class SizedFlashStringAdapter {
: _str(str), _size(sz) {} : _str(str), _size(sz) {}
int8_t compare(const char* other) const { int8_t compare(const char* other) const {
if (!other && !_str) return 0; if (!other && !_str)
if (!_str) return -1; return 0;
if (!other) return 1; if (!_str)
return -1;
if (!other)
return 1;
return int8_t( return int8_t(
-strncmp_P(other, reinterpret_cast<const char*>(_str), _size)); -strncmp_P(other, reinterpret_cast<const char*>(_str), _size));
} }
@ -30,9 +33,11 @@ class SizedFlashStringAdapter {
} }
char* save(MemoryPool* pool) const { char* save(MemoryPool* pool) const {
if (!_str) return NULL; if (!_str)
return NULL;
char* dup = pool->allocFrozenString(_size); char* dup = pool->allocFrozenString(_size);
if (dup) memcpy_P(dup, reinterpret_cast<const char*>(_str), _size); if (dup)
memcpy_P(dup, reinterpret_cast<const char*>(_str), _size);
return dup; return dup;
} }

View File

@ -27,9 +27,11 @@ class SizedRamStringAdapter {
} }
char* save(MemoryPool* pool) const { char* save(MemoryPool* pool) const {
if (!_str) return NULL; if (!_str)
return NULL;
char* dup = pool->allocFrozenString(_size); char* dup = pool->allocFrozenString(_size);
if (dup) memcpy(dup, _str, _size); if (dup)
memcpy(dup, _str, _size);
return dup; return dup;
} }

View File

@ -18,7 +18,8 @@ class StlStringAdapter {
char* save(MemoryPool* pool) const { char* save(MemoryPool* pool) const {
size_t n = _str->length() + 1; size_t n = _str->length() + 1;
char* dup = pool->allocFrozenString(n); char* dup = pool->allocFrozenString(n);
if (dup) memcpy(dup, _str->c_str(), n); if (dup)
memcpy(dup, _str->c_str(), n);
return dup; return dup;
} }
@ -27,12 +28,14 @@ class StlStringAdapter {
} }
int8_t compare(const char* other) const { int8_t compare(const char* other) const {
if (!other) return 1; if (!other)
return 1;
return static_cast<int8_t>(_str->compare(other)); return static_cast<int8_t>(_str->compare(other));
} }
bool equals(const char* expected) const { bool equals(const char* expected) const {
if (!expected) return false; if (!expected)
return false;
return *_str == expected; return *_str == expected;
} }

View File

@ -27,9 +27,12 @@ class String {
} }
friend bool operator==(String lhs, String rhs) { friend bool operator==(String lhs, String rhs) {
if (lhs._data == rhs._data) return true; if (lhs._data == rhs._data)
if (!lhs._data) return false; return true;
if (!rhs._data) return false; if (!lhs._data)
return false;
if (!rhs._data)
return false;
return strcmp(lhs._data, rhs._data) == 0; return strcmp(lhs._data, rhs._data) == 0;
} }

View File

@ -11,12 +11,14 @@ namespace ARDUINOJSON_NAMESPACE {
template <typename TAdaptedString> template <typename TAdaptedString>
inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool) { inline bool slotSetKey(VariantSlot* var, TAdaptedString key, MemoryPool* pool) {
if (!var) return false; if (!var)
return false;
if (key.isStatic()) { if (key.isStatic()) {
var->setLinkedKey(make_not_null(key.data())); var->setLinkedKey(make_not_null(key.data()));
} else { } else {
const char* dup = key.save(pool); const char* dup = key.save(pool);
if (!dup) return false; if (!dup)
return false;
var->setOwnedKey(make_not_null(dup)); var->setOwnedKey(make_not_null(dup));
} }
return true; return true;

View File

@ -32,7 +32,8 @@ template <typename T>
inline typename enable_if<IsWriteableString<T>::value, T>::type variantAs( inline typename enable_if<IsWriteableString<T>::value, T>::type variantAs(
const VariantData* _data) { const VariantData* _data) {
const char* cstr = _data != 0 ? _data->asString() : 0; const char* cstr = _data != 0 ? _data->asString() : 0;
if (cstr) return T(cstr); if (cstr)
return T(cstr);
T s; T s;
serializeJson(VariantConstRef(_data), s); serializeJson(VariantConstRef(_data), s);
return s; return s;

View File

@ -185,12 +185,14 @@ class VariantData {
} }
void remove(size_t index) { void remove(size_t index) {
if (isArray()) _content.asCollection.remove(index); if (isArray())
_content.asCollection.remove(index);
} }
template <typename TAdaptedString> template <typename TAdaptedString>
void remove(TAdaptedString key) { void remove(TAdaptedString key) {
if (isObject()) _content.asCollection.remove(key); if (isObject())
_content.asCollection.remove(key);
} }
void setBoolean(bool value) { void setBoolean(bool value) {
@ -329,8 +331,10 @@ class VariantData {
} }
VariantData *addElement(MemoryPool *pool) { VariantData *addElement(MemoryPool *pool) {
if (isNull()) toArray(); if (isNull())
if (!isArray()) return 0; toArray();
if (!isArray())
return 0;
return _content.asCollection.add(pool); return _content.asCollection.add(pool);
} }
@ -345,15 +349,19 @@ class VariantData {
template <typename TAdaptedString> template <typename TAdaptedString>
VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool) { VariantData *getOrAddMember(TAdaptedString key, MemoryPool *pool) {
if (isNull()) toObject(); if (isNull())
if (!isObject()) return 0; toObject();
if (!isObject())
return 0;
VariantData *var = _content.asCollection.get(key); VariantData *var = _content.asCollection.get(key);
if (var) return var; if (var)
return var;
return _content.asCollection.add(key, pool); return _content.asCollection.add(key, pool);
} }
void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) { void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) {
if (_flags & VALUE_IS_OWNED) _content.asString += stringDistance; if (_flags & VALUE_IS_OWNED)
_content.asString += stringDistance;
if (_flags & COLLECTION_MASK) if (_flags & COLLECTION_MASK)
_content.asCollection.movePointers(stringDistance, variantDistance); _content.asCollection.movePointers(stringDistance, variantDistance);
} }

View File

@ -30,7 +30,8 @@ inline CollectionData *variantAsObject(VariantData *var) {
inline bool variantCopyFrom(VariantData *dst, const VariantData *src, inline bool variantCopyFrom(VariantData *dst, const VariantData *src,
MemoryPool *pool) { MemoryPool *pool) {
if (!dst) return false; if (!dst)
return false;
if (!src) { if (!src) {
dst->setNull(); dst->setNull();
return true; return true;
@ -39,8 +40,10 @@ inline bool variantCopyFrom(VariantData *dst, const VariantData *src,
} }
inline bool variantEquals(const VariantData *a, const VariantData *b) { inline bool variantEquals(const VariantData *a, const VariantData *b) {
if (a == b) return true; if (a == b)
if (!a || !b) return false; return true;
if (!a || !b)
return false;
return a->equals(*b); return a->equals(*b);
} }
@ -74,20 +77,23 @@ inline bool variantIsNull(const VariantData *var) {
} }
inline bool variantSetBoolean(VariantData *var, bool value) { inline bool variantSetBoolean(VariantData *var, bool value) {
if (!var) return false; if (!var)
return false;
var->setBoolean(value); var->setBoolean(value);
return true; return true;
} }
inline bool variantSetFloat(VariantData *var, Float value) { inline bool variantSetFloat(VariantData *var, Float value) {
if (!var) return false; if (!var)
return false;
var->setFloat(value); var->setFloat(value);
return true; return true;
} }
inline bool variantSetLinkedRaw(VariantData *var, inline bool variantSetLinkedRaw(VariantData *var,
SerializedValue<const char *> value) { SerializedValue<const char *> value) {
if (!var) return false; if (!var)
return false;
var->setLinkedRaw(value); var->setLinkedRaw(value);
return true; return true;
} }
@ -100,24 +106,28 @@ inline bool variantSetOwnedRaw(VariantData *var, SerializedValue<T> value,
template <typename T> template <typename T>
inline bool variantSetSignedInteger(VariantData *var, T value) { inline bool variantSetSignedInteger(VariantData *var, T value) {
if (!var) return false; if (!var)
return false;
var->setSignedInteger(value); var->setSignedInteger(value);
return true; return true;
} }
inline bool variantSetLinkedString(VariantData *var, const char *value) { inline bool variantSetLinkedString(VariantData *var, const char *value) {
if (!var) return false; if (!var)
return false;
var->setLinkedString(value); var->setLinkedString(value);
return true; return true;
} }
inline void variantSetNull(VariantData *var) { inline void variantSetNull(VariantData *var) {
if (!var) return; if (!var)
return;
var->setNull(); var->setNull();
} }
inline bool variantSetOwnedString(VariantData *var, char *value) { inline bool variantSetOwnedString(VariantData *var, char *value) {
if (!var) return false; if (!var)
return false;
var->setOwnedString(value); var->setOwnedString(value);
return true; return true;
} }
@ -128,7 +138,8 @@ inline bool variantSetOwnedString(VariantData *var, T value, MemoryPool *pool) {
} }
inline bool variantSetUnsignedInteger(VariantData *var, UInt value) { inline bool variantSetUnsignedInteger(VariantData *var, UInt value) {
if (!var) return false; if (!var)
return false;
var->setUnsignedInteger(value); var->setUnsignedInteger(value);
return true; return true;
} }
@ -138,12 +149,14 @@ inline size_t variantSize(const VariantData *var) {
} }
inline CollectionData *variantToArray(VariantData *var) { inline CollectionData *variantToArray(VariantData *var) {
if (!var) return 0; if (!var)
return 0;
return &var->toArray(); return &var->toArray();
} }
inline CollectionData *variantToObject(VariantData *var) { inline CollectionData *variantToObject(VariantData *var) {
if (!var) return 0; if (!var)
return 0;
return &var->toObject(); return &var->toObject();
} }

View File

@ -324,7 +324,8 @@ class VariantRef : public VariantRefBase<VariantData>,
FORCE_INLINE VariantRef getOrAddMember(const TString &) const; FORCE_INLINE VariantRef getOrAddMember(const TString &) const;
FORCE_INLINE void remove(size_t index) const { FORCE_INLINE void remove(size_t index) const {
if (_data) _data->remove(index); if (_data)
_data->remove(index);
} }
// remove(char*) const // remove(char*) const
// remove(const char*) const // remove(const char*) const
@ -332,14 +333,16 @@ class VariantRef : public VariantRefBase<VariantData>,
template <typename TChar> template <typename TChar>
FORCE_INLINE typename enable_if<IsString<TChar *>::value>::type remove( FORCE_INLINE typename enable_if<IsString<TChar *>::value>::type remove(
TChar *key) const { TChar *key) const {
if (_data) _data->remove(adaptString(key)); if (_data)
_data->remove(adaptString(key));
} }
// remove(const std::string&) const // remove(const std::string&) const
// remove(const String&) const // remove(const String&) const
template <typename TString> template <typename TString>
FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove( FORCE_INLINE typename enable_if<IsString<TString>::value>::type remove(
const TString &key) const { const TString &key) const {
if (_data) _data->remove(adaptString(key)); if (_data)
_data->remove(adaptString(key));
} }
private: private:

View File

@ -49,7 +49,8 @@ class VariantSlot {
VariantSlot* next(size_t distance) { VariantSlot* next(size_t distance) {
VariantSlot* slot = this; VariantSlot* slot = this;
while (distance--) { while (distance--) {
if (!slot->_next) return 0; if (!slot->_next)
return 0;
slot += slot->_next; slot += slot->_next;
} }
return slot; return slot;
@ -93,8 +94,10 @@ class VariantSlot {
} }
void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) { void movePointers(ptrdiff_t stringDistance, ptrdiff_t variantDistance) {
if (_flags & KEY_IS_OWNED) _key += stringDistance; if (_flags & KEY_IS_OWNED)
if (_flags & VALUE_IS_OWNED) _content.asString += stringDistance; _key += stringDistance;
if (_flags & VALUE_IS_OWNED)
_content.asString += stringDistance;
if (_flags & COLLECTION_MASK) if (_flags & COLLECTION_MASK)
_content.asCollection.movePointers(stringDistance, variantDistance); _content.asCollection.movePointers(stringDistance, variantDistance);
} }