summaryrefslogtreecommitdiffstats
path: root/src/jplist.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/jplist.c')
-rw-r--r--src/jplist.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/src/jplist.c b/src/jplist.c
index 1c7a932..2e53400 100644
--- a/src/jplist.c
+++ b/src/jplist.c
@@ -38,6 +38,7 @@
38#include "plist.h" 38#include "plist.h"
39#include "strbuf.h" 39#include "strbuf.h"
40#include "jsmn.h" 40#include "jsmn.h"
41#include "hashtable.h"
41 42
42#ifdef DEBUG 43#ifdef DEBUG
43static int plist_json_debug = 0; 44static int plist_json_debug = 0;
@@ -315,18 +316,27 @@ static int num_digits_u(uint64_t i)
315 return n; 316 return n;
316} 317}
317 318
318static plist_err_t node_estimate_size(node_t node, uint64_t *size, uint32_t depth, int prettify) 319static plist_err_t _node_estimate_size(node_t node, uint64_t *size, uint32_t depth, int prettify, hashtable_t *visited)
319{ 320{
320 plist_data_t data; 321 plist_data_t data;
321 if (!node) { 322 if (!node) {
322 return PLIST_ERR_INVALID_ARG; 323 return PLIST_ERR_INVALID_ARG;
323 } 324 }
325
326 if (hash_table_lookup(visited, node)) {
327 PLIST_JSON_WRITE_ERR("circular reference detected\n");
328 return PLIST_ERR_CIRCULAR_REF;
329 }
330
331 // mark as visited
332 hash_table_insert(visited, node, (void*)1);
333
324 data = plist_get_data(node); 334 data = plist_get_data(node);
325 if (node->children) { 335 if (node->children) {
326 node_t ch; 336 node_t ch;
327 unsigned int n_children = node_n_children(node); 337 unsigned int n_children = node_n_children(node);
328 for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) { 338 for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) {
329 plist_err_t res = node_estimate_size(ch, size, depth + 1, prettify); 339 plist_err_t res = _node_estimate_size(ch, size, depth + 1, prettify, visited);
330 if (res < 0) { 340 if (res < 0) {
331 return res; 341 return res;
332 } 342 }
@@ -402,6 +412,15 @@ static plist_err_t node_estimate_size(node_t node, uint64_t *size, uint32_t dept
402 return PLIST_ERR_SUCCESS; 412 return PLIST_ERR_SUCCESS;
403} 413}
404 414
415static plist_err_t node_estimate_size(node_t node, uint64_t *size, uint32_t depth, int prettify)
416{
417 hashtable_t *visited = hash_table_new(plist_node_ptr_hash, plist_node_ptr_compare, NULL);
418 if (!visited) return PLIST_ERR_NO_MEM;
419 plist_err_t err = _node_estimate_size(node, size, depth, prettify, visited);
420 hash_table_destroy(visited);
421 return err;
422}
423
405plist_err_t plist_to_json(plist_t plist, char **plist_json, uint32_t* length, int prettify) 424plist_err_t plist_to_json(plist_t plist, char **plist_json, uint32_t* length, int prettify)
406{ 425{
407 uint64_t size = 0; 426 uint64_t size = 0;