summaryrefslogtreecommitdiffstats
path: root/src/out-default.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/out-default.c')
-rw-r--r--src/out-default.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/src/out-default.c b/src/out-default.c
index 266070b..09e64c3 100644
--- a/src/out-default.c
+++ b/src/out-default.c
@@ -38,6 +38,7 @@
38#include "plist.h" 38#include "plist.h"
39#include "strbuf.h" 39#include "strbuf.h"
40#include "time64.h" 40#include "time64.h"
41#include "hashtable.h"
41 42
42#define MAC_EPOCH 978307200 43#define MAC_EPOCH 978307200
43 44
@@ -310,19 +311,30 @@ static int num_digits_u(uint64_t i)
310 return n; 311 return n;
311} 312}
312 313
313static plist_err_t node_estimate_size(node_t node, uint64_t *size, uint32_t depth, uint32_t indent, int partial_data) 314static plist_err_t _node_estimate_size(node_t node, uint64_t *size, uint32_t depth, uint32_t indent, int partial_data, hashtable_t *visited)
314{ 315{
315 plist_data_t data; 316 plist_data_t data;
316 if (!node) { 317 if (!node) {
317 return PLIST_ERR_INVALID_ARG; 318 return PLIST_ERR_INVALID_ARG;
318 } 319 }
320
321 if (hash_table_lookup(visited, node)) {
322#if DEBUG
323 fprintf(stderr, "libplist: ERROR: circular reference detected\n");
324#endif
325 return PLIST_ERR_CIRCULAR_REF;
326 }
327
328 // mark as visited
329 hash_table_insert(visited, node, (void*)1);
330
319 data = plist_get_data(node); 331 data = plist_get_data(node);
320 if (node->children) { 332 if (node->children) {
321 node_t ch; 333 node_t ch;
322 unsigned int n_children = node_n_children(node); 334 unsigned int n_children = node_n_children(node);
323 for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) { 335 for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) {
324 plist_err_t res = node_estimate_size(ch, size, depth + 1, indent, partial_data); 336 plist_err_t res = _node_estimate_size(ch, size, depth + 1, indent, partial_data, visited);
325 if (res < 0) { 337 if (res != PLIST_ERR_SUCCESS) {
326 return res; 338 return res;
327 } 339 }
328 } 340 }
@@ -401,6 +413,15 @@ static plist_err_t node_estimate_size(node_t node, uint64_t *size, uint32_t dept
401 return PLIST_ERR_SUCCESS; 413 return PLIST_ERR_SUCCESS;
402} 414}
403 415
416static plist_err_t node_estimate_size(node_t node, uint64_t *size, uint32_t depth, uint32_t indent, int partial_data)
417{
418 hashtable_t *visited = hash_table_new(plist_node_ptr_hash, plist_node_ptr_compare, NULL);
419 if (!visited) return PLIST_ERR_NO_MEM;
420 plist_err_t err = _node_estimate_size(node, size, depth, indent, partial_data, visited);
421 hash_table_destroy(visited);
422 return err;
423}
424
404static plist_err_t _plist_write_to_strbuf(plist_t plist, strbuf_t *outbuf, plist_write_options_t options) 425static plist_err_t _plist_write_to_strbuf(plist_t plist, strbuf_t *outbuf, plist_write_options_t options)
405{ 426{
406 uint8_t indent = 0; 427 uint8_t indent = 0;