diff options
Diffstat (limited to 'src/out-limd.c')
| -rw-r--r-- | src/out-limd.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/src/out-limd.c b/src/out-limd.c index 7d861f8..e281644 100644 --- a/src/out-limd.c +++ b/src/out-limd.c | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | #include "strbuf.h" | 40 | #include "strbuf.h" |
| 41 | #include "time64.h" | 41 | #include "time64.h" |
| 42 | #include "base64.h" | 42 | #include "base64.h" |
| 43 | #include "hashtable.h" | ||
| 43 | 44 | ||
| 44 | #define MAC_EPOCH 978307200 | 45 | #define MAC_EPOCH 978307200 |
| 45 | 46 | ||
| @@ -278,19 +279,30 @@ static int num_digits_u(uint64_t i) | |||
| 278 | return n; | 279 | return n; |
| 279 | } | 280 | } |
| 280 | 281 | ||
| 281 | static plist_err_t node_estimate_size(node_t node, uint64_t *size, uint32_t depth, uint32_t indent) | 282 | static plist_err_t _node_estimate_size(node_t node, uint64_t *size, uint32_t depth, uint32_t indent, hashtable_t *visited) |
| 282 | { | 283 | { |
| 283 | plist_data_t data; | 284 | plist_data_t data; |
| 284 | if (!node) { | 285 | if (!node) { |
| 285 | return PLIST_ERR_INVALID_ARG; | 286 | return PLIST_ERR_INVALID_ARG; |
| 286 | } | 287 | } |
| 288 | |||
| 289 | if (hash_table_lookup(visited, node)) { | ||
| 290 | #if DEBUG | ||
| 291 | fprintf(stderr, "libplist: ERROR: circular reference detected\n"); | ||
| 292 | #endif | ||
| 293 | return PLIST_ERR_CIRCULAR_REF; | ||
| 294 | } | ||
| 295 | |||
| 296 | // mark as visited | ||
| 297 | hash_table_insert(visited, node, (void*)1); | ||
| 298 | |||
| 287 | data = plist_get_data(node); | 299 | data = plist_get_data(node); |
| 288 | if (node->children) { | 300 | if (node->children) { |
| 289 | node_t ch; | 301 | node_t ch; |
| 290 | unsigned int n_children = node_n_children(node); | 302 | unsigned int n_children = node_n_children(node); |
| 291 | for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) { | 303 | for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) { |
| 292 | plist_err_t res = node_estimate_size(ch, size, depth + 1, indent); | 304 | plist_err_t res = _node_estimate_size(ch, size, depth + 1, indent, visited); |
| 293 | if (res < 0) { | 305 | if (res != PLIST_ERR_SUCCESS) { |
| 294 | return res; | 306 | return res; |
| 295 | } | 307 | } |
| 296 | } | 308 | } |
| @@ -359,6 +371,15 @@ static plist_err_t node_estimate_size(node_t node, uint64_t *size, uint32_t dept | |||
| 359 | return PLIST_ERR_SUCCESS; | 371 | return PLIST_ERR_SUCCESS; |
| 360 | } | 372 | } |
| 361 | 373 | ||
| 374 | static plist_err_t node_estimate_size(node_t node, uint64_t *size, uint32_t depth, uint32_t indent) | ||
| 375 | { | ||
| 376 | hashtable_t *visited = hash_table_new(plist_node_ptr_hash, plist_node_ptr_compare, NULL); | ||
| 377 | if (!visited) return PLIST_ERR_NO_MEM; | ||
| 378 | plist_err_t err = _node_estimate_size(node, size, depth, indent, visited); | ||
| 379 | hash_table_destroy(visited); | ||
| 380 | return err; | ||
| 381 | } | ||
| 382 | |||
| 362 | static plist_err_t _plist_write_to_strbuf(plist_t plist, strbuf_t *outbuf, plist_write_options_t options) | 383 | static plist_err_t _plist_write_to_strbuf(plist_t plist, strbuf_t *outbuf, plist_write_options_t options) |
| 363 | { | 384 | { |
| 364 | uint8_t indent = 0; | 385 | uint8_t indent = 0; |
