diff options
Diffstat (limited to 'src/xplist.c')
| -rw-r--r-- | src/xplist.c | 26 |
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 | ||
| 447 | static plist_err_t node_estimate_size(node_t node, uint64_t *size, uint32_t depth) | 448 | static 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 | ||
| 545 | static 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 | |||
| 532 | plist_err_t plist_to_xml(plist_t plist, char **plist_xml, uint32_t * length) | 554 | plist_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; |
