Skip to content

Commit 3782684

Browse files
committed
fix another mem leak
1 parent 435aac7 commit 3782684

File tree

2 files changed

+39
-37
lines changed

2 files changed

+39
-37
lines changed

src/ArduinoYaml.cpp

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,9 @@ YAMLParser::~YAMLParser()
109109
{
110110
yaml_parser_delete(&_parser);
111111
yaml_emitter_delete(&_emitter);
112-
yaml_document_delete(&_document);
112+
#if !defined ESP8266 // TODO: fix mem leak with esp8266
113+
yaml_document_delete(&_document);
114+
#endif
113115
}
114116

115117

@@ -219,63 +221,60 @@ void YAMLParser::handle_emitter_error(yaml_emitter_t *e)
219221

220222
#if defined HAS_ARDUINOJSON
221223

224+
222225
// yaml_node_t deconstructor => JsonObject
223226
void deserializeYml_JsonObject( yaml_document_t* document, yaml_node_t* yamlNode, JsonObject &jsonNode, YAMLParser::JNestingType_t nt, const char *nodename, int depth )
224227
{
225-
// Prevent "use after free" situations in JsonObject key
226-
// ArduinoJson only aliases const char* so use char* to force a copy
227-
char* _nodename = (char*)malloc( strlen(nodename)+1 );
228-
strcpy(_nodename, nodename);
229-
230228
switch (yamlNode->type) {
231-
case YAML_NO_NODE: /*YAML_LOG_v("YAML_NO_NODE");*/ break;
232229
case YAML_SCALAR_NODE:
233230
{
234231
double number;
235232
char* scalar;
236233
char* end;
237-
bool is_string;
238234
scalar = (char *)yamlNode->data.scalar.value;
239235
number = strtod(scalar, &end);
240-
is_string = (end == scalar || *end);
236+
bool is_string = (end == scalar || *end);
241237
switch( nt ) {
242238
case YAMLParser::SEQ_KEY:
243239
{
244-
if(is_string) jsonNode[_nodename].add( scalar );
245-
else jsonNode[_nodename].add( number );
240+
JsonArray array = jsonNode[nodename];
241+
if(is_string) array.add( scalar );
242+
else array.add( number );
243+
//YAML_LOG_d("[SEQ][%s][%d] => %s(%s)", nodename, array.size()-1, is_string?"string":"number", is_string?scalar:String(number).c_str() );
246244
}
247245
break;
248246
case YAMLParser::MAP_KEY:
249-
if(is_string) jsonNode[_nodename] = scalar;
250-
else jsonNode[_nodename] = number;
247+
if(is_string) jsonNode[nodename] = scalar;
248+
else jsonNode[nodename] = number;
249+
//YAML_LOG_d("[MAP][%d][%s] => %s(%s)", jsonNode.size()-1, nodename, is_string?"string":"number", is_string?scalar:String(number).c_str() );
251250
break;
252251
default: YAML_LOG_e("Error invalid nesting type"); break;
253252
}
254253
}
255254
break;
256255
case YAML_SEQUENCE_NODE:
257256
{
258-
jsonNode.createNestedArray(_nodename);
257+
JsonArray tmpArray = jsonNode.createNestedArray(nodename);
259258
yaml_node_item_t * item_i;
259+
yaml_node_t *itemNode;
260+
String _nodename;
260261
for (item_i = yamlNode->data.sequence.items.start; item_i < yamlNode->data.sequence.items.top; ++item_i) {
261-
yaml_node_t *itemNode = yaml_document_get_node(document, *item_i);
262+
itemNode = yaml_document_get_node(document, *item_i);
262263
if( itemNode->type == YAML_MAPPING_NODE ) { // array of anonymous objects
263-
JsonObject tmpObj = jsonNode[_nodename].createNestedObject(); // insert empty nested object
264-
deserializeYml_JsonObject( document, itemNode, tmpObj, YAMLParser::SEQ_KEY, "root", depth+1 ); // go recursive using temporary node name
265-
jsonNode[_nodename][jsonNode[_nodename].size()-1].set( tmpObj["root"] ); // remove temporary name and make object anonymous
264+
JsonObject tmpObj = tmpArray.createNestedObject(); // insert empty nested object
265+
_nodename = ROOT_NODE + String( nodename ) + String( tmpArray.size() ); // generate a temporary nodename
266+
deserializeYml_JsonObject( document, itemNode, tmpObj, YAMLParser::SEQ_KEY, _nodename.c_str(), depth+1 ); // go recursive using temporary node name
267+
jsonNode[nodename][tmpArray.size()-1] = tmpObj[_nodename]; // remove temporary name and make object anonymous
266268
} else { // array of sequences or values
267-
deserializeYml_JsonObject( document, itemNode, jsonNode, YAMLParser::SEQ_KEY, _nodename, depth+1 );
269+
deserializeYml_JsonObject( document, itemNode, jsonNode, YAMLParser::SEQ_KEY, nodename, depth+1 );
268270
}
269271
}
272+
//YAML_LOG_d("[ARR][%s] has %d items", nodename, tmpArray.size() );
270273
}
271274
break;
272275
case YAML_MAPPING_NODE:
273276
{
274-
jsonNode.createNestedObject(_nodename);
275-
JsonObject tmpObj = jsonNode[_nodename];
276-
if( nt == YAMLParser::NONE ) {
277-
jsonNode = tmpObj; // topmost object, nodename is empty so apply reparenting
278-
}
277+
JsonObject tmpNode = jsonNode.createNestedObject(nodename);
279278
yaml_node_pair_t* pair_i;
280279
yaml_node_t* key;
281280
yaml_node_t* value;
@@ -286,18 +285,20 @@ void YAMLParser::handle_emitter_error(yaml_emitter_t *e)
286285
YAML_LOG_w("Mapping key is not scalar (line %lu, val=%s).", key->start_mark.line, (const char*)value->data.scalar.value);
287286
continue;
288287
}
289-
deserializeYml_JsonObject( document, value, tmpObj, YAMLParser::MAP_KEY, (const char*)key->data.scalar.value, depth+1 );
288+
deserializeYml_JsonObject( document, value, tmpNode, YAMLParser::MAP_KEY, (const char*)key->data.scalar.value, depth+1 );
289+
}
290+
if( nt == YAMLParser::NONE ) {
291+
//YAML_LOG_d("Root node has %d items", jsonNode.size() );
292+
} else {
293+
//YAML_LOG_d("[KEY][%s] has %d items", nodename, jsonNode.size() );
290294
}
291295
}
292296
break;
293-
default:
294-
YAML_LOG_w("Unknown node type (line %lu).", yamlNode->start_mark.line);
295-
break;
297+
case YAML_NO_NODE: YAML_LOG_e("YAML_NO_NODE"); break;
298+
default: YAML_LOG_w("Unknown node type (line %lu).", yamlNode->start_mark.line); break;
296299
}
297-
free(_nodename);
298300
}
299301

300-
301302
// JsonVariant deconstructor => YAML stream
302303
size_t serializeYml_JsonVariant( JsonVariant root, Stream &out, int depth, YAMLParser::JNestingType_t nt )
303304
{
@@ -362,7 +363,7 @@ void YAMLParser::handle_emitter_error(yaml_emitter_t *e)
362363
{
363364
YAMLToArduinoJson *parser = new YAMLToArduinoJson();
364365
JsonObject tmpObj = parser->toJson( src ); // decode yaml stream/string
365-
dest_doc.set( tmpObj );
366+
dest_doc.set( tmpObj[ROOT_NODE] );
366367
delete parser;
367368
return DeserializationError::Ok;
368369
}
@@ -372,7 +373,7 @@ void YAMLParser::handle_emitter_error(yaml_emitter_t *e)
372373
{
373374
YAMLToArduinoJson *parser = new YAMLToArduinoJson();
374375
JsonObject tmpObj = parser->toJson( src ); // decode yaml stream/string
375-
dest_doc.set( tmpObj );
376+
dest_doc.set( tmpObj[ROOT_NODE] );
376377
delete parser;
377378
return DeserializationError::Ok;
378379
}

src/ArduinoYaml.hpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -110,22 +110,24 @@ class YAMLParser
110110
#include <ArduinoJson.h>
111111

112112
// deconstructors
113-
void deserializeYml_JsonObject( yaml_document_t* document, yaml_node_t* yamlNode, JsonObject &jsonNode, YAMLParser::JNestingType_t nt=YAMLParser::NONE, const char *nodename="", int depth=0 );
113+
#define ROOT_NODE "_root_"
114+
void deserializeYml_JsonObject( yaml_document_t* document, yaml_node_t* yamlNode, JsonObject &jsonNode, YAMLParser::JNestingType_t nt=YAMLParser::NONE, const char *nodename=ROOT_NODE, int depth=0 );
114115
size_t serializeYml_JsonVariant( JsonVariant root, Stream &out, int depth_level, YAMLParser::JNestingType_t nt );
115116

116117
class YAMLToArduinoJson : public YAMLParser
117118
{
118119
public:
119120
YAMLToArduinoJson() {};
120-
~YAMLToArduinoJson() { if( _doc) delete _doc; };
121-
void setJsonDocument( const size_t capacity ) { _doc = new DynamicJsonDocument(capacity); _root = _doc->to<JsonObject>(); };
121+
~YAMLToArduinoJson() { if( _doc) delete _doc; }
122+
void setJsonDocument( const size_t capacity ) { _doc = new DynamicJsonDocument(capacity); _root = _doc->to<JsonObject>(); /*_root.createNestedObject(ROOT_NODE);*/ }
122123
JsonObject& getJsonObject() { return _root; }
123124
void toJson() {
124125
yaml_node_t * node;
125126
if( !_doc || _root.isNull() ) {
126127
YAML_LOG_e("No destination JsonObject defined.");
127128
return;
128129
}
130+
// YAML_LOG_i("JsonDocument capacity: %d (%d/%d yaml r/w)", _doc->capacity(), bytesRead(), bytesWritten() );
129131
// dafuq is that if( a=b, !a ) notation ??
130132
if (node = yaml_document_get_root_node(getDocument()), !node) {
131133
YAML_LOG_e("No document defined.");
@@ -171,8 +173,7 @@ class YAMLParser
171173
DeserializationError deserializeYml( JsonObject &dest_obj, T &src)
172174
{
173175
YAMLToArduinoJson *parser = new YAMLToArduinoJson();
174-
JsonObject tmpObj = parser->toJson( src ); // decode yaml stream/string
175-
dest_obj = tmpObj;
176+
dest_obj = parser->toJson( src ); // decode yaml stream/string
176177
size_t capacity = parser->bytesWritten()*2;
177178
delete parser;
178179
if( capacity == 0 ) {

0 commit comments

Comments
 (0)