diff options
Diffstat (limited to 'src/oplist.c')
| -rw-r--r-- | src/oplist.c | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/src/oplist.c b/src/oplist.c index 277693f..680873c 100644 --- a/src/oplist.c +++ b/src/oplist.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | 37 | ||
| 38 | #include "plist.h" | 38 | #include "plist.h" |
| 39 | #include "strbuf.h" | 39 | #include "strbuf.h" |
| 40 | #include "hashtable.h" | ||
| 40 | 41 | ||
| 41 | #ifdef DEBUG | 42 | #ifdef DEBUG |
| 42 | static int plist_ostep_debug = 0; | 43 | static int plist_ostep_debug = 0; |
| @@ -359,18 +360,27 @@ static int num_digits_u(uint64_t i) | |||
| 359 | return n; | 360 | return n; |
| 360 | } | 361 | } |
| 361 | 362 | ||
| 362 | static plist_err_t node_estimate_size(node_t node, uint64_t *size, uint32_t depth, int prettify) | 363 | static plist_err_t _node_estimate_size(node_t node, uint64_t *size, uint32_t depth, int prettify, hashtable_t *visited) |
| 363 | { | 364 | { |
| 364 | plist_data_t data; | 365 | plist_data_t data; |
| 365 | if (!node) { | 366 | if (!node) { |
| 366 | return PLIST_ERR_INVALID_ARG; | 367 | return PLIST_ERR_INVALID_ARG; |
| 367 | } | 368 | } |
| 369 | |||
| 370 | if (hash_table_lookup(visited, node)) { | ||
| 371 | PLIST_OSTEP_WRITE_ERR("circular reference detected\n"); | ||
| 372 | return PLIST_ERR_CIRCULAR_REF; | ||
| 373 | } | ||
| 374 | |||
| 375 | // mark as visited | ||
| 376 | hash_table_insert(visited, node, (void*)1); | ||
| 377 | |||
| 368 | data = plist_get_data(node); | 378 | data = plist_get_data(node); |
| 369 | if (node->children) { | 379 | if (node->children) { |
| 370 | node_t ch; | 380 | node_t ch; |
| 371 | unsigned int n_children = node_n_children(node); | 381 | unsigned int n_children = node_n_children(node); |
| 372 | for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) { | 382 | for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) { |
| 373 | plist_err_t res = node_estimate_size(ch, size, depth + 1, prettify); | 383 | plist_err_t res = _node_estimate_size(ch, size, depth + 1, prettify, visited); |
| 374 | if (res < 0) { | 384 | if (res < 0) { |
| 375 | return res; | 385 | return res; |
| 376 | } | 386 | } |
| @@ -446,6 +456,15 @@ static plist_err_t node_estimate_size(node_t node, uint64_t *size, uint32_t dept | |||
| 446 | return PLIST_ERR_SUCCESS; | 456 | return PLIST_ERR_SUCCESS; |
| 447 | } | 457 | } |
| 448 | 458 | ||
| 459 | static plist_err_t node_estimate_size(node_t node, uint64_t *size, uint32_t depth, int prettify) | ||
| 460 | { | ||
| 461 | hashtable_t *visited = hash_table_new(plist_node_ptr_hash, plist_node_ptr_compare, NULL); | ||
| 462 | if (!visited) return PLIST_ERR_NO_MEM; | ||
| 463 | plist_err_t err = _node_estimate_size(node, size, depth, prettify, visited); | ||
| 464 | hash_table_destroy(visited); | ||
| 465 | return err; | ||
| 466 | } | ||
| 467 | |||
| 449 | plist_err_t plist_to_openstep(plist_t plist, char **openstep, uint32_t* length, int prettify) | 468 | plist_err_t plist_to_openstep(plist_t plist, char **openstep, uint32_t* length, int prettify) |
| 450 | { | 469 | { |
| 451 | uint64_t size = 0; | 470 | uint64_t size = 0; |
