summaryrefslogtreecommitdiffstats
path: root/src/xplist.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xplist.c')
-rw-r--r--src/xplist.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/src/xplist.c b/src/xplist.c
index dc5213b..c25c6b9 100644
--- a/src/xplist.c
+++ b/src/xplist.c
@@ -46,6 +46,7 @@
46#include "base64.h" 46#include "base64.h"
47#include "strbuf.h" 47#include "strbuf.h"
48#include "time64.h" 48#include "time64.h"
49#include "hashtable.h"
49 50
50#define XPLIST_KEY "key" 51#define XPLIST_KEY "key"
51#define XPLIST_KEY_LEN 3 52#define XPLIST_KEY_LEN 3
@@ -444,17 +445,29 @@ static int num_digits_u(uint64_t i)
444 return n; 445 return n;
445} 446}
446 447
447static plist_err_t node_estimate_size(node_t node, uint64_t *size, uint32_t depth) 448static plist_err_t _node_estimate_size(node_t node, uint64_t *size, uint32_t depth, hashtable_t *visited)
448{ 449{
449 plist_data_t data; 450 plist_data_t data;
450 if (!node) { 451 if (!node) {
451 return PLIST_ERR_INVALID_ARG; 452 return PLIST_ERR_INVALID_ARG;
452 } 453 }
454
455 if (hash_table_lookup(visited, node)) {
456 PLIST_XML_WRITE_ERR("circular reference detected\n");
457 return PLIST_ERR_CIRCULAR_REF;
458 }
459
460 // mark as visited
461 hash_table_insert(visited, node, (void*)1);
462
453 data = plist_get_data(node); 463 data = plist_get_data(node);
454 if (node->children) { 464 if (node->children) {
455 node_t ch; 465 node_t ch;
456 for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) { 466 for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) {
457 node_estimate_size(ch, size, depth + 1); 467 plist_err_t err = _node_estimate_size(ch, size, depth + 1, visited);
468 if (err != PLIST_ERR_SUCCESS) {
469 return err;
470 }
458 } 471 }
459 switch (data->type) { 472 switch (data->type) {
460 case PLIST_DICT: 473 case PLIST_DICT:
@@ -529,6 +542,15 @@ static plist_err_t node_estimate_size(node_t node, uint64_t *size, uint32_t dept
529 return PLIST_ERR_SUCCESS; 542 return PLIST_ERR_SUCCESS;
530} 543}
531 544
545static plist_err_t node_estimate_size(node_t node, uint64_t *size, uint32_t depth)
546{
547 hashtable_t *visited = hash_table_new(plist_node_ptr_hash, plist_node_ptr_compare, NULL);
548 if (!visited) return PLIST_ERR_NO_MEM;
549 plist_err_t err = _node_estimate_size(node, size, depth, visited);
550 hash_table_destroy(visited);
551 return err;
552}
553
532plist_err_t plist_to_xml(plist_t plist, char **plist_xml, uint32_t * length) 554plist_err_t plist_to_xml(plist_t plist, char **plist_xml, uint32_t * length)
533{ 555{
534 uint64_t size = 0; 556 uint64_t size = 0;