Abandon own buffer size control

pull/41/head
Hieromon Ikasamo 6 years ago
parent b0fbfc3558
commit 3058169829
  1. 2
      src/AutoConnect.h
  2. 189
      src/AutoConnectAux.cpp
  3. 23
      src/AutoConnectAux.h
  4. 2
      src/AutoConnectElement.h

@ -176,7 +176,7 @@ class AutoConnect {
#ifdef AUTOCONNECT_USE_JSON #ifdef AUTOCONNECT_USE_JSON
bool load(const String& aux); bool load(const String& aux);
bool load(const __FlashStringHelper* aux); bool load(const __FlashStringHelper* aux);
bool load(Stream& aux, size_t bufferSize = AUTOCONNECT_JSON_BUFFER_SIZE); bool load(Stream& aux);
bool _load(JsonVariant& aux); bool _load(JsonVariant& aux);
#endif // !AUTOCONNECT_USE_JSON #endif // !AUTOCONNECT_USE_JSON

@ -488,21 +488,6 @@ AutoConnectTextBasis& AutoConnectAux::getElement(const String& name) {
#else #else
/**
* Static storage for JSON buffer size calculation.
*/
int16_t AutoConnectAux::_jbSize; /**< JSON dynamic buffer size */
uint16_t AutoConnectAux::_jbByte; /**< Byte count for calculation of JSON buffer */
uint8_t AutoConnectAux::_jbObject; /**< Object count for calculation of JSON buffer */
uint8_t AutoConnectAux::_jbArray; /**< Array count for calculation of JSON buffer */
uint8_t AutoConnectAux::_jbNest; /**< JSON array nest count */
uint8_t AutoConnectAux::_kStack[AUTOCONENCT_JSONOBJECTTREE_MAXDEPTH]; /**< JSON array counter stack */
uint8_t AutoConnectAux::_nStack[AUTOCONENCT_JSONOBJECTTREE_MAXDEPTH]; /**< JSON object counter stack */
int8_t AutoConnectAux::_kp; /**< Stack pointer for JSON array counter */
int8_t AutoConnectAux::_np; /**< Stack pointer for JSON object counter */
bool AutoConnectAux::_jbOpen; /**< JSON object paring status */
bool AutoConnectAux::_jbLiteral; /**< JSON object lexical status */
/** /**
* Get AutoConnectButtonJson element. * Get AutoConnectButtonJson element.
* @param name An element name. * @param name An element name.
@ -630,8 +615,7 @@ AutoConnectTextJson& AutoConnectAux::getElement(const String& name) {
* @return true Successfully loaded. * @return true Successfully loaded.
*/ */
bool AutoConnect::load(const String& aux) { bool AutoConnect::load(const String& aux) {
const size_t bufferSize = AutoConnectAux::_calcJsonBufferSize(aux.c_str()); DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
DynamicJsonBuffer jsonBuffer(bufferSize);
JsonVariant jv = jsonBuffer.parse(aux); JsonVariant jv = jsonBuffer.parse(aux);
return _load(jv); return _load(jv);
} }
@ -644,8 +628,7 @@ bool AutoConnect::load(const String& aux) {
* @return true Successfully loaded. * @return true Successfully loaded.
*/ */
bool AutoConnect::load(const __FlashStringHelper* aux) { bool AutoConnect::load(const __FlashStringHelper* aux) {
const size_t bufferSize = AutoConnectAux::_calcJsonBufferSize(aux); DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
DynamicJsonBuffer jsonBuffer(bufferSize);
JsonVariant jv = jsonBuffer.parse(aux); JsonVariant jv = jsonBuffer.parse(aux);
return _load(jv); return _load(jv);
} }
@ -657,8 +640,8 @@ bool AutoConnect::load(const __FlashStringHelper* aux) {
* @param aux Stream for read AutoConnectAux elements. * @param aux Stream for read AutoConnectAux elements.
* @return true Successfully loaded. * @return true Successfully loaded.
*/ */
bool AutoConnect::load(Stream& aux, size_t bufferSize) { bool AutoConnect::load(Stream& aux) {
DynamicJsonBuffer jsonBuffer(bufferSize); DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
JsonVariant jv = jsonBuffer.parse(aux); JsonVariant jv = jsonBuffer.parse(aux);
return _load(jv); return _load(jv);
} }
@ -755,8 +738,7 @@ AutoConnectElement* AutoConnectAux::_createElement(const JsonObject& json) {
* @return false Invalid JSON data occurred. * @return false Invalid JSON data occurred.
*/ */
bool AutoConnectAux::load(const String& in) { bool AutoConnectAux::load(const String& in) {
const size_t bufferSize = _calcJsonBufferSize(in.c_str()); DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
DynamicJsonBuffer jsonBuffer(bufferSize);
JsonObject& jb = jsonBuffer.parseObject(in); JsonObject& jb = jsonBuffer.parseObject(in);
return _load(jb); return _load(jb);
} }
@ -770,8 +752,7 @@ bool AutoConnectAux::load(const String& in) {
* @return false Invalid JSON data occurred. * @return false Invalid JSON data occurred.
*/ */
bool AutoConnectAux::load(const __FlashStringHelper* in) { bool AutoConnectAux::load(const __FlashStringHelper* in) {
const size_t bufferSize = _calcJsonBufferSize(in); DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
DynamicJsonBuffer jsonBuffer(bufferSize);
JsonObject& jb = jsonBuffer.parseObject(in); JsonObject& jb = jsonBuffer.parseObject(in);
return _load(jb); return _load(jb);
} }
@ -784,8 +765,8 @@ bool AutoConnectAux::load(const __FlashStringHelper* in) {
* @return true The element collection successfully loaded. * @return true The element collection successfully loaded.
* @return false Invalid JSON data occurred. * @return false Invalid JSON data occurred.
*/ */
bool AutoConnectAux::load(Stream& in, const size_t bufferSize) { bool AutoConnectAux::load(Stream& in) {
DynamicJsonBuffer jsonBuffer(bufferSize); DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
JsonObject& jb = jsonBuffer.parseObject(in); JsonObject& jb = jsonBuffer.parseObject(in);
return _load(jb); return _load(jb);
} }
@ -822,21 +803,19 @@ bool AutoConnectAux::_load(JsonObject& jb) {
* @return A reference of loaded AutoConnectElement instance. * @return A reference of loaded AutoConnectElement instance.
*/ */
bool AutoConnectAux::loadElement(const String& in, const String& name) { bool AutoConnectAux::loadElement(const String& in, const String& name) {
const size_t bufferSize = _calcJsonBufferSize(in.c_str()); DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
DynamicJsonBuffer jsonBuffer(bufferSize);
JsonVariant jb = jsonBuffer.parse(in); JsonVariant jb = jsonBuffer.parse(in);
return _loadElement(jb, name); return _loadElement(jb, name);
} }
bool AutoConnectAux::loadElement(const __FlashStringHelper* in, const String& name) { bool AutoConnectAux::loadElement(const __FlashStringHelper* in, const String& name) {
const size_t bufferSize = _calcJsonBufferSize(in); DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
DynamicJsonBuffer jsonBuffer(bufferSize);
JsonVariant jb = jsonBuffer.parse(in); JsonVariant jb = jsonBuffer.parse(in);
return _loadElement(jb, name); return _loadElement(jb, name);
} }
bool AutoConnectAux::loadElement(Stream& in, const String& name, const size_t bufferSize) { bool AutoConnectAux::loadElement(Stream& in, const String& name) {
DynamicJsonBuffer jsonBuffer(bufferSize); DynamicJsonBuffer jsonBuffer(AUTOCONNECT_JSON_BUFFER_SIZE);
JsonVariant jb = jsonBuffer.parse(in); JsonVariant jb = jsonBuffer.parse(in);
return _loadElement(jb, name); return _loadElement(jb, name);
} }
@ -873,6 +852,7 @@ AutoConnectElement& AutoConnectAux::_loadElement(JsonObject& element, const Stri
auxElm = getElement(elmName); auxElm = getElement(elmName);
// The element is not created yet, create new one. // The element is not created yet, create new one.
if (!auxElm) { if (!auxElm) {
if (elmName.length()) {
if ((auxElm = _createElement(element))) { if ((auxElm = _createElement(element))) {
AC_DBG("%s<%d> of %s created\n", elmName.c_str(), (int)(auxElm->typeOf()), uri()); AC_DBG("%s<%d> of %s created\n", elmName.c_str(), (int)(auxElm->typeOf()), uri());
add(*auxElm); // Insert to AutoConnect add(*auxElm); // Insert to AutoConnect
@ -881,6 +861,11 @@ AutoConnectElement& AutoConnectAux::_loadElement(JsonObject& element, const Stri
AC_DBG("%s unknown element type\n", elmName.c_str()); AC_DBG("%s unknown element type\n", elmName.c_str());
} }
} }
else {
AC_DBG("Element name missing\n");
}
}
if (auxElm) {
if (auxElm->loadMember(element)) if (auxElm->loadMember(element))
AC_DBG("%s<%d> of %s loaded\n", auxElm->name.c_str(), (int)auxElm->typeOf(), uri()); AC_DBG("%s<%d> of %s loaded\n", auxElm->name.c_str(), (int)auxElm->typeOf(), uri());
else { else {
@ -888,6 +873,7 @@ AutoConnectElement& AutoConnectAux::_loadElement(JsonObject& element, const Stri
AC_DBG("Type of %s element mismatched\n", elmName.c_str()); AC_DBG("Type of %s element mismatched\n", elmName.c_str());
} }
} }
}
return auxElm ? *auxElm : _nullElement(); return auxElm ? *auxElm : _nullElement();
} }
@ -982,141 +968,4 @@ const ACElement_t AutoConnectAux::_asElementType(const String& type) {
return t; return t;
} }
/**
* Calculate JSON dynamic buffer size.
* @param in JSON string
* @return Estimated buffer size.
*/
size_t AutoConnectAux::_calcJsonBufferSize(const char* in) {
_initJsonBufferSize();
while (*in)
_accJsonBufferSize(*in++);
return _resultJsonBufferSize();
}
/**
* Calculate JSON dynamic buffer size.
* @param in JSON string stored in pgm_data.
* @return Estimated buffer size.
*/
size_t AutoConnectAux::_calcJsonBufferSize(const __FlashStringHelper* in) {
_initJsonBufferSize();
uint8_t c = pgm_read_byte_near(reinterpret_cast<const char*>(in));
size_t l = 0;
while (c) {
_accJsonBufferSize(static_cast<const char>(c));
c = pgm_read_byte_near(reinterpret_cast<const char*>(in) + ++l);
}
return _resultJsonBufferSize();
}
/**
* Initialize the stacks for JSON Dynamic buffer size calculation.
*/
void AutoConnectAux::_initJsonBufferSize() {
_jbSize = 0;
_jbByte = 0;
_jbObject = 0;
_jbArray = 0;
_jbNest = 0;
_kp = -1;
_np = -1;
_jbOpen = false;
_jbLiteral = false;
}
/**
* Accumulate JSON Dynamic buffer size.
*/
void AutoConnectAux::_accJsonBufferSize(const char c) {
if (_jbSize < 0)
return;
if (!isGraph(c))
return;
if (_jbLiteral)
_jbByte++;
switch (c) {
case '"':
_jbLiteral = !_jbLiteral;
break;
case ':':
_jbObject++;
_jbOpen = false;
break;
case '{':
if (_jbObject > 0) {
if (_np >= AUTOCONENCT_JSONOBJECTTREE_MAXDEPTH) {
_jbSize = -1;
break;
}
_nStack[++_np] = _jbObject;
}
_jbObject = 0;
_jbOpen = true;
break;
case '}':
if (_jbNest > 0)
_jbArray++;
if (_jbObject > 0) {
_jbSize += JSON_OBJECT_SIZE(_jbObject);
_jbByte += 2;
}
_jbObject = _nStack[_np--];
_jbOpen = false;
break;
case '[':
if (_jbNest++ > 0) {
if (_kp >= AUTOCONENCT_JSONOBJECTTREE_MAXDEPTH) {
_jbSize = -1;
break;
}
_kStack[++_kp] = _jbArray;
}
_jbArray = 0;
if (_jbObject > 0) {
if (_np >= AUTOCONENCT_JSONOBJECTTREE_MAXDEPTH) {
_jbSize = -1;
break;
}
_nStack[++_np] = _jbObject;
_jbObject = 0;
}
_jbOpen = true;
break;
case ']':
if (_jbOpen)
_jbArray++;
_jbSize += JSON_ARRAY_SIZE(_jbArray);
_jbByte += 2;
_jbArray = _nStack[_kp--];
_jbNest--;
if (_np >= 0)
_jbObject = _nStack[_np--];
_jbObject = false;
break;
case ',':
if (_jbObject && _jbNest > 0)
_jbArray++;
break;
}
}
/**
* Retrieve accumulated result value of JSON dynamic buffer size.
* @return the JSON Dynamic Buffer Size
*/
size_t AutoConnectAux::_resultJsonBufferSize() {
if (_jbSize < 0) {
AC_DBG("json buffer calculation error\n");
return -1;
}
else {
AC_DBG("json buffer size:%d\n", _jbSize + _jbByte);
return static_cast<size_t>(_jbSize + _jbByte);
}
}
#endif // AUTOCONNECT_USE_JSON #endif // AUTOCONNECT_USE_JSON

@ -66,10 +66,10 @@ class AutoConnectAux : public PageBuilder {
#ifdef AUTOCONNECT_USE_JSON #ifdef AUTOCONNECT_USE_JSON
bool load(const String& in); /**< Load whole elements to AutoConnectAux Page */ bool load(const String& in); /**< Load whole elements to AutoConnectAux Page */
bool load(const __FlashStringHelper* in); /**< Load whole elements to AutoConnectAux Page */ bool load(const __FlashStringHelper* in); /**< Load whole elements to AutoConnectAux Page */
bool load(Stream& in, const size_t bufferSize = AUTOCONNECT_JSON_BUFFER_SIZE); /**< Load whole elements to AutoConnectAux Page */ bool load(Stream& in); /**< Load whole elements to AutoConnectAux Page */
bool loadElement(const String& in, const String& name = String("")); /**< Load specified element */ bool loadElement(const String& in, const String& name = String("")); /**< Load specified element */
bool loadElement(const __FlashStringHelper* in, const String& name = String("")); /**< Load specified element */ bool loadElement(const __FlashStringHelper* in, const String& name = String("")); /**< Load specified element */
bool loadElement(Stream& in, const String& name = String(""), const size_t bufferSize = AUTOCONNECT_JSON_BUFFER_SIZE); /**< Load specified element */ bool loadElement(Stream& in, const String& name = String("")); /**< Load specified element */
size_t saveElement(Stream& out, std::vector<String> const& names = {}); /**< Write elements of AutoConnectAux to the stream */ size_t saveElement(Stream& out, std::vector<String> const& names = {}); /**< Write elements of AutoConnectAux to the stream */
#endif // !AUTOCONNECT_USE_JSON #endif // !AUTOCONNECT_USE_JSON
@ -105,25 +105,6 @@ class AutoConnectAux : public PageBuilder {
// Protected members can be used from AutoConnect which handles AutoConnectAux pages. // Protected members can be used from AutoConnect which handles AutoConnectAux pages.
friend class AutoConnect; friend class AutoConnect;
private:
static size_t _calcJsonBufferSize(const char* in); /**< Calculate JSON buffer size for constant character array */
static size_t _calcJsonBufferSize(const __FlashStringHelper* in); /**< Calculate JSON buffer size for pgm_data */
static void _initJsonBufferSize(void); /**< Initialize the stacks for JSON Dynamic buffer size calculation */
static void _accJsonBufferSize(const char c); /**< Accumulate JSON Dynamic buffer size */
static size_t _resultJsonBufferSize(void); /**< Retrieve accumulated result value */
static int16_t _jbSize; /**< JSON dynamic buffer size */
static uint16_t _jbByte; /**< Byte count for calculation of JSON buffer */
static uint8_t _jbObject; /**< Object count for calculation of JSON buffer */
static uint8_t _jbArray; /**< Array count for calculation of JSON buffer */
static uint8_t _jbNest; /**< JSON array nest count */
static uint8_t _kStack[AUTOCONENCT_JSONOBJECTTREE_MAXDEPTH]; /**< JSON array counter stack */
static uint8_t _nStack[AUTOCONENCT_JSONOBJECTTREE_MAXDEPTH]; /**< JSON object counter stack */
static int8_t _kp; /**< Stack pointer for JSON array counter */
static int8_t _np; /**< Stack pointer for JSON object counter */
static bool _jbOpen; /**< JSON object paring status */
static bool _jbLiteral; /**< JSON object lexical status */
}; };
#endif // _AUTOCONNECTAUX_H_ #endif // _AUTOCONNECTAUX_H_

@ -22,7 +22,7 @@ using AutoConnectRadio = AutoConnectRadioJson;
using AutoConnectSelect = AutoConnectSelectJson; using AutoConnectSelect = AutoConnectSelectJson;
using AutoConnectSubmit = AutoConnectSubmitJson; using AutoConnectSubmit = AutoConnectSubmitJson;
using AutoConnectText = AutoConnectTextJson; using AutoConnectText = AutoConnectTextJson;
#define AUTOCONNECT_JSON_BUFFER_SIZE 512 #define AUTOCONNECT_JSON_BUFFER_SIZE 256
#else #else
using AutoConnectElement = AutoConnectElementBasis; using AutoConnectElement = AutoConnectElementBasis;
using AutoConnectButton = AutoConnectButtonBasis; using AutoConnectButton = AutoConnectButtonBasis;

Loading…
Cancel
Save