mirror of
https://github.com/bblanchon/ArduinoJson.git
synced 2025-07-17 20:42:24 +02:00
Append terminator in saveStringFromFreeZone()
This commit is contained in:
@ -113,3 +113,21 @@ TEST_CASE("Not enough room to save the key") {
|
|||||||
DeserializationError::NoMemory); // fails in the second string
|
DeserializationError::NoMemory); // fails in the second string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Empty memory pool") {
|
||||||
|
// NOLINTNEXTLINE(clang-analyzer-optin.portability.UnixAPI)
|
||||||
|
DynamicJsonDocument doc(0);
|
||||||
|
|
||||||
|
SECTION("Input is const char*") {
|
||||||
|
REQUIRE(deserializeJson(doc, "\"hello\"") ==
|
||||||
|
DeserializationError::NoMemory);
|
||||||
|
REQUIRE(deserializeJson(doc, "\"\"") == DeserializationError::NoMemory);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Input is const char*") {
|
||||||
|
char hello[] = "\"hello\"";
|
||||||
|
REQUIRE(deserializeJson(doc, hello) == DeserializationError::Ok);
|
||||||
|
char empty[] = "\"hello\"";
|
||||||
|
REQUIRE(deserializeJson(doc, empty) == DeserializationError::Ok);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -11,12 +11,11 @@ TEST_CASE("StringCopier") {
|
|||||||
char buffer[4096];
|
char buffer[4096];
|
||||||
|
|
||||||
SECTION("Works when buffer is big enough") {
|
SECTION("Works when buffer is big enough") {
|
||||||
MemoryPool pool(buffer, addPadding(JSON_STRING_SIZE(6)));
|
MemoryPool pool(buffer, addPadding(JSON_STRING_SIZE(5)));
|
||||||
StringCopier str(pool);
|
StringCopier str(pool);
|
||||||
|
|
||||||
str.startString();
|
str.startString();
|
||||||
str.append("hello");
|
str.append("hello");
|
||||||
str.append('\0');
|
|
||||||
|
|
||||||
REQUIRE(str.isValid() == true);
|
REQUIRE(str.isValid() == true);
|
||||||
REQUIRE(std::string(str.str()) == "hello");
|
REQUIRE(std::string(str.str()) == "hello");
|
||||||
@ -31,6 +30,7 @@ TEST_CASE("StringCopier") {
|
|||||||
str.append("hello world!");
|
str.append("hello world!");
|
||||||
|
|
||||||
REQUIRE(str.isValid() == false);
|
REQUIRE(str.isValid() == false);
|
||||||
|
REQUIRE(pool.overflowed() == true);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Increases size of memory pool") {
|
SECTION("Increases size of memory pool") {
|
||||||
@ -38,10 +38,19 @@ TEST_CASE("StringCopier") {
|
|||||||
StringCopier str(pool);
|
StringCopier str(pool);
|
||||||
|
|
||||||
str.startString();
|
str.startString();
|
||||||
str.append('h');
|
|
||||||
str.save();
|
str.save();
|
||||||
|
|
||||||
REQUIRE(1 == pool.size());
|
REQUIRE(1 == pool.size());
|
||||||
|
REQUIRE(pool.overflowed() == false);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("Works when memory pool is 0 bytes") {
|
||||||
|
MemoryPool pool(buffer, 0);
|
||||||
|
StringCopier str(pool);
|
||||||
|
|
||||||
|
str.startString();
|
||||||
|
REQUIRE(str.isValid() == false);
|
||||||
|
REQUIRE(pool.overflowed() == true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +58,6 @@ static const char* addStringToPool(MemoryPool& pool, const char* s) {
|
|||||||
StringCopier str(pool);
|
StringCopier str(pool);
|
||||||
str.startString();
|
str.startString();
|
||||||
str.append(s);
|
str.append(s);
|
||||||
str.append('\0');
|
|
||||||
return str.save().c_str();
|
return str.save().c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,6 @@ static void testCodepoint(uint32_t codepoint, std::string expected) {
|
|||||||
CAPTURE(codepoint);
|
CAPTURE(codepoint);
|
||||||
Utf8::encodeCodepoint(codepoint, str);
|
Utf8::encodeCodepoint(codepoint, str);
|
||||||
|
|
||||||
str.append('\0');
|
|
||||||
REQUIRE(str.str().c_str() == expected);
|
REQUIRE(str.str().c_str() == expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,6 +60,7 @@ TEST_CASE("Printable") {
|
|||||||
CHECK(printable.totalBytesWritten() == 7);
|
CHECK(printable.totalBytesWritten() == 7);
|
||||||
CHECK(doc.overflowed() == false);
|
CHECK(doc.overflowed() == false);
|
||||||
CHECK(doc.memoryUsage() == 8);
|
CHECK(doc.memoryUsage() == 8);
|
||||||
|
CHECK(doc.as<JsonVariant>().memoryUsage() == 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Via Print::write(const char* size_t)") {
|
SECTION("Via Print::write(const char* size_t)") {
|
||||||
@ -69,6 +70,7 @@ TEST_CASE("Printable") {
|
|||||||
CHECK(printable.totalBytesWritten() == 7);
|
CHECK(printable.totalBytesWritten() == 7);
|
||||||
CHECK(doc.overflowed() == false);
|
CHECK(doc.overflowed() == false);
|
||||||
CHECK(doc.memoryUsage() == 8);
|
CHECK(doc.memoryUsage() == 8);
|
||||||
|
CHECK(doc.as<JsonVariant>().memoryUsage() == 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -401,8 +401,6 @@ class JsonDeserializer {
|
|||||||
_stringStorage.append(c);
|
_stringStorage.append(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
_stringStorage.append('\0');
|
|
||||||
|
|
||||||
if (!_stringStorage.isValid()) {
|
if (!_stringStorage.isValid()) {
|
||||||
_error = DeserializationError::NoMemory;
|
_error = DeserializationError::NoMemory;
|
||||||
return false;
|
return false;
|
||||||
@ -426,8 +424,6 @@ class JsonDeserializer {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_stringStorage.append('\0');
|
|
||||||
|
|
||||||
if (!_stringStorage.isValid()) {
|
if (!_stringStorage.isValid()) {
|
||||||
_error = DeserializationError::NoMemory;
|
_error = DeserializationError::NoMemory;
|
||||||
return false;
|
return false;
|
||||||
|
@ -87,13 +87,14 @@ class MemoryPool {
|
|||||||
|
|
||||||
const char* saveStringFromFreeZone(size_t len) {
|
const char* saveStringFromFreeZone(size_t len) {
|
||||||
#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
|
#if ARDUINOJSON_ENABLE_STRING_DEDUPLICATION
|
||||||
const char* dup = findString(adaptString(_left));
|
const char* dup = findString(adaptString(_left, len));
|
||||||
if (dup)
|
if (dup)
|
||||||
return dup;
|
return dup;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const char* str = _left;
|
const char* str = _left;
|
||||||
_left += len;
|
_left += len;
|
||||||
|
*_left++ = 0;
|
||||||
checkInvariants();
|
checkInvariants();
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
@ -343,7 +343,6 @@ class MsgPackDeserializer {
|
|||||||
return false;
|
return false;
|
||||||
_stringStorage.append(static_cast<char>(c));
|
_stringStorage.append(static_cast<char>(c));
|
||||||
}
|
}
|
||||||
_stringStorage.append('\0');
|
|
||||||
if (!_stringStorage.isValid()) {
|
if (!_stringStorage.isValid()) {
|
||||||
_error = DeserializationError::NoMemory;
|
_error = DeserializationError::NoMemory;
|
||||||
return false;
|
return false;
|
||||||
|
@ -17,10 +17,13 @@ class StringCopier {
|
|||||||
void startString() {
|
void startString() {
|
||||||
_pool->getFreeZone(&_ptr, &_capacity);
|
_pool->getFreeZone(&_ptr, &_capacity);
|
||||||
_size = 0;
|
_size = 0;
|
||||||
|
if (_capacity == 0)
|
||||||
|
_pool->markAsOverflowed();
|
||||||
}
|
}
|
||||||
|
|
||||||
string_type save() {
|
string_type save() {
|
||||||
ARDUINOJSON_ASSERT(_ptr);
|
ARDUINOJSON_ASSERT(_ptr);
|
||||||
|
ARDUINOJSON_ASSERT(_size < _capacity); // needs room for the terminator
|
||||||
return _pool->saveStringFromFreeZone(_size);
|
return _pool->saveStringFromFreeZone(_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,23 +36,24 @@ class StringCopier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void append(char c) {
|
void append(char c) {
|
||||||
if (!_ptr)
|
if (_size + 1 < _capacity)
|
||||||
return;
|
_ptr[_size++] = c;
|
||||||
|
else
|
||||||
if (_size >= _capacity) {
|
|
||||||
_ptr = 0;
|
|
||||||
_pool->markAsOverflowed();
|
_pool->markAsOverflowed();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_ptr[_size++] = c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isValid() {
|
bool isValid() const {
|
||||||
return _ptr != 0;
|
return !_pool->overflowed();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const {
|
||||||
|
return _size;
|
||||||
}
|
}
|
||||||
|
|
||||||
string_type str() const {
|
string_type str() const {
|
||||||
|
ARDUINOJSON_ASSERT(_ptr);
|
||||||
|
ARDUINOJSON_ASSERT(_size < _capacity);
|
||||||
|
_ptr[_size] = 0;
|
||||||
return _ptr;
|
return _ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,10 @@ class StringMover {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FORCE_INLINE string_type save() {
|
FORCE_INLINE string_type save() {
|
||||||
return _startPtr;
|
_writePtr[0] = 0; // terminator
|
||||||
|
string_type s = str();
|
||||||
|
_writePtr++;
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void append(char c) {
|
void append(char c) {
|
||||||
@ -35,6 +38,10 @@ class StringMover {
|
|||||||
return string_type(_startPtr);
|
return string_type(_startPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t size() const {
|
||||||
|
return size_t(_writePtr - _startPtr);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char* _writePtr;
|
char* _writePtr;
|
||||||
char* _startPtr;
|
char* _startPtr;
|
||||||
|
@ -204,8 +204,7 @@ class MemoryPoolPrint : public Print {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CopiedString str() {
|
CopiedString str() {
|
||||||
_string[_size++] = 0;
|
ARDUINOJSON_ASSERT(_size < _capacity);
|
||||||
ARDUINOJSON_ASSERT(_size <= _capacity);
|
|
||||||
return _pool->saveStringFromFreeZone(_size);
|
return _pool->saveStringFromFreeZone(_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user