Skip to content

Commit

Permalink
Removed the indirection via StringSlot
Browse files Browse the repository at this point in the history
  • Loading branch information
bblanchon committed Nov 27, 2018
1 parent 929beb1 commit 3b07809
Show file tree
Hide file tree
Showing 23 changed files with 104 additions and 163 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ project(ArduinoJson)

enable_testing()

add_definitions(-DARDUINOJSON_DEBUG)
if(CMAKE_CXX_COMPILER_ID MATCHES "(GNU|Clang)")
add_definitions(-DARDUINOJSON_DEBUG)
add_compile_options(-g -O0)
endif()

Expand Down
2 changes: 2 additions & 0 deletions scripts/code-size/arduino_avr_uno.csv
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
Version,Date,JsonParserExample,JsonGeneratorExample
v6.6.0-beta-6-g8217012,2018-11-27,7204,7630
v6.6.0-beta-5-g13cc610,2018-11-27,7264,7850
v6.6.0-beta-2-g2bd280d,2018-11-16,7872,8446
v6.6.0-beta,2018-11-13,8380,8916
v6.5.0-beta,2018-10-13,7384,7874
Expand Down
2 changes: 0 additions & 2 deletions src/ArduinoJson/Data/JsonVariantData.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ union JsonVariantContent {
JsonArrayData asArray;
JsonObjectData asObject;
const char *asString;
struct StringSlot *asOwnedString;
struct StringSlot *asOwnedRaw;
struct {
const char *data;
size_t size;
Expand Down
4 changes: 2 additions & 2 deletions src/ArduinoJson/Data/ObjectFunctions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ inline bool objectCopy(JsonObjectData* dst, const JsonObjectData* src,
for (VariantSlot* s = src->head; s; s = s->next) {
JsonVariantData* var;
if (s->value.keyIsOwned)
var = objectAdd(dst, ZeroTerminatedRamString(s->ownedKey->value), pool);
var = objectAdd(dst, ZeroTerminatedRamString(s->key), pool);
else
var = objectAdd(dst, ZeroTerminatedRamStringConst(s->linkedKey), pool);
var = objectAdd(dst, ZeroTerminatedRamStringConst(s->key), pool);
if (!variantCopy(var, &s->value, pool)) return false;
}
return true;
Expand Down
12 changes: 6 additions & 6 deletions src/ArduinoJson/Data/SlotFunctions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,28 +13,28 @@ namespace ARDUINOJSON_NAMESPACE {

template <typename TKey>
inline bool slotSetKey(VariantSlot* var, TKey key, MemoryPool* pool) {
StringSlot* slot = key.save(pool);
if (!slot) return false;
var->ownedKey = slot;
char* dup = key.save(pool);
if (!dup) return false;
var->key = dup;
var->value.keyIsOwned = true;
return true;
}

inline bool slotSetKey(VariantSlot* var, ZeroTerminatedRamStringConst key,
MemoryPool*) {
var->linkedKey = key.c_str();
var->key = key.c_str();
var->value.keyIsOwned = false;
return true;
}

inline bool slotSetKey(VariantSlot* var, StringInMemoryPool key, MemoryPool*) {
var->ownedKey = key.slot();
var->key = key.c_str();
var->value.keyIsOwned = true;
return true;
}

inline const char* slotGetKey(const VariantSlot* var) {
return var->value.keyIsOwned ? var->ownedKey->value : var->linkedKey;
return var->key;
}

inline const VariantSlot* slotAdvance(const VariantSlot* var, size_t distance) {
Expand Down
46 changes: 21 additions & 25 deletions src/ArduinoJson/Data/VariantFunctions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ inline T variantAsIntegral(const JsonVariantData* var) {
case JSON_NEGATIVE_INTEGER:
return T(~var->content.asInteger + 1);
case JSON_LINKED_STRING:
return parseInteger<T>(var->content.asString);
case JSON_OWNED_STRING:
return parseInteger<T>(var->content.asOwnedString->value);
return parseInteger<T>(var->content.asString);
case JSON_FLOAT:
return T(var->content.asFloat);
default:
Expand All @@ -47,9 +46,8 @@ inline T variantAsFloat(const JsonVariantData* var) {
case JSON_NEGATIVE_INTEGER:
return -static_cast<T>(var->content.asInteger);
case JSON_LINKED_STRING:
return parseFloat<T>(var->content.asString);
case JSON_OWNED_STRING:
return parseFloat<T>(var->content.asOwnedString->value);
return parseFloat<T>(var->content.asString);
case JSON_FLOAT:
return static_cast<T>(var->content.asFloat);
default:
Expand All @@ -61,9 +59,8 @@ inline const char* variantAsString(const JsonVariantData* var) {
if (!var) return 0;
switch (var->type) {
case JSON_LINKED_STRING:
return var->content.asString;
case JSON_OWNED_STRING:
return var->content.asOwnedString->value;
return var->content.asString;
default:
return 0;
}
Expand Down Expand Up @@ -144,10 +141,11 @@ template <typename T>
inline bool variantSetOwnedRaw(JsonVariantData* var, SerializedValue<T> value,
MemoryPool* pool) {
if (!var) return false;
StringSlot* slot = makeString(value.data(), value.size()).save(pool);
if (slot) {
char* dup = makeString(value.data(), value.size()).save(pool);
if (dup) {
var->type = JSON_OWNED_RAW;
var->content.asOwnedRaw = slot;
var->content.asRaw.data = dup;
var->content.asRaw.size = value.size();
return true;
} else {
var->type = JSON_NULL;
Expand All @@ -158,21 +156,21 @@ inline bool variantSetOwnedRaw(JsonVariantData* var, SerializedValue<T> value,
template <typename T>
inline bool variantSetString(JsonVariantData* var, T value, MemoryPool* pool) {
if (!var) return false;
StringSlot* slot = value.save(pool);
if (slot) {
char* dup = value.save(pool);
if (dup) {
var->type = JSON_OWNED_STRING;
var->content.asOwnedString = slot;
var->content.asString = dup;
return true;
} else {
var->type = JSON_NULL;
return false;
}
}

inline bool variantSetOwnedString(JsonVariantData* var, StringSlot* slot) {
inline bool variantSetOwnedString(JsonVariantData* var, char* s) {
if (!var) return false;
var->type = JSON_OWNED_STRING;
var->content.asOwnedString = slot;
var->content.asString = s;
return true;
}

Expand Down Expand Up @@ -218,12 +216,11 @@ inline bool variantCopy(JsonVariantData* dst, const JsonVariantData* src,
return objectCopy(variantToObject(dst), &src->content.asObject, pool);
case JSON_OWNED_STRING:
return variantSetString(
dst, makeString(src->content.asOwnedString->value), pool);
dst, ZeroTerminatedRamString(src->content.asString), pool);
case JSON_OWNED_RAW:
return variantSetOwnedRaw(dst,
serialized(src->content.asOwnedRaw->value,
src->content.asOwnedRaw->size),
pool);
return variantSetOwnedRaw(
dst, serialized(src->content.asRaw.data, src->content.asRaw.size),
pool);
default:
// caution: don't override keyIsOwned
dst->type = src->type;
Expand Down Expand Up @@ -266,16 +263,15 @@ inline bool variantEquals(const JsonVariantData* a, const JsonVariantData* b) {
if (a->type != b->type) return false;

switch (a->type) {
case JSON_LINKED_RAW:
case JSON_LINKED_STRING:
case JSON_OWNED_STRING:
return !strcmp(a->content.asString, b->content.asString);

case JSON_LINKED_RAW:
case JSON_OWNED_RAW:
case JSON_OWNED_STRING:
return a->content.asOwnedString->size == b->content.asOwnedString->size &&
!memcmp(a->content.asOwnedString->value,
b->content.asOwnedString->value,
a->content.asOwnedString->size);
return a->content.asRaw.size == b->content.asRaw.size &&
!memcmp(a->content.asRaw.data, b->content.asRaw.data,
a->content.asRaw.size);

case JSON_BOOLEAN:
case JSON_POSITIVE_INTEGER:
Expand Down
2 changes: 1 addition & 1 deletion src/ArduinoJson/JsonKey.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class JsonKey {
}

bool isNull() const {
return _slot == 0 || _slot->linkedKey == 0;
return _slot == 0 || _slot->key == 0;
}

friend bool operator==(JsonKey lhs, const char* rhs) {
Expand Down
3 changes: 2 additions & 1 deletion src/ArduinoJson/JsonVariant.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,8 @@ class JsonVariant : public JsonVariantProxy<JsonVariantData>,

// for internal use only
FORCE_INLINE bool set(StringInMemoryPool value) const {
return variantSetOwnedString(_data, value.slot());
return variantSetOwnedString(_data,
value.save(_memoryPool)); // TODO: remove?
}
FORCE_INLINE bool set(ZeroTerminatedRamStringConst value) const {
return variantSetString(_data, value.c_str());
Expand Down
7 changes: 1 addition & 6 deletions src/ArduinoJson/JsonVariantImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,10 @@ inline void JsonVariantConst::accept(Visitor& visitor) const {
return visitor.visitObject(JsonObjectConst(&_data->content.asObject));

case JSON_LINKED_STRING:
return visitor.visitString(_data->content.asString);

case JSON_OWNED_STRING:
return visitor.visitString(_data->content.asOwnedString->value);
return visitor.visitString(_data->content.asString);

case JSON_OWNED_RAW:
return visitor.visitRawJson(_data->content.asOwnedRaw->value,
_data->content.asOwnedRaw->size);

case JSON_LINKED_RAW:
return visitor.visitRawJson(_data->content.asRaw.data,
_data->content.asRaw.size);
Expand Down
41 changes: 9 additions & 32 deletions src/ArduinoJson/Memory/MemoryPool.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,6 @@ namespace ARDUINOJSON_NAMESPACE {
// _left _right

class MemoryPool {
class UpdateStringSlotAddress {
public:
UpdateStringSlotAddress(const char* address, size_t offset)
: _address(address), _offset(offset) {}

void operator()(StringSlot* slot) const {
ARDUINOJSON_ASSERT(slot != NULL);
if (slot->value > _address) slot->value -= _offset;
}

private:
const char* _address;
size_t _offset;
};

public:
MemoryPool(char* buf, size_t capa)
: _begin(buf),
Expand Down Expand Up @@ -66,34 +51,26 @@ class MemoryPool {
return allocRight<VariantSlot>();
}

StringSlot* allocFrozenString(size_t n) {
StringSlot* s = allocStringSlot();
if (!s) return 0;
char* allocFrozenString(size_t n) {
if (!canAlloc(n)) return 0;

s->value = _left;
s->size = n;
char* s = _left;
_left += n;
checkInvariants();

return s;
}

StringSlot* allocExpandableString() {
StringSlot* s = allocStringSlot();
if (!s) return 0;

s->value = _left;
s->size = size_t(_right - _left);
StringSlot allocExpandableString() {
StringSlot s;
s.value = _left;
s.size = size_t(_right - _left);
_left = _right;

checkInvariants();
return s;
}

void freezeString(StringSlot* slot, size_t newSize) {
_left -= (slot->size - newSize);
slot->size = newSize;
void freezeString(StringSlot& s, size_t newSize) {
_left -= (s.size - newSize);
s.size = newSize;
checkInvariants();
}

Expand Down
14 changes: 7 additions & 7 deletions src/ArduinoJson/Memory/StringBuilder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,28 +26,28 @@ class StringBuilder {
}

void append(char c) {
if (!_slot) return;
if (!_slot.value) return;

if (_size >= _slot->size) {
_slot = 0;
if (_size >= _slot.size) {
_slot.value = 0;
return;
}

_slot->value[_size++] = c;
_slot.value[_size++] = c;
}

StringType complete() {
append('\0');
if (_slot) {
if (_slot.value) {
_parent->freezeString(_slot, _size);
}
return _slot;
return _slot.value;
}

private:
MemoryPool* _parent;
size_t _size;
StringSlot* _slot;
StringSlot _slot;
};

} // namespace ARDUINOJSON_NAMESPACE
4 changes: 1 addition & 3 deletions src/ArduinoJson/Memory/StringSlot.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,12 @@
#include <stddef.h> // for size_t
#include "../Configuration.hpp"

#define JSON_STRING_SIZE(SIZE) \
(sizeof(ARDUINOJSON_NAMESPACE::StringSlot) + (SIZE))
#define JSON_STRING_SIZE(SIZE) (SIZE)

namespace ARDUINOJSON_NAMESPACE {

struct StringSlot {
char *value;
size_t size;
struct StringSlot *next;
};
} // namespace ARDUINOJSON_NAMESPACE
5 changes: 1 addition & 4 deletions src/ArduinoJson/Memory/VariantSlot.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@ struct VariantSlot {
JsonVariantData value;
struct VariantSlot* next;
struct VariantSlot* prev;
union {
const char* linkedKey;
StringSlot* ownedKey;
};
const char* key;
};

} // namespace ARDUINOJSON_NAMESPACE
9 changes: 4 additions & 5 deletions src/ArduinoJson/Strings/ArduinoString.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,12 @@ class ArduinoString {
public:
ArduinoString(const ::String& str) : _str(&str) {}

template <typename TMemoryPool>
StringSlot* save(TMemoryPool* memoryPool) const {
char* save(MemoryPool* memoryPool) const {
if (isNull()) return NULL;
size_t n = _str->length() + 1;
StringSlot* slot = memoryPool->allocFrozenString(n);
if (slot) memcpy(slot->value, _str->c_str(), n);
return slot;
char* dup = memoryPool->allocFrozenString(n);
if (dup) memcpy(dup, _str->c_str(), n);
return dup;
}

bool isNull() const {
Expand Down
9 changes: 4 additions & 5 deletions src/ArduinoJson/Strings/FixedSizeFlashString.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,11 @@ class FixedSizeFlashString {
return !_str;
}

template <typename TMemoryPool>
StringSlot* save(TMemoryPool* memoryPool) const {
char* save(MemoryPool* memoryPool) const {
if (!_str) return NULL;
StringSlot* slot = memoryPool->allocFrozenString(_size);
if (!slot) memcpy_P(slot->value, (const char*)_str, _size);
return slot;
char* dup = memoryPool->allocFrozenString(_size);
if (!dup) memcpy_P(dup, (const char*)_str, _size);
return dup;
}

size_t size() const {
Expand Down

0 comments on commit 3b07809

Please sign in to comment.