summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGravatar Nikias Bassen2018-12-23 02:38:20 +0100
committerGravatar Nikias Bassen2018-12-23 02:38:20 +0100
commit3f967317479acc4b98594b4b86a2787cbd2aa1f1 (patch)
treeb2510557f854f522c117d2e067f414d01a0cc3c1 /src
parent92e5c858c246f3a01104f511c23217fd75c272f4 (diff)
downloadlibplist-3f967317479acc4b98594b4b86a2787cbd2aa1f1.tar.gz
libplist-3f967317479acc4b98594b4b86a2787cbd2aa1f1.tar.bz2
plist: Improve plist_dict_next_item() drastically by iterating on node list directly
As Xiao Deng pointed out in #131, plist_dict_next_item() was very inefficient. For each iteration, node_nth_child() was called with the iterator value, which would walk through the child node list on EVERY iteration. If the dictionary is large this makes things very slow. More than that, after reaching the key node the code was calling node_nth_child() AGAIN (with iterator value + 1) to reach the value node, which would walk through the node list once more. This commit changes the iterator to be a node_t pointer so that the iteration is done on the node list directly.
Diffstat (limited to 'src')
-rw-r--r--src/plist.c18
1 files changed, 8 insertions, 10 deletions
diff --git a/src/plist.c b/src/plist.c
index cd22ca6..6b604d6 100644
--- a/src/plist.c
+++ b/src/plist.c
@@ -471,15 +471,15 @@ PLIST_API void plist_dict_new_iter(plist_t node, plist_dict_iter *iter)
471{ 471{
472 if (iter && *iter == NULL) 472 if (iter && *iter == NULL)
473 { 473 {
474 *iter = malloc(sizeof(uint32_t)); 474 *iter = malloc(sizeof(node_t*));
475 *((uint32_t*)(*iter)) = 0; 475 *((node_t**)(*iter)) = node_first_child(node);
476 } 476 }
477 return; 477 return;
478} 478}
479 479
480PLIST_API void plist_dict_next_item(plist_t node, plist_dict_iter iter, char **key, plist_t *val) 480PLIST_API void plist_dict_next_item(plist_t node, plist_dict_iter iter, char **key, plist_t *val)
481{ 481{
482 uint32_t* iter_int = (uint32_t*) iter; 482 node_t** iter_node = (node_t**)iter;
483 483
484 if (key) 484 if (key)
485 { 485 {
@@ -490,20 +490,18 @@ PLIST_API void plist_dict_next_item(plist_t node, plist_dict_iter iter, char **k
490 *val = NULL; 490 *val = NULL;
491 } 491 }
492 492
493 if (node && PLIST_DICT == plist_get_node_type(node) && *iter_int < node_n_children(node)) 493 if (node && PLIST_DICT == plist_get_node_type(node) && *iter_node)
494 { 494 {
495
496 if (key) 495 if (key)
497 { 496 {
498 plist_get_key_val((plist_t)node_nth_child(node, *iter_int), key); 497 plist_get_key_val((plist_t)(*iter_node), key);
499 } 498 }
500 499 *iter_node = node_next_sibling(*iter_node);
501 if (val) 500 if (val)
502 { 501 {
503 *val = (plist_t) node_nth_child(node, *iter_int + 1); 502 *val = (plist_t)(*iter_node);
504 } 503 }
505 504 *iter_node = node_next_sibling(*iter_node);
506 *iter_int += 2;
507 } 505 }
508 return; 506 return;
509} 507}