LLVMFuzzerTestOneInput:
   26|  2.36k|{
   27|  2.36k|	plist_t root_node = NULL;
   28|  2.36k|	plist_from_json(reinterpret_cast<const char*>(data), size, &root_node);
   29|  2.36k|	plist_free(root_node);
   30|       |
   31|  2.36k|	return 0;
   32|  2.36k|}

node_destroy:
   31|   198k|{
   32|   198k|	if(!node) return;
  ------------------
  |  Branch (32:5): [True: 0, False: 198k]
  ------------------
   33|       |
   34|   198k|	if (node->children && node->children->count > 0) {
  ------------------
  |  Branch (34:6): [True: 30.3k, False: 167k]
  |  Branch (34:24): [True: 0, False: 30.3k]
  ------------------
   35|      0|		node_t ch;
   36|      0|		while ((ch = node->children->begin)) {
  ------------------
  |  Branch (36:10): [True: 0, False: 0]
  ------------------
   37|      0|			node_list_remove(node->children, ch);
   38|      0|			node_destroy(ch);
   39|      0|		}
   40|      0|	}
   41|   198k|	node_list_destroy(node->children);
   42|   198k|	node->children = NULL;
   43|       |
   44|   198k|	free(node);
   45|   198k|}
node_create:
   48|   198k|{
   49|   198k|	int error = 0;
   50|       |
   51|   198k|	node_t node = (node_t)calloc(1, sizeof(struct node));
   52|   198k|	if (node == NULL) {
  ------------------
  |  Branch (52:6): [True: 0, False: 198k]
  ------------------
   53|      0|		return NULL;
   54|      0|	}
   55|       |
   56|   198k|	node->data = data;
   57|   198k|	node->next = NULL;
   58|   198k|	node->prev = NULL;
   59|   198k|	node->count = 0;
   60|   198k|	node->parent = NULL;
   61|   198k|	node->children = NULL;
   62|       |
   63|       |	// Pass NULL to create a root node
   64|   198k|	if (parent != NULL) {
  ------------------
  |  Branch (64:6): [True: 0, False: 198k]
  ------------------
   65|       |		// This is a child node so attach it to it's parent
   66|      0|		error = node_attach(parent, node);
   67|      0|		if (error < 0) {
  ------------------
  |  Branch (67:7): [True: 0, False: 0]
  ------------------
   68|       |			// Unable to attach nodes
   69|      0|			node_destroy(node);
   70|      0|			return NULL;
   71|      0|		}
   72|      0|	}
   73|       |
   74|   198k|	return node;
   75|   198k|}
node_attach:
  133|   188k|{
  134|   188k|	if (!parent || !child) return NODE_ERR_INVALID_ARG;
  ------------------
  |  |   37|      0|#define NODE_ERR_INVALID_ARG  -1
  ------------------
  |  Branch (134:6): [True: 0, False: 188k]
  |  Branch (134:17): [True: 0, False: 188k]
  ------------------
  135|       |
  136|       |	// already parented?
  137|   188k|	if (child->parent) return NODE_ERR_PARENT;
  ------------------
  |  |   39|      0|#define NODE_ERR_PARENT       -3
  ------------------
  |  Branch (137:6): [True: 0, False: 188k]
  ------------------
  138|       |
  139|       |	// self/cycle guard
  140|   188k|	if (parent == child) return NODE_ERR_CIRCULAR_REF;
  ------------------
  |  |   40|      0|#define NODE_ERR_CIRCULAR_REF -4
  ------------------
  |  Branch (140:6): [True: 0, False: 188k]
  ------------------
  141|   188k|	if (would_create_cycle(parent, child)) return NODE_ERR_CIRCULAR_REF;
  ------------------
  |  |   40|      0|#define NODE_ERR_CIRCULAR_REF -4
  ------------------
  |  Branch (141:6): [True: 0, False: 188k]
  ------------------
  142|       |
  143|       |	// depth guard: depth(parent)+1+max_depth(child_subtree) <= NODE_MAX_DEPTH
  144|   188k|	int pd = node_depth_from_root(parent);
  145|   188k|	int cd = node_subtree_max_depth(child);
  146|   188k|	if (pd + 1 + cd > NODE_MAX_DEPTH) {
  ------------------
  |  |   33|   188k|#define NODE_MAX_DEPTH 512
  ------------------
  |  Branch (146:6): [True: 4, False: 188k]
  ------------------
  147|      4|		return NODE_ERR_MAX_DEPTH;
  ------------------
  |  |   41|      4|#define NODE_ERR_MAX_DEPTH    -5
  ------------------
  148|      4|	}
  149|       |
  150|   188k|	if (!parent->children) {
  ------------------
  |  Branch (150:6): [True: 30.3k, False: 158k]
  ------------------
  151|  30.3k|		parent->children = node_list_create();
  152|  30.3k|		if (!parent->children) return NODE_ERR_NO_MEM;
  ------------------
  |  |   38|      0|#define NODE_ERR_NO_MEM       -2
  ------------------
  |  Branch (152:7): [True: 0, False: 30.3k]
  ------------------
  153|  30.3k|	}
  154|   188k|	int res = node_list_add(parent->children, child);
  155|   188k|	if (res == 0) {
  ------------------
  |  Branch (155:6): [True: 188k, False: 0]
  ------------------
  156|   188k|		child->parent = parent;
  157|   188k|		parent->count++;
  158|   188k|	}
  159|   188k|	return res;
  160|   188k|}
node_detach:
  163|   192k|{
  164|   192k|	if (!parent || !child) return NODE_ERR_INVALID_ARG;
  ------------------
  |  |   37|      0|#define NODE_ERR_INVALID_ARG  -1
  ------------------
  |  Branch (164:6): [True: 0, False: 192k]
  |  Branch (164:17): [True: 0, False: 192k]
  ------------------
  165|   192k|	if (!parent->children) return NODE_ERR_NOT_FOUND;
  ------------------
  |  |   42|      0|#define NODE_ERR_NOT_FOUND    -6
  ------------------
  |  Branch (165:6): [True: 0, False: 192k]
  ------------------
  166|   192k|	if (child->parent && child->parent != parent) return NODE_ERR_PARENT;
  ------------------
  |  |   39|      0|#define NODE_ERR_PARENT       -3
  ------------------
  |  Branch (166:6): [True: 192k, False: 0]
  |  Branch (166:23): [True: 0, False: 192k]
  ------------------
  167|       |
  168|   192k|	int node_index = node_list_remove(parent->children, child);
  169|   192k|	if (node_index >= 0) {
  ------------------
  |  Branch (169:6): [True: 192k, False: 0]
  ------------------
  170|   192k|		if (parent->count > 0) parent->count--;
  ------------------
  |  Branch (170:7): [True: 192k, False: 0]
  ------------------
  171|   192k|		child->parent = NULL;
  172|   192k|		child->prev = NULL;
  173|       |		child->next = NULL;
  174|   192k|	}
  175|   192k|	return node_index;
  176|   192k|}
node_insert:
  179|  3.86k|{
  180|  3.86k|	if (!parent || !child) return NODE_ERR_INVALID_ARG;
  ------------------
  |  |   37|      0|#define NODE_ERR_INVALID_ARG  -1
  ------------------
  |  Branch (180:6): [True: 0, False: 3.86k]
  |  Branch (180:17): [True: 0, False: 3.86k]
  ------------------
  181|       |
  182|       |	// already parented?
  183|  3.86k|	if (child->parent) return NODE_ERR_PARENT;
  ------------------
  |  |   39|      0|#define NODE_ERR_PARENT       -3
  ------------------
  |  Branch (183:6): [True: 0, False: 3.86k]
  ------------------
  184|       |
  185|       |	// self/cycle guard
  186|  3.86k|	if (parent == child) return NODE_ERR_CIRCULAR_REF;
  ------------------
  |  |   40|      0|#define NODE_ERR_CIRCULAR_REF -4
  ------------------
  |  Branch (186:6): [True: 0, False: 3.86k]
  ------------------
  187|  3.86k|	if (would_create_cycle(parent, child)) return NODE_ERR_CIRCULAR_REF;
  ------------------
  |  |   40|      0|#define NODE_ERR_CIRCULAR_REF -4
  ------------------
  |  Branch (187:6): [True: 0, False: 3.86k]
  ------------------
  188|       |
  189|       |	// depth guard: depth(parent)+1+max_depth(child_subtree) <= NODE_MAX_DEPTH
  190|  3.86k|	int pd = node_depth_from_root(parent);
  191|  3.86k|	int cd = node_subtree_max_depth(child);
  192|  3.86k|	if (pd + 1 + cd > NODE_MAX_DEPTH) {
  ------------------
  |  |   33|  3.86k|#define NODE_MAX_DEPTH 512
  ------------------
  |  Branch (192:6): [True: 3, False: 3.86k]
  ------------------
  193|      3|		return NODE_ERR_MAX_DEPTH;
  ------------------
  |  |   41|      3|#define NODE_ERR_MAX_DEPTH    -5
  ------------------
  194|      3|	}
  195|       |
  196|  3.86k|	if (!parent->children) {
  ------------------
  |  Branch (196:6): [True: 0, False: 3.86k]
  ------------------
  197|      0|		parent->children = node_list_create();
  198|      0|		if (!parent->children) return NODE_ERR_NO_MEM;
  ------------------
  |  |   38|      0|#define NODE_ERR_NO_MEM       -2
  ------------------
  |  Branch (198:7): [True: 0, False: 0]
  ------------------
  199|      0|	}
  200|  3.86k|	int res = node_list_insert(parent->children, node_index, child);
  201|  3.86k|	if (res == 0) {
  ------------------
  |  Branch (201:6): [True: 3.86k, False: 0]
  ------------------
  202|  3.86k|		child->parent = parent;
  203|  3.86k|		parent->count++;
  204|  3.86k|	}
  205|  3.86k|	return res;
  206|  3.86k|}
node_first_child:
  262|  5.48M|{
  263|  5.48M|	if (!node || !node->children) return NULL;
  ------------------
  |  Branch (263:6): [True: 0, False: 5.48M]
  |  Branch (263:15): [True: 169k, False: 5.31M]
  ------------------
  264|  5.31M|	return node->children->begin;
  265|  5.48M|}
node_prev_sibling:
  268|  3.86k|{
  269|  3.86k|	if (!node) return NULL;
  ------------------
  |  Branch (269:6): [True: 0, False: 3.86k]
  ------------------
  270|  3.86k|	return node->prev;
  271|  3.86k|}
node_next_sibling:
  274|  21.1M|{
  275|  21.1M|	if (!node) return NULL;
  ------------------
  |  Branch (275:6): [True: 0, False: 21.1M]
  ------------------
  276|  21.1M|	return node->next;
  277|  21.1M|}
node.c:would_create_cycle:
  124|   192k|{
  125|       |	// if parent is anywhere in child's ancestor chain => cycle
  126|   384k|	for (node_t p = parent; p; p = p->parent) {
  ------------------
  |  Branch (126:26): [True: 192k, False: 192k]
  ------------------
  127|   192k|		if (p == child) return 1;
  ------------------
  |  Branch (127:7): [True: 0, False: 192k]
  ------------------
  128|   192k|	}
  129|   192k|	return 0;
  130|   192k|}
node.c:node_depth_from_root:
   78|   192k|{
   79|   192k|	int d = 0;
   80|   192k|	while (n && n->parent) {
  ------------------
  |  Branch (80:9): [True: 192k, False: 0]
  |  Branch (80:14): [True: 0, False: 192k]
  ------------------
   81|      0|		d++;
   82|      0|		n = n->parent;
   83|      0|		if (d > NODE_MAX_DEPTH) return d; // early out
  ------------------
  |  |   33|      0|#define NODE_MAX_DEPTH 512
  ------------------
  |  Branch (83:7): [True: 0, False: 0]
  ------------------
   84|      0|	}
   85|   192k|	return d;
   86|   192k|}
node.c:node_subtree_max_depth:
   89|   192k|{
   90|   192k|	if (!root) return 0;
  ------------------
  |  Branch (90:6): [True: 0, False: 192k]
  ------------------
   91|       |
   92|   192k|	typedef struct { node_t n; int depth; } frame_t;
   93|   192k|	size_t cap = 64, sp = 0;
   94|   192k|	frame_t *st = (frame_t*)malloc(cap * sizeof(*st));
   95|   192k|	if (!st) return NODE_MAX_DEPTH + 1;
  ------------------
  |  |   33|      0|#define NODE_MAX_DEPTH 512
  ------------------
  |  Branch (95:6): [True: 0, False: 192k]
  ------------------
   96|       |
   97|   192k|	st[sp++] = (frame_t){ root, 0 };
   98|   192k|	int maxd = 0;
   99|       |
  100|  5.81M|	while (sp) {
  ------------------
  |  Branch (100:9): [True: 5.62M, False: 192k]
  ------------------
  101|  5.62M|		frame_t f = st[--sp];
  102|  5.62M|		if (f.depth > maxd) maxd = f.depth;
  ------------------
  |  Branch (102:7): [True: 4.77M, False: 855k]
  ------------------
  103|  5.62M|		if (maxd > NODE_MAX_DEPTH) break;
  ------------------
  |  |   33|  5.62M|#define NODE_MAX_DEPTH 512
  ------------------
  |  Branch (103:7): [True: 0, False: 5.62M]
  ------------------
  104|       |
  105|  5.62M|		if (!f.n->children) continue;
  ------------------
  |  Branch (105:7): [True: 600k, False: 5.02M]
  ------------------
  106|       |
  107|  10.4M|		for (node_t ch = node_first_child(f.n); ch; ch = node_next_sibling(ch)) {
  ------------------
  |  Branch (107:43): [True: 5.43M, False: 5.02M]
  ------------------
  108|  5.43M|			if (sp == cap) {
  ------------------
  |  Branch (108:8): [True: 1.90k, False: 5.43M]
  ------------------
  109|  1.90k|				cap *= 2;
  110|  1.90k|				frame_t *tmp = (frame_t*)realloc(st, cap * sizeof(*st));
  111|  1.90k|				if (!tmp) { maxd = NODE_MAX_DEPTH + 1; goto out; }
  ------------------
  |  |   33|      0|#define NODE_MAX_DEPTH 512
  ------------------
  |  Branch (111:9): [True: 0, False: 1.90k]
  ------------------
  112|  1.90k|				st = tmp;
  113|  1.90k|			}
  114|  5.43M|			st[sp++] = (frame_t){ ch, f.depth + 1 };
  115|  5.43M|		}
  116|  5.02M|	}
  117|       |
  118|   192k|out:
  119|   192k|	free(st);
  120|   192k|	return maxd;
  121|   192k|}

node_list_destroy:
   32|   198k|{
   33|   198k|	free(list);
   34|   198k|}
node_list_create:
   37|  30.3k|{
   38|  30.3k|	node_list_t list = (node_list_t)calloc(1, sizeof(struct node_list));
   39|  30.3k|	if (list == NULL) {
  ------------------
  |  Branch (39:6): [True: 0, False: 30.3k]
  ------------------
   40|      0|		return NULL;
   41|      0|	}
   42|       |
   43|       |	// Initialize structure
   44|  30.3k|	list->begin = NULL;
   45|       |	list->end = NULL;
   46|  30.3k|	list->count = 0;
   47|  30.3k|	return list;
   48|  30.3k|}
node_list_add:
   51|   191k|{
   52|   191k|	if (!list || !node) return NODE_ERR_INVALID_ARG;
  ------------------
  |  |   37|      0|#define NODE_ERR_INVALID_ARG  -1
  ------------------
  |  Branch (52:6): [True: 0, False: 191k]
  |  Branch (52:15): [True: 0, False: 191k]
  ------------------
   53|       |
   54|       |	// Find the last element in the list
   55|   191k|	node_t last = list->end;
   56|       |
   57|       |	// Setup our new node as the new last element
   58|   191k|	node->next = NULL;
   59|   191k|	node->prev = last;
   60|       |
   61|       |	// Set the next element of our old "last" element
   62|   191k|	if (last) {
  ------------------
  |  Branch (62:6): [True: 161k, False: 30.3k]
  ------------------
   63|       |		// but only if the node list is not empty
   64|   161k|		last->next = node;
   65|   161k|	} else {
   66|       |		// otherwise this is the start of the list
   67|  30.3k|		list->begin = node;
   68|  30.3k|	}
   69|       |
   70|       |	// Set the lists prev to the new last element
   71|   191k|	list->end = node;
   72|       |
   73|       |	// Increment our node count for this list
   74|   191k|	list->count++;
   75|   191k|	return NODE_ERR_SUCCESS;
  ------------------
  |  |   36|   191k|#define NODE_ERR_SUCCESS       0
  ------------------
   76|   191k|}
node_list_insert:
   79|  3.86k|{
   80|  3.86k|	if (!list || !node) return NODE_ERR_INVALID_ARG;
  ------------------
  |  |   37|      0|#define NODE_ERR_INVALID_ARG  -1
  ------------------
  |  Branch (80:6): [True: 0, False: 3.86k]
  |  Branch (80:15): [True: 0, False: 3.86k]
  ------------------
   81|  3.86k|	if (node_index > list->count) return NODE_ERR_INVALID_ARG;
  ------------------
  |  |   37|      0|#define NODE_ERR_INVALID_ARG  -1
  ------------------
  |  Branch (81:6): [True: 0, False: 3.86k]
  ------------------
   82|  3.86k|	if (node_index == list->count) {
  ------------------
  |  Branch (82:6): [True: 3.01k, False: 845]
  ------------------
   83|  3.01k|		return node_list_add(list, node);
   84|  3.01k|	}
   85|       |
   86|       |	// Get the first element in the list
   87|    845|	node_t cur = list->begin;
   88|    845|	node_t prev = NULL;
   89|       |
   90|  80.2k|	for (unsigned int pos = 0; pos < node_index; pos++) {
  ------------------
  |  Branch (90:29): [True: 79.4k, False: 845]
  ------------------
   91|  79.4k|		if (!cur) return NODE_ERR_INVALID_ARG;
  ------------------
  |  |   37|      0|#define NODE_ERR_INVALID_ARG  -1
  ------------------
  |  Branch (91:7): [True: 0, False: 79.4k]
  ------------------
   92|  79.4k|		prev = cur;
   93|  79.4k|		cur = cur->next;
   94|  79.4k|	}
   95|       |
   96|       |	// insert node before cur
   97|    845|	node->prev = prev;
   98|    845|	node->next = cur;
   99|       |
  100|    845|	if (prev) {
  ------------------
  |  Branch (100:6): [True: 845, False: 0]
  ------------------
  101|    845|		prev->next = node;
  102|    845|	} else {
  103|      0|		list->begin = node;
  104|      0|	}
  105|       |
  106|    845|	if (cur) {
  ------------------
  |  Branch (106:6): [True: 845, False: 0]
  ------------------
  107|    845|		cur->prev = node;
  108|    845|	} else {
  109|       |		// should not happen with bounds above, but keeps things consistent
  110|      0|		list->end = node;
  111|      0|	}
  112|       |
  113|       |	// Increment our node count for this list
  114|    845|	list->count++;
  115|    845|	return NODE_ERR_SUCCESS;
  ------------------
  |  |   36|    845|#define NODE_ERR_SUCCESS       0
  ------------------
  116|    845|}
node_list_remove:
  120|   192k|{
  121|   192k|	if (!list || !node) return NODE_ERR_INVALID_ARG;
  ------------------
  |  |   37|      0|#define NODE_ERR_INVALID_ARG  -1
  ------------------
  |  Branch (121:6): [True: 0, False: 192k]
  |  Branch (121:15): [True: 0, False: 192k]
  ------------------
  122|   192k|	if (list->count == 0) return NODE_ERR_NOT_FOUND;
  ------------------
  |  |   42|      0|#define NODE_ERR_NOT_FOUND    -6
  ------------------
  |  Branch (122:6): [True: 0, False: 192k]
  ------------------
  123|       |
  124|   192k|	int node_index = 0;
  125|   279k|	for (node_t n = list->begin; n; n = n->next, node_index++) {
  ------------------
  |  Branch (125:31): [True: 279k, False: 0]
  ------------------
  126|   279k|		if (node != n) continue;
  ------------------
  |  Branch (126:7): [True: 87.6k, False: 192k]
  ------------------
  127|       |
  128|   192k|		node_t newnode = node->next;
  129|   192k|		if (node->prev) {
  ------------------
  |  Branch (129:7): [True: 3.86k, False: 188k]
  ------------------
  130|  3.86k|			node->prev->next = newnode;
  131|   188k|		} else {
  132|       |			// we just removed the first element
  133|   188k|			list->begin = newnode;
  134|   188k|		}
  135|       |
  136|   192k|		if (newnode) {
  ------------------
  |  Branch (136:7): [True: 158k, False: 33.3k]
  ------------------
  137|   158k|			newnode->prev = node->prev;
  138|   158k|		} else {
  139|       |			// we removed the last element, set new end
  140|  33.3k|			list->end = node->prev;
  141|  33.3k|		}
  142|       |
  143|       |		// fully detach node from list
  144|   192k|		node->prev = NULL;
  145|   192k|		node->next = NULL;
  146|       |
  147|   192k|		list->count--;
  148|   192k|		return node_index;
  149|   279k|	}
  150|      0|	return NODE_ERR_NOT_FOUND;
  ------------------
  |  |   42|      0|#define NODE_ERR_NOT_FOUND    -6
  ------------------
  151|   192k|}

plist_bin_init:
  254|      2|{
  255|       |    /* init binary plist stuff */
  256|      2|#ifdef DEBUG
  257|      2|    char *env_debug = getenv("PLIST_BIN_DEBUG");
  258|      2|    if (env_debug && !strcmp(env_debug, "1")) {
  ------------------
  |  Branch (258:9): [True: 0, False: 2]
  |  Branch (258:22): [True: 0, False: 0]
  ------------------
  259|      0|        plist_bin_debug = 1;
  260|      0|    }
  261|      2|#endif
  262|      2|}

hash_table_new:
   24|    240|{
   25|    240|	hashtable_t* ht = (hashtable_t*)malloc(sizeof(hashtable_t));
   26|    240|	int i;
   27|   983k|	for (i = 0; i < 4096; i++) {
  ------------------
  |  Branch (27:14): [True: 983k, False: 240]
  ------------------
   28|       |		ht->entries[i] = NULL;
   29|   983k|	}
   30|    240|	ht->count = 0;
   31|    240|	ht->hash_func = hash_func;
   32|    240|	ht->compare_func = compare_func;
   33|    240|	ht->free_func = free_func;
   34|    240|	return ht;
   35|    240|}
hash_table_destroy:
   38|  12.7k|{
   39|  12.7k|	if (!ht) return;
  ------------------
  |  Branch (39:6): [True: 12.5k, False: 240]
  ------------------
   40|       |
   41|    240|	int i = 0;
   42|   983k|	for (i = 0; i < 4096; i++) {
  ------------------
  |  Branch (42:14): [True: 983k, False: 240]
  ------------------
   43|   983k|		if (ht->entries[i]) {
  ------------------
  |  Branch (43:7): [True: 59.4k, False: 923k]
  ------------------
   44|  59.4k|			hashentry_t* e = ht->entries[i];
   45|   120k|			while (e) {
  ------------------
  |  Branch (45:11): [True: 60.6k, False: 59.4k]
  ------------------
   46|  60.6k|				if (ht->free_func) {
  ------------------
  |  Branch (46:9): [True: 0, False: 60.6k]
  ------------------
   47|      0|					ht->free_func(e->value);
   48|      0|				}
   49|  60.6k|				hashentry_t* old = e;
   50|  60.6k|				e = e->next;
   51|  60.6k|				free(old);
   52|  60.6k|			}
   53|  59.4k|		}
   54|   983k|	}
   55|    240|	free(ht);
   56|    240|}
hash_table_insert:
   59|  61.1k|{
   60|  61.1k|	if (!ht || !key) return;
  ------------------
  |  Branch (60:6): [True: 0, False: 61.1k]
  |  Branch (60:13): [True: 0, False: 61.1k]
  ------------------
   61|       |
   62|  61.1k|	unsigned int hash = ht->hash_func(key);
   63|       |
   64|  61.1k|	int idx0 = hash & 0xFFF;
   65|       |
   66|       |	// get the idx0 list
   67|  61.1k|	hashentry_t* e = ht->entries[idx0];
   68|  63.0k|	while (e) {
  ------------------
  |  Branch (68:9): [True: 2.41k, False: 60.6k]
  ------------------
   69|  2.41k|		if (ht->compare_func(e->key, key)) {
  ------------------
  |  Branch (69:7): [True: 565, False: 1.85k]
  ------------------
   70|       |			// element already present. replace value.
   71|    565|			e->value = value;
   72|    565|			return;
   73|    565|		}
   74|  1.85k|		e = e->next;
   75|  1.85k|	}
   76|       |
   77|       |	// if we get here, the element is not yet in the list.
   78|       |
   79|       |	// make a new entry.
   80|  60.6k|	hashentry_t* entry = (hashentry_t*)malloc(sizeof(hashentry_t));
   81|  60.6k|	entry->key = key;
   82|  60.6k|	entry->value = value;
   83|  60.6k|	if (!ht->entries[idx0]) {
  ------------------
  |  Branch (83:6): [True: 59.4k, False: 1.21k]
  ------------------
   84|       |		// first entry
   85|  59.4k|		entry->next = NULL;
   86|  59.4k|	} else {
   87|       |		// add to list
   88|  1.21k|		entry->next = ht->entries[idx0];
   89|  1.21k|	}
   90|  60.6k|	ht->entries[idx0] = entry;
   91|  60.6k|	ht->count++;
   92|  60.6k|}
hash_table_lookup:
   95|    955|{
   96|    955|	if (!ht || !key) return NULL;
  ------------------
  |  Branch (96:6): [True: 0, False: 955]
  |  Branch (96:13): [True: 0, False: 955]
  ------------------
   97|    955|	unsigned int hash = ht->hash_func(key);
   98|       |
   99|    955|	int idx0 = hash & 0xFFF;
  100|       |
  101|    955|	hashentry_t* e = ht->entries[idx0];
  102|  1.42k|	while (e) {
  ------------------
  |  Branch (102:9): [True: 1.03k, False: 390]
  ------------------
  103|  1.03k|		if (ht->compare_func(e->key, key)) {
  ------------------
  |  Branch (103:7): [True: 565, False: 471]
  ------------------
  104|    565|			return e->value;
  105|    565|		}
  106|    471|		e = e->next;
  107|    471|	}
  108|    390|	return NULL;
  109|    955|}

plist_json_init:
   56|      2|{
   57|       |    /* init JSON stuff */
   58|      2|#ifdef DEBUG
   59|      2|    char *env_debug = getenv("PLIST_JSON_DEBUG");
   60|      2|    if (env_debug && !strcmp(env_debug, "1")) {
  ------------------
  |  Branch (60:9): [True: 0, False: 2]
  |  Branch (60:22): [True: 0, False: 0]
  ------------------
   61|      0|        plist_json_debug = 1;
   62|      0|    }
   63|      2|#endif
   64|      2|}
plist_from_json:
  897|  2.36k|{
  898|  2.36k|    if (!plist) {
  ------------------
  |  Branch (898:9): [True: 0, False: 2.36k]
  ------------------
  899|      0|        return PLIST_ERR_INVALID_ARG;
  900|      0|    }
  901|  2.36k|    *plist = NULL;
  902|  2.36k|    if (!json || (length == 0)) {
  ------------------
  |  Branch (902:9): [True: 0, False: 2.36k]
  |  Branch (902:18): [True: 0, False: 2.36k]
  ------------------
  903|      0|        return PLIST_ERR_INVALID_ARG;
  904|      0|    }
  905|       |
  906|  2.36k|    jsmn_parser parser;
  907|  2.36k|    jsmn_init(&parser);
  908|  2.36k|    unsigned int maxtoks = 256;
  909|  2.36k|    unsigned int curtoks = 0;
  910|  2.36k|    int r = 0;
  911|  2.36k|    jsmntok_t *tokens = NULL;
  912|       |
  913|  13.3k|    do {
  914|  13.3k|        jsmntok_t* newtokens = (jsmntok_t*)realloc(tokens, sizeof(jsmntok_t)*maxtoks);
  915|  13.3k|        if (!newtokens) {
  ------------------
  |  Branch (915:13): [True: 0, False: 13.3k]
  ------------------
  916|      0|            free(tokens);
  917|      0|            PLIST_JSON_ERR("%s: Out of memory\n", __func__);
  ------------------
  |  |   48|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  918|      0|            return PLIST_ERR_NO_MEM;
  919|      0|        }
  920|  13.3k|        memset((unsigned char*)newtokens + sizeof(jsmntok_t)*curtoks, '\0', sizeof(jsmntok_t)*(maxtoks-curtoks));
  921|  13.3k|        tokens = newtokens;
  922|  13.3k|        curtoks = maxtoks;
  923|       |
  924|  13.3k|        r = jsmn_parse(&parser, json, length, tokens, maxtoks);
  925|  13.3k|        if (r == JSMN_ERROR_NOMEM) {
  ------------------
  |  Branch (925:13): [True: 11.0k, False: 2.36k]
  ------------------
  926|  11.0k|            if (maxtoks > (unsigned int)INT_MAX - 16) {
  ------------------
  |  Branch (926:17): [True: 0, False: 11.0k]
  ------------------
  927|      0|                free(tokens);
  928|      0|                return PLIST_ERR_NO_MEM;
  929|      0|            }
  930|  11.0k|            maxtoks+=16;
  931|  11.0k|            continue;
  932|  11.0k|        } else if (r < 0) {
  ------------------
  |  Branch (932:20): [True: 386, False: 1.97k]
  ------------------
  933|    386|            break;
  934|    386|        }
  935|  13.3k|    } while (r == JSMN_ERROR_NOMEM);
  ------------------
  |  Branch (935:14): [True: 11.0k, False: 1.97k]
  ------------------
  936|       |
  937|  2.36k|    switch(r) {
  938|      0|        case JSMN_ERROR_NOMEM:
  ------------------
  |  Branch (938:9): [True: 0, False: 2.36k]
  ------------------
  939|      0|            PLIST_JSON_ERR("%s: Out of memory...\n", __func__);
  ------------------
  |  |   48|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  940|      0|            free(tokens);
  941|      0|            return PLIST_ERR_NO_MEM;
  942|     69|        case JSMN_ERROR_INVAL:
  ------------------
  |  Branch (942:9): [True: 69, False: 2.29k]
  ------------------
  943|     69|            PLIST_JSON_ERR("%s: Invalid character inside JSON string\n", __func__);
  ------------------
  |  |   48|     69|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 69]
  |  |  ------------------
  ------------------
  944|     69|            free(tokens);
  945|     69|            return PLIST_ERR_PARSE;
  946|    317|        case JSMN_ERROR_PART:
  ------------------
  |  Branch (946:9): [True: 317, False: 2.04k]
  ------------------
  947|    317|            PLIST_JSON_ERR("%s: Incomplete JSON, more bytes expected\n", __func__);
  ------------------
  |  |   48|    317|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 317]
  |  |  ------------------
  ------------------
  948|    317|            free(tokens);
  949|    317|            return PLIST_ERR_PARSE;
  950|      0|        case JSMN_ERROR_LIMIT:
  ------------------
  |  Branch (950:9): [True: 0, False: 2.36k]
  ------------------
  951|      0|            PLIST_JSON_ERR("%s: Input data too large\n", __func__);
  ------------------
  |  |   48|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  952|      0|            free(tokens);
  953|      0|            return PLIST_ERR_PARSE;
  954|  1.97k|        default:
  ------------------
  |  Branch (954:9): [True: 1.97k, False: 386]
  ------------------
  955|  1.97k|            break;
  956|  2.36k|    }
  957|       |
  958|  1.97k|    int startindex = 0;
  959|  1.97k|    jsmntok_info_t ti = { tokens, parser.toknext, PLIST_ERR_SUCCESS };
  960|  1.97k|    switch (tokens[startindex].type) {
  961|    711|        case JSMN_PRIMITIVE:
  ------------------
  |  Branch (961:9): [True: 711, False: 1.26k]
  ------------------
  962|    711|            *plist = parse_primitive(json, &ti, &startindex);
  963|    711|            break;
  964|    192|        case JSMN_STRING:
  ------------------
  |  Branch (964:9): [True: 192, False: 1.78k]
  ------------------
  965|    192|            *plist = parse_string(json, &ti, &startindex);
  966|    192|            break;
  967|    456|        case JSMN_ARRAY:
  ------------------
  |  Branch (967:9): [True: 456, False: 1.52k]
  ------------------
  968|    456|            *plist = parse_array(json, &ti, &startindex, 0);
  969|    456|            break;
  970|    617|        case JSMN_OBJECT:
  ------------------
  |  Branch (970:9): [True: 617, False: 1.35k]
  ------------------
  971|    617|            *plist = parse_object(json, &ti, &startindex, 0);
  972|    617|            break;
  973|      0|        default:
  ------------------
  |  Branch (973:9): [True: 0, False: 1.97k]
  ------------------
  974|      0|            break;
  975|  1.97k|    }
  976|  1.97k|    free(tokens);
  977|  1.97k|    if (!*plist) {
  ------------------
  |  Branch (977:9): [True: 467, False: 1.50k]
  ------------------
  978|    467|        return (ti.err != PLIST_ERR_SUCCESS) ? ti.err : PLIST_ERR_PARSE;
  ------------------
  |  Branch (978:16): [True: 127, False: 340]
  ------------------
  979|    467|    }
  980|  1.50k|    return PLIST_ERR_SUCCESS;
  981|  1.97k|}
jplist.c:parse_primitive:
  545|  27.9k|{
  546|  27.9k|    if (ti->tokens[*index].type != JSMN_PRIMITIVE) {
  ------------------
  |  Branch (546:9): [True: 0, False: 27.9k]
  ------------------
  547|      0|        PLIST_JSON_ERR("%s: token type != JSMN_PRIMITIVE\n", __func__);
  ------------------
  |  |   48|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  548|      0|        return NULL;
  549|      0|    }
  550|  27.9k|    plist_t val = NULL;
  551|  27.9k|    const char* str_val = js + ti->tokens[*index].start;
  552|  27.9k|    const char* str_end = js + ti->tokens[*index].end;
  553|  27.9k|    size_t str_len = ti->tokens[*index].end - ti->tokens[*index].start;
  554|  27.9k|    if (!strncmp("false", str_val, str_len)) {
  ------------------
  |  Branch (554:9): [True: 5.34k, False: 22.5k]
  ------------------
  555|  5.34k|        val = plist_new_bool(0);
  556|  22.5k|    } else if (!strncmp("true", str_val, str_len)) {
  ------------------
  |  Branch (556:16): [True: 3.21k, False: 19.3k]
  ------------------
  557|  3.21k|        val = plist_new_bool(1);
  558|  19.3k|    } else if (!strncmp("null", str_val, str_len)) {
  ------------------
  |  Branch (558:16): [True: 12.5k, False: 6.80k]
  ------------------
  559|  12.5k|        plist_data_t data = plist_new_plist_data();
  560|  12.5k|        if (!data) {
  ------------------
  |  Branch (560:13): [True: 0, False: 12.5k]
  ------------------
  561|      0|            PLIST_JSON_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |   48|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  562|      0|            return NULL;
  563|      0|        }
  564|  12.5k|        data->type = PLIST_NULL;
  565|  12.5k|        val = plist_new_node(data);
  566|  12.5k|    } else if (isdigit(str_val[0]) || (str_val[0] == '-' && str_val+1 < str_end && isdigit(str_val[1]))) {
  ------------------
  |  Branch (566:16): [True: 5.48k, False: 1.32k]
  |  Branch (566:40): [True: 1.17k, False: 150]
  |  Branch (566:61): [True: 1.16k, False: 3]
  |  Branch (566:84): [True: 1.16k, False: 6]
  ------------------
  567|  6.64k|        char* endp = (char*)str_val;
  568|  6.64k|        int is_neg = (str_val[0] == '-');
  569|  6.64k|        int64_t intpart = parse_decimal(str_val, str_end, &endp);
  570|  6.64k|        if (endp >= str_end) {
  ------------------
  |  Branch (570:13): [True: 4.18k, False: 2.46k]
  ------------------
  571|       |            /* integer */
  572|  4.18k|            if (is_neg || intpart <= INT64_MAX) {
  ------------------
  |  Branch (572:17): [True: 899, False: 3.28k]
  |  Branch (572:27): [True: 3.28k, False: 0]
  ------------------
  573|  4.18k|                val = plist_new_int(intpart);
  574|  4.18k|            } else {
  575|      0|                val = plist_new_uint((uint64_t)intpart);
  576|      0|            }
  577|  4.18k|        } else if ((*endp == '.' && endp+1 < str_end && isdigit(*(endp+1))) || ((*endp == 'e' || *endp == 'E') && endp+1 < str_end && (isdigit(*(endp+1)) || (((*(endp+1) == '-') || (*(endp+1) == '+')) && endp+2 < str_end && isdigit(*(endp+2)))))) {
  ------------------
  |  Branch (577:21): [True: 551, False: 1.91k]
  |  Branch (577:37): [True: 549, False: 2]
  |  Branch (577:57): [True: 548, False: 1]
  |  Branch (577:82): [True: 1.47k, False: 444]
  |  Branch (577:98): [True: 420, False: 24]
  |  Branch (577:115): [True: 1.87k, False: 15]
  |  Branch (577:136): [True: 707, False: 1.16k]
  |  Branch (577:160): [True: 898, False: 270]
  |  Branch (577:182): [True: 260, False: 10]
  |  Branch (577:205): [True: 1.14k, False: 14]
  |  Branch (577:225): [True: 1.14k, False: 1]
  ------------------
  578|       |            /* floating point */
  579|  2.39k|            double dval = (double)intpart;
  580|  2.39k|            char* fendp = endp;
  581|  2.39k|            int err = 0;
  582|  2.39k|            do {
  583|  2.39k|                if (*endp == '.') {
  ------------------
  |  Branch (583:21): [True: 548, False: 1.85k]
  ------------------
  584|    548|                    fendp++;
  585|    548|                    double frac = 0;
  586|    548|                    double p = 0.1;
  587|  1.39k|                    while (fendp < str_end && isdigit(*fendp)) {
  ------------------
  |  Branch (587:28): [True: 875, False: 523]
  |  Branch (587:47): [True: 850, False: 25]
  ------------------
  588|    850|                        frac = frac + (*fendp - '0') * p;
  589|    850|                        p *= 0.1;
  590|    850|                        fendp++;
  591|    850|                    }
  592|    548|                    if (is_neg) {
  ------------------
  |  Branch (592:25): [True: 241, False: 307]
  ------------------
  593|    241|                        dval -= frac;
  594|    307|                    } else {
  595|    307|                        dval += frac;
  596|    307|                    }
  597|    548|                }
  598|  2.39k|                if (fendp >= str_end) {
  ------------------
  |  Branch (598:21): [True: 523, False: 1.87k]
  ------------------
  599|    523|                    break;
  600|    523|                }
  601|  1.87k|                if (fendp+1 < str_end && (*fendp == 'e' || *fendp == 'E') && (isdigit(*(fendp+1)) || (((*(fendp+1) == '-') || (*(fendp+1) == '+')) && fendp+2 < str_end && isdigit(*(fendp+2))))) {
  ------------------
  |  Branch (601:21): [True: 1.87k, False: 2]
  |  Branch (601:43): [True: 1.45k, False: 421]
  |  Branch (601:60): [True: 407, False: 14]
  |  Branch (601:79): [True: 707, False: 1.15k]
  |  Branch (601:104): [True: 891, False: 261]
  |  Branch (601:127): [True: 254, False: 7]
  |  Branch (601:151): [True: 1.14k, False: 1]
  |  Branch (601:172): [True: 1.14k, False: 1]
  ------------------
  602|  1.85k|                    int64_t exp = parse_decimal(fendp+1, str_end, &fendp);
  603|  1.85k|                    dval = dval * pow(10, (double)exp);
  604|  1.85k|                } else {
  605|     25|                    PLIST_JSON_ERR("%s: invalid character at offset %d when parsing floating point value\n", __func__, (int)(fendp - js));
  ------------------
  |  |   48|     25|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 25]
  |  |  ------------------
  ------------------
  606|     25|                    err++;
  607|     25|                }
  608|  1.87k|            } while (0);
  ------------------
  |  Branch (608:22): [Folded, False: 1.87k]
  ------------------
  609|  2.39k|            if (!err) {
  ------------------
  |  Branch (609:17): [True: 2.37k, False: 25]
  ------------------
  610|  2.37k|                if (isinf(dval) || isnan(dval)) {
  ------------------
  |  Branch (610:21): [True: 130, False: 2.24k]
  |  Branch (610:36): [True: 29, False: 2.21k]
  ------------------
  611|    159|                   PLIST_JSON_ERR("%s: unrepresentable floating point value at offset %d when parsing numerical value\n", __func__, (int)(str_val - js));
  ------------------
  |  |   48|    159|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 159]
  |  |  ------------------
  ------------------
  612|  2.21k|                } else {
  613|  2.21k|                    val = plist_new_real(dval);
  614|  2.21k|                }
  615|  2.37k|            }
  616|  2.39k|        } else {
  617|     64|            PLIST_JSON_ERR("%s: invalid character at offset %d when parsing numerical value\n", __func__, (int)(endp - js));
  ------------------
  |  |   48|     64|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 64]
  |  |  ------------------
  ------------------
  618|     64|        }
  619|  6.64k|    } else {
  620|    159|        PLIST_JSON_ERR("%s: invalid primitive value '%.*s' encountered\n", __func__, (int)str_len, str_val);
  ------------------
  |  |   48|    159|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 159]
  |  |  ------------------
  ------------------
  621|    159|    }
  622|  27.9k|    if (!val) {
  ------------------
  |  Branch (622:9): [True: 407, False: 27.5k]
  ------------------
  623|    407|        PLIST_JSON_ERR("%s: failed to create node\n", __func__);
  ------------------
  |  |   48|    407|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 407]
  |  |  ------------------
  ------------------
  624|    407|        return NULL;
  625|    407|    }
  626|  27.5k|    (*index)++;
  627|  27.5k|    return val;
  628|  27.9k|}
jplist.c:parse_decimal:
  499|  8.49k|{
  500|  8.49k|    const uint64_t po10i_limit = INT64_MAX / 10;
  501|  8.49k|    uint64_t MAX = INT64_MAX;
  502|  8.49k|    uint64_t x = 0;
  503|  8.49k|    int is_neg = 0;
  504|  8.49k|    *endp = (char*)str;
  505|       |
  506|  8.49k|    if (str[0] == '-') {
  ------------------
  |  Branch (506:9): [True: 2.05k, False: 6.44k]
  ------------------
  507|  2.05k|        is_neg = 1;
  508|  2.05k|        (*endp)++;
  509|  6.44k|    } else if (str[0] == '+') {
  ------------------
  |  Branch (509:16): [True: 253, False: 6.19k]
  ------------------
  510|    253|        (*endp)++;
  511|    253|    }
  512|  8.49k|    if (is_neg) {
  ------------------
  |  Branch (512:9): [True: 2.05k, False: 6.44k]
  ------------------
  513|  2.05k|        MAX++;
  514|  2.05k|    }
  515|  43.2k|    while (*endp < str_end && isdigit(**endp)) {
  ------------------
  |  Branch (515:12): [True: 38.4k, False: 4.79k]
  |  Branch (515:31): [True: 35.9k, False: 2.47k]
  ------------------
  516|  35.9k|        if (x > po10i_limit) {
  ------------------
  |  Branch (516:13): [True: 689, False: 35.3k]
  ------------------
  517|    689|            x = MAX;
  518|    689|            break;
  519|    689|        }
  520|  35.3k|        x = x * 10;
  521|  35.3k|        unsigned int add = (**endp - '0');
  522|  35.3k|        if (x + add > MAX) {
  ------------------
  |  Branch (522:13): [True: 534, False: 34.7k]
  ------------------
  523|    534|            x = MAX;
  524|    534|            break;
  525|    534|        }
  526|  34.7k|        x += add;
  527|  34.7k|        (*endp)++;
  528|  34.7k|    }
  529|       |
  530|       |    // swallow the rest of the digits in case we dropped out early
  531|  10.5k|    while (*endp < str_end && isdigit(**endp)) (*endp)++;
  ------------------
  |  Branch (531:12): [True: 4.51k, False: 6.02k]
  |  Branch (531:31): [True: 2.03k, False: 2.47k]
  ------------------
  532|       |
  533|  8.49k|    int64_t result = x;
  534|  8.49k|    if (is_neg) {
  ------------------
  |  Branch (534:9): [True: 2.05k, False: 6.44k]
  ------------------
  535|  2.05k|        if (x == MAX) {
  ------------------
  |  Branch (535:13): [True: 810, False: 1.24k]
  ------------------
  536|    810|            result = INT64_MIN;
  537|  1.24k|        } else {
  538|  1.24k|            result = -(int64_t)x;
  539|  1.24k|        }
  540|  2.05k|    }
  541|  8.49k|    return result;
  542|  8.49k|}
jplist.c:parse_string:
  710|  35.3k|{
  711|  35.3k|    if (ti->tokens[*index].type != JSMN_STRING) {
  ------------------
  |  Branch (711:9): [True: 0, False: 35.3k]
  ------------------
  712|      0|        PLIST_JSON_ERR("%s: token type != JSMN_STRING\n", __func__);
  ------------------
  |  |   48|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  713|      0|        return NULL;
  714|      0|    }
  715|       |
  716|  35.3k|    size_t str_len = 0; ;
  717|  35.3k|    char* strval = unescape_string(js + ti->tokens[*index].start, ti->tokens[*index].end - ti->tokens[*index].start, &str_len);
  718|  35.3k|    if (!strval) {
  ------------------
  |  Branch (718:9): [True: 26, False: 35.3k]
  ------------------
  719|     26|        return NULL;
  720|     26|    }
  721|  35.3k|    plist_t node;
  722|       |
  723|  35.3k|    plist_data_t data = plist_new_plist_data();
  724|  35.3k|    if (!data) {
  ------------------
  |  Branch (724:9): [True: 0, False: 35.3k]
  ------------------
  725|      0|        free(strval);
  726|      0|        PLIST_JSON_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |   48|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  727|      0|        return NULL;
  728|      0|    }
  729|  35.3k|    data->type = PLIST_STRING;
  730|  35.3k|    data->strval = strval;
  731|  35.3k|    data->length = str_len;
  732|  35.3k|    node = plist_new_node(data);
  733|  35.3k|    if (!node) {
  ------------------
  |  Branch (733:9): [True: 0, False: 35.3k]
  ------------------
  734|      0|        plist_free_data(data);
  735|      0|        PLIST_JSON_ERR("%s: failed to create node\n", __func__);
  ------------------
  |  |   48|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  736|      0|        return NULL;
  737|      0|    }
  738|       |
  739|  35.3k|    (*index)++;
  740|  35.3k|    return node;
  741|  35.3k|}
jplist.c:unescape_string:
  631|   104k|{
  632|   104k|    char* strval = strndup(str_val, str_len);
  633|   104k|    if (!strval) return NULL;
  ------------------
  |  Branch (633:9): [True: 0, False: 104k]
  ------------------
  634|   104k|    size_t i = 0;
  635|   231k|    while (i < str_len) {
  ------------------
  |  Branch (635:12): [True: 126k, False: 104k]
  ------------------
  636|   126k|        if (strval[i] == '\\' && i < str_len-1) {
  ------------------
  |  Branch (636:13): [True: 2.61k, False: 124k]
  |  Branch (636:34): [True: 2.61k, False: 0]
  ------------------
  637|  2.61k|            switch (strval[i+1]) {
  638|    859|                case '\"': case '/' : case '\\' : case 'b' :
  ------------------
  |  Branch (638:17): [True: 205, False: 2.41k]
  |  Branch (638:28): [True: 196, False: 2.41k]
  |  Branch (638:39): [True: 211, False: 2.40k]
  |  Branch (638:51): [True: 247, False: 2.36k]
  ------------------
  639|  1.83k|                case 'f' : case 'r' : case 'n'  : case 't' :
  ------------------
  |  Branch (639:17): [True: 225, False: 2.39k]
  |  Branch (639:28): [True: 242, False: 2.37k]
  |  Branch (639:39): [True: 213, False: 2.40k]
  |  Branch (639:51): [True: 300, False: 2.31k]
  ------------------
  640|  1.83k|                    memmove(strval+i, strval+i+1, str_len - (i+1));
  641|  1.83k|                    str_len--;
  642|  1.83k|                    switch (strval[i]) {
  643|    247|                        case 'b':
  ------------------
  |  Branch (643:25): [True: 247, False: 1.59k]
  ------------------
  644|    247|                            strval[i] = '\b';
  645|    247|                            break;
  646|    225|                        case 'f':
  ------------------
  |  Branch (646:25): [True: 225, False: 1.61k]
  ------------------
  647|    225|                            strval[i] = '\f';
  648|    225|                            break;
  649|    242|                        case 'r':
  ------------------
  |  Branch (649:25): [True: 242, False: 1.59k]
  ------------------
  650|    242|                            strval[i] = '\r';
  651|    242|                            break;
  652|    213|                        case 'n':
  ------------------
  |  Branch (652:25): [True: 213, False: 1.62k]
  ------------------
  653|    213|                            strval[i] = '\n';
  654|    213|                            break;
  655|    300|                        case 't':
  ------------------
  |  Branch (655:25): [True: 300, False: 1.53k]
  ------------------
  656|    300|                            strval[i] = '\t';
  657|    300|                            break;
  658|    612|                        default:
  ------------------
  |  Branch (658:25): [True: 612, False: 1.22k]
  ------------------
  659|    612|                            break;
  660|  1.83k|                    }
  661|  1.83k|                    break;
  662|  1.83k|                case 'u': {
  ------------------
  |  Branch (662:17): [True: 776, False: 1.83k]
  ------------------
  663|    776|                    unsigned int val = 0;
  664|    776|                    if (str_len-(i+2) < 4) {
  ------------------
  |  Branch (664:25): [True: 8, False: 768]
  ------------------
  665|      8|                        PLIST_JSON_ERR("%s: invalid escape sequence '%s' (too short)\n", __func__, strval+i);
  ------------------
  |  |   48|      8|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 8]
  |  |  ------------------
  ------------------
  666|      8|                        free(strval);
  667|      8|                        return NULL;
  668|      8|                    }
  669|    768|                    if (!(isxdigit(strval[i+2]) && isxdigit(strval[i+3]) && isxdigit(strval[i+4]) && isxdigit(strval[i+5])) || sscanf(strval+i+2, "%04x", &val) != 1) {
  ------------------
  |  Branch (669:27): [True: 762, False: 6]
  |  Branch (669:52): [True: 761, False: 1]
  |  Branch (669:77): [True: 757, False: 4]
  |  Branch (669:102): [True: 747, False: 10]
  |  Branch (669:128): [True: 0, False: 747]
  ------------------
  670|     21|                        PLIST_JSON_ERR("%s: invalid escape sequence '%.*s'\n", __func__, 6, strval+i);
  ------------------
  |  |   48|     21|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 21]
  |  |  ------------------
  ------------------
  671|     21|                        free(strval);
  672|     21|                        return NULL;
  673|     21|                    }
  674|    747|                    int bytelen = 0;
  675|    747|                    if (val >= 0x800) {
  ------------------
  |  Branch (675:25): [True: 210, False: 537]
  ------------------
  676|       |                        /* three bytes */
  677|    210|                        strval[i]   = (char)(0xE0 + ((val >> 12) & 0xF));
  678|    210|                        strval[i+1] = (char)(0x80 + ((val >> 6) & 0x3F));
  679|    210|                        strval[i+2] = (char)(0x80 + (val & 0x3F));
  680|    210|                        bytelen = 3;
  681|    537|                    } else if (val >= 0x80) {
  ------------------
  |  Branch (681:32): [True: 304, False: 233]
  ------------------
  682|       |                        /* two bytes */
  683|    304|                        strval[i]   = (char)(0xC0 + ((val >> 6) & 0x1F));
  684|    304|                        strval[i+1] = (char)(0x80 + (val & 0x3F));
  685|    304|                        bytelen = 2;
  686|    304|                    } else {
  687|       |                        /* one byte */
  688|    233|                        strval[i] = (char)(val & 0x7F);
  689|    233|                        bytelen = 1;
  690|    233|                    }
  691|    747|                    memmove(strval+i+bytelen, strval+i+6, str_len - (i+5));
  692|    747|                    str_len -= (6-bytelen);
  693|    747|                }   break;
  694|      0|                default:
  ------------------
  |  Branch (694:17): [True: 0, False: 2.61k]
  ------------------
  695|      0|                    PLIST_JSON_ERR("%s: invalid escape sequence '%.*s'\n", __func__, 2, strval+i);
  ------------------
  |  |   48|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  696|      0|                    free(strval);
  697|      0|                    return NULL;
  698|  2.61k|            }
  699|  2.61k|        }
  700|   126k|        i++;
  701|   126k|    }
  702|   104k|    strval[str_len] = '\0';
  703|   104k|    if (new_len) {
  ------------------
  |  Branch (703:9): [True: 35.3k, False: 69.0k]
  ------------------
  704|  35.3k|        *new_len = str_len;
  705|  35.3k|    }
  706|   104k|    return strval;
  707|   104k|}
jplist.c:parse_array:
  746|  57.9k|{
  747|  57.9k|    if (ti->tokens[*index].type != JSMN_ARRAY) {
  ------------------
  |  Branch (747:9): [True: 0, False: 57.9k]
  ------------------
  748|      0|        PLIST_JSON_ERR("%s: token type != JSMN_ARRAY\n", __func__);
  ------------------
  |  |   48|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  749|      0|        ti->err = PLIST_ERR_PARSE;
  750|      0|        return NULL;
  751|      0|    }
  752|  57.9k|    if (depth > PLIST_MAX_NESTING_DEPTH) {
  ------------------
  |  |   56|  57.9k|#define PLIST_MAX_NESTING_DEPTH NODE_MAX_DEPTH
  |  |  ------------------
  |  |  |  |   33|  57.9k|#define NODE_MAX_DEPTH 512
  |  |  ------------------
  ------------------
  |  Branch (752:9): [True: 1, False: 57.8k]
  ------------------
  753|      1|        PLIST_JSON_ERR("%s: maximum nesting depth (%u) exceeded\n", __func__, (unsigned)PLIST_MAX_NESTING_DEPTH);
  ------------------
  |  |   48|      1|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 1]
  |  |  ------------------
  ------------------
  754|      1|        ti->err = PLIST_ERR_MAX_NESTING;
  755|      1|        return NULL;
  756|      1|    }
  757|  57.8k|    plist_t arr = plist_new_array();
  758|  57.8k|    if (!arr) {
  ------------------
  |  Branch (758:9): [True: 0, False: 57.8k]
  ------------------
  759|      0|        PLIST_JSON_ERR("%s: failed to create array node\n", __func__);
  ------------------
  |  |   48|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  760|      0|        ti->err = PLIST_ERR_NO_MEM;
  761|      0|        return NULL;
  762|      0|    }
  763|  57.8k|    size_t num_tokens = ti->tokens[*index].size;
  764|  57.8k|    size_t num;
  765|  57.8k|    int j = (*index)+1;
  766|   116k|    for (num = 0; num < num_tokens; num++) {
  ------------------
  |  Branch (766:19): [True: 62.9k, False: 53.9k]
  ------------------
  767|  62.9k|        if (j >= ti->count) {
  ------------------
  |  Branch (767:13): [True: 0, False: 62.9k]
  ------------------
  768|      0|            PLIST_JSON_ERR("%s: token index out of valid range\n", __func__);
  ------------------
  |  |   48|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  769|      0|            plist_free(arr);
  770|      0|            ti->err = PLIST_ERR_PARSE;
  771|      0|            return NULL;
  772|      0|        }
  773|  62.9k|        plist_t val = NULL;
  774|  62.9k|        switch (ti->tokens[j].type) {
  775|    427|            case JSMN_OBJECT:
  ------------------
  |  Branch (775:13): [True: 427, False: 62.5k]
  ------------------
  776|    427|                val = parse_object(js, ti, &j, depth+1);
  777|    427|                break;
  778|  36.0k|            case JSMN_ARRAY:
  ------------------
  |  Branch (778:13): [True: 36.0k, False: 26.9k]
  ------------------
  779|  36.0k|                val = parse_array(js, ti, &j, depth+1);
  780|  36.0k|                break;
  781|  1.27k|            case JSMN_STRING:
  ------------------
  |  Branch (781:13): [True: 1.27k, False: 61.6k]
  ------------------
  782|  1.27k|                val = parse_string(js, ti, &j);
  783|  1.27k|                break;
  784|  25.2k|            case JSMN_PRIMITIVE:
  ------------------
  |  Branch (784:13): [True: 25.2k, False: 37.7k]
  ------------------
  785|  25.2k|                val = parse_primitive(js, ti, &j);
  786|  25.2k|                break;
  787|      0|            default:
  ------------------
  |  Branch (787:13): [True: 0, False: 62.9k]
  ------------------
  788|      0|                break;
  789|  62.9k|        }
  790|  62.9k|        if (val) {
  ------------------
  |  Branch (790:13): [True: 59.0k, False: 3.91k]
  ------------------
  791|  59.0k|            plist_array_append_item(arr, val);
  792|       |            // if append failed, val still has no parent, free it and abort
  793|  59.0k|            if (((node_t)val)->parent == NULL) {
  ------------------
  |  Branch (793:17): [True: 2, False: 59.0k]
  ------------------
  794|      2|                plist_free(val);
  795|      2|                plist_free(arr);
  796|      2|                ti->err = PLIST_ERR_NO_MEM;
  797|      2|                return NULL;
  798|      2|            }
  799|  59.0k|        } else {
  800|  3.91k|            plist_free(arr);
  801|  3.91k|            ti->err = PLIST_ERR_PARSE;
  802|  3.91k|            return NULL;
  803|  3.91k|        }
  804|  62.9k|    }
  805|  53.9k|    *(index) = j;
  806|  53.9k|    return arr;
  807|  57.8k|}
jplist.c:parse_object:
  810|  12.8k|{
  811|  12.8k|    if (ti->tokens[*index].type != JSMN_OBJECT) {
  ------------------
  |  Branch (811:9): [True: 0, False: 12.8k]
  ------------------
  812|      0|        PLIST_JSON_ERR("%s: token type != JSMN_OBJECT\n", __func__);
  ------------------
  |  |   48|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  813|      0|        ti->err = PLIST_ERR_PARSE;
  814|      0|        return NULL;
  815|      0|    }
  816|  12.8k|    if (depth > PLIST_MAX_NESTING_DEPTH) {
  ------------------
  |  |   56|  12.8k|#define PLIST_MAX_NESTING_DEPTH NODE_MAX_DEPTH
  |  |  ------------------
  |  |  |  |   33|  12.8k|#define NODE_MAX_DEPTH 512
  |  |  ------------------
  ------------------
  |  Branch (816:9): [True: 1, False: 12.8k]
  ------------------
  817|      1|        PLIST_JSON_ERR("%s: maximum nesting depth (%u) exceeded\n", __func__, (unsigned)PLIST_MAX_NESTING_DEPTH);
  ------------------
  |  |   48|      1|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 1]
  |  |  ------------------
  ------------------
  818|      1|        ti->err = PLIST_ERR_MAX_NESTING;
  819|      1|        return NULL;
  820|      1|    }
  821|  12.8k|    size_t num_tokens = ti->tokens[*index].size;
  822|  12.8k|    size_t num;
  823|  12.8k|    int j = (*index)+1;
  824|  12.8k|    if (num_tokens % 2 != 0) {
  ------------------
  |  Branch (824:9): [True: 16, False: 12.7k]
  ------------------
  825|     16|        PLIST_JSON_ERR("%s: number of children must be even\n", __func__);
  ------------------
  |  |   48|     16|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 16]
  |  |  ------------------
  ------------------
  826|     16|        ti->err = PLIST_ERR_PARSE;
  827|     16|        return NULL;
  828|     16|    }
  829|  12.7k|    plist_t obj = plist_new_dict();
  830|  12.7k|    if (!obj) {
  ------------------
  |  Branch (830:9): [True: 0, False: 12.7k]
  ------------------
  831|      0|        PLIST_JSON_ERR("%s: failed to create dict node\n", __func__);
  ------------------
  |  |   48|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  832|      0|        ti->err = PLIST_ERR_NO_MEM;
  833|      0|        return NULL;
  834|      0|    }
  835|  81.2k|    for (num = 0; num < num_tokens; num++) {
  ------------------
  |  Branch (835:19): [True: 69.0k, False: 12.2k]
  ------------------
  836|  69.0k|        if (j+1 >= ti->count) {
  ------------------
  |  Branch (836:13): [True: 0, False: 69.0k]
  ------------------
  837|      0|            PLIST_JSON_ERR("%s: token index out of valid range\n", __func__);
  ------------------
  |  |   48|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  838|      0|            plist_free(obj);
  839|      0|            ti->err = PLIST_ERR_PARSE;
  840|      0|            return NULL;
  841|      0|        }
  842|  69.0k|        if (ti->tokens[j].type == JSMN_STRING) {
  ------------------
  |  Branch (842:13): [True: 69.0k, False: 6]
  ------------------
  843|  69.0k|            char* key = unescape_string(js + ti->tokens[j].start, ti->tokens[j].end - ti->tokens[j].start, NULL);
  844|  69.0k|            if (!key) {
  ------------------
  |  Branch (844:17): [True: 3, False: 69.0k]
  ------------------
  845|      3|                plist_free(obj);
  846|      3|                ti->err = PLIST_ERR_PARSE;
  847|      3|                return NULL;
  848|      3|            }
  849|  69.0k|            plist_t val = NULL;
  850|  69.0k|            j++;
  851|  69.0k|            num++;
  852|  69.0k|            switch (ti->tokens[j].type) {
  853|  11.7k|                case JSMN_OBJECT:
  ------------------
  |  Branch (853:17): [True: 11.7k, False: 57.2k]
  ------------------
  854|  11.7k|                    val = parse_object(js, ti, &j, depth+1);
  855|  11.7k|                    break;
  856|  21.4k|                case JSMN_ARRAY:
  ------------------
  |  Branch (856:17): [True: 21.4k, False: 47.6k]
  ------------------
  857|  21.4k|                    val = parse_array(js, ti, &j, depth+1);
  858|  21.4k|                    break;
  859|  33.9k|                case JSMN_STRING:
  ------------------
  |  Branch (859:17): [True: 33.9k, False: 35.1k]
  ------------------
  860|  33.9k|                    val = parse_string(js, ti, &j);
  861|  33.9k|                    break;
  862|  1.95k|                case JSMN_PRIMITIVE:
  ------------------
  |  Branch (862:17): [True: 1.95k, False: 67.0k]
  ------------------
  863|  1.95k|                    val = parse_primitive(js, ti, &j);
  864|  1.95k|                    break;
  865|      0|                default:
  ------------------
  |  Branch (865:17): [True: 0, False: 69.0k]
  ------------------
  866|      0|                    break;
  867|  69.0k|            }
  868|  69.0k|            if (val) {
  ------------------
  |  Branch (868:17): [True: 68.5k, False: 537]
  ------------------
  869|  68.5k|                plist_dict_set_item(obj, key, val);
  870|       |                // if set failed, val still has no parent, free it and abort
  871|  68.5k|                if (((node_t)val)->parent == NULL) {
  ------------------
  |  Branch (871:21): [True: 5, False: 68.5k]
  ------------------
  872|      5|                    plist_free(val);
  873|      5|                    free(key);
  874|      5|                    plist_free(obj);
  875|      5|                    ti->err = PLIST_ERR_NO_MEM;
  876|      5|                    return NULL;
  877|      5|                }
  878|  68.5k|            } else {
  879|    537|                free(key);
  880|    537|                plist_free(obj);
  881|    537|                ti->err = PLIST_ERR_PARSE;
  882|    537|                return NULL;
  883|    537|            }
  884|  68.5k|            free(key);
  885|  68.5k|        } else {
  886|      6|            PLIST_JSON_ERR("%s: keys must be of type STRING\n", __func__);
  ------------------
  |  |   48|      6|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 6]
  |  |  ------------------
  ------------------
  887|      6|            plist_free(obj);
  888|      6|            ti->err = PLIST_ERR_PARSE;
  889|      6|            return NULL;
  890|      6|        }
  891|  69.0k|    }
  892|  12.2k|    (*index) = j;
  893|  12.2k|    return obj;
  894|  12.7k|}

jsmn_parse:
  173|  13.3k|		unsigned int num_tokens) {
  174|  13.3k|	jsmnerr_t r;
  175|  13.3k|	int i;
  176|  13.3k|	jsmntok_t *token;
  177|       |
  178|  13.3k|	parser->end = length;
  179|       |
  180|  13.3k|	if (num_tokens >= INT_MAX) {
  ------------------
  |  Branch (180:6): [True: 0, False: 13.3k]
  ------------------
  181|      0|		return JSMN_ERROR_LIMIT;
  182|      0|	}
  183|  13.3k|	if (length > SIZE_MAX / 2) {
  ------------------
  |  Branch (183:6): [True: 0, False: 13.3k]
  ------------------
  184|      0|		return JSMN_ERROR_LIMIT;
  185|      0|	}
  186|       |
  187|   440k|	for (; (parser->end > 0 && parser->pos < parser->end) && js[parser->pos] != '\0'; parser->pos++) {
  ------------------
  |  Branch (187:10): [True: 440k, False: 0]
  |  Branch (187:29): [True: 438k, False: 2.15k]
  |  Branch (187:59): [True: 438k, False: 4]
  ------------------
  188|   438k|		char c;
  189|   438k|		jsmntype_t type;
  190|       |
  191|   438k|		c = js[parser->pos];
  192|   438k|		switch (c) {
  193|   178k|			case '{': case '[':
  ------------------
  |  Branch (193:4): [True: 57.1k, False: 381k]
  |  Branch (193:14): [True: 120k, False: 317k]
  ------------------
  194|   178k|				token = jsmn_alloc_token(parser, tokens, num_tokens);
  195|   178k|				if (token == NULL)
  ------------------
  |  Branch (195:9): [True: 7.36k, False: 170k]
  ------------------
  196|  7.36k|					return JSMN_ERROR_NOMEM;
  197|   170k|				if (parser->toksuper != -1) {
  ------------------
  |  Branch (197:9): [True: 164k, False: 6.34k]
  ------------------
  198|   164k|					tokens[parser->toksuper].size++;
  199|       |#ifdef JSMN_PARENT_LINKS
  200|       |					token->parent = parser->toksuper;
  201|       |#endif
  202|   164k|				}
  203|   170k|				token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
  ------------------
  |  Branch (203:20): [True: 54.0k, False: 116k]
  ------------------
  204|   170k|				token->start = parser->pos;
  205|   170k|				parser->toksuper = parser->toknext - 1;
  206|   170k|				break;
  207|  79.4k|			case '}': case ']':
  ------------------
  |  Branch (207:4): [True: 18.5k, False: 419k]
  |  Branch (207:14): [True: 60.9k, False: 377k]
  ------------------
  208|  79.4k|				type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
  ------------------
  |  Branch (208:13): [True: 18.5k, False: 60.9k]
  ------------------
  209|       |#ifdef JSMN_PARENT_LINKS
  210|       |				if (parser->toknext < 1) {
  211|       |					return JSMN_ERROR_INVAL;
  212|       |				}
  213|       |				token = &tokens[parser->toknext - 1];
  214|       |				for (;;) {
  215|       |					if (token->start != JSMN_POS_INVALID && token->end == JSMN_POS_INVALID) {
  216|       |						if (token->type != type) {
  217|       |							return JSMN_ERROR_INVAL;
  218|       |						}
  219|       |						if (parser->pos == SIZE_MAX) {
  220|       |							return JSMN_ERROR_INVAL;
  221|       |						}
  222|       |						token->end = parser->pos + 1;
  223|       |						parser->toksuper = token->parent;
  224|       |						break;
  225|       |					}
  226|       |					if (token->parent == -1) {
  227|       |						break;
  228|       |					}
  229|       |					token = &tokens[token->parent];
  230|       |				}
  231|       |#else
  232|  7.86M|				for (i = parser->toknext - 1; i >= 0; i--) {
  ------------------
  |  Branch (232:35): [True: 7.86M, False: 40]
  ------------------
  233|  7.86M|					token = &tokens[i];
  234|  7.86M|					if (token->start != JSMN_POS_INVALID && token->end == JSMN_POS_INVALID) {
  ------------------
  |  |   35|  15.7M|#define JSMN_POS_INVALID ((size_t)SIZE_MAX)
  ------------------
              					if (token->start != JSMN_POS_INVALID && token->end == JSMN_POS_INVALID) {
  ------------------
  |  |   35|  7.86M|#define JSMN_POS_INVALID ((size_t)SIZE_MAX)
  ------------------
  |  Branch (234:10): [True: 7.86M, False: 0]
  |  Branch (234:46): [True: 79.4k, False: 7.78M]
  ------------------
  235|  79.4k|						if (token->type != type) {
  ------------------
  |  Branch (235:11): [True: 2, False: 79.4k]
  ------------------
  236|      2|							return JSMN_ERROR_INVAL;
  237|      2|						}
  238|  79.4k|						parser->toksuper = -1;
  239|  79.4k|						token->end = parser->pos + 1;
  240|  79.4k|						break;
  241|  79.4k|					}
  242|  7.86M|				}
  243|       |				/* Error if unmatched closing bracket */
  244|  79.4k|				if (i == -1) return JSMN_ERROR_INVAL;
  ------------------
  |  Branch (244:9): [True: 40, False: 79.4k]
  ------------------
  245|  27.1M|				for (; i >= 0; i--) {
  ------------------
  |  Branch (245:12): [True: 27.1M, False: 6.13k]
  ------------------
  246|  27.1M|					token = &tokens[i];
  247|  27.1M|					if (token->start != JSMN_POS_INVALID && token->end == JSMN_POS_INVALID) {
  ------------------
  |  |   35|  54.3M|#define JSMN_POS_INVALID ((size_t)SIZE_MAX)
  ------------------
              					if (token->start != JSMN_POS_INVALID && token->end == JSMN_POS_INVALID) {
  ------------------
  |  |   35|  27.1M|#define JSMN_POS_INVALID ((size_t)SIZE_MAX)
  ------------------
  |  Branch (247:10): [True: 27.1M, False: 0]
  |  Branch (247:46): [True: 73.2k, False: 27.1M]
  ------------------
  248|  73.2k|						parser->toksuper = i;
  249|  73.2k|						break;
  250|  73.2k|					}
  251|  27.1M|				}
  252|  79.4k|#endif
  253|  79.4k|				break;
  254|   115k|			case '\"':
  ------------------
  |  Branch (254:4): [True: 115k, False: 323k]
  ------------------
  255|   115k|				r = jsmn_parse_string(parser, js, tokens, num_tokens);
  256|   115k|				if (r < 0) return r;
  ------------------
  |  Branch (256:9): [True: 2.68k, False: 112k]
  ------------------
  257|   112k|				if (parser->toksuper != -1)
  ------------------
  |  Branch (257:9): [True: 111k, False: 637]
  ------------------
  258|   111k|					tokens[parser->toksuper].size++;
  259|   112k|				break;
  260|  31.9k|			case '\t' : case '\r' : case '\n' : case ':' : case ',': case ' ':
  ------------------
  |  Branch (260:4): [True: 753, False: 437k]
  |  Branch (260:16): [True: 1.12k, False: 437k]
  |  Branch (260:28): [True: 10.7k, False: 427k]
  |  Branch (260:40): [True: 13.5k, False: 424k]
  |  Branch (260:51): [True: 5.03k, False: 433k]
  |  Branch (260:61): [True: 655, False: 437k]
  ------------------
  261|  31.9k|				break;
  262|       |#ifdef JSMN_STRICT
  263|       |			/* In strict mode primitives are: numbers and booleans */
  264|       |			case '-': case '0': case '1' : case '2': case '3' : case '4':
  265|       |			case '5': case '6': case '7' : case '8': case '9':
  266|       |			case 't': case 'f': case 'n' :
  267|       |#else
  268|       |			/* In non-strict mode every unquoted value is a primitive */
  269|  33.6k|			default:
  ------------------
  |  Branch (269:4): [True: 33.6k, False: 404k]
  ------------------
  270|  33.6k|#endif
  271|  33.6k|				r = jsmn_parse_primitive(parser, js, tokens, num_tokens);
  272|  33.6k|				if (r < 0) return r;
  ------------------
  |  Branch (272:9): [True: 1.14k, False: 32.4k]
  ------------------
  273|  32.4k|				if (parser->toksuper != -1)
  ------------------
  |  Branch (273:9): [True: 30.4k, False: 2.03k]
  ------------------
  274|  30.4k|					tokens[parser->toksuper].size++;
  275|  32.4k|				break;
  276|       |
  277|       |#ifdef JSMN_STRICT
  278|       |			/* Unexpected char in strict mode */
  279|       |			default:
  280|       |				return JSMN_ERROR_INVAL;
  281|       |#endif
  282|       |
  283|   438k|		}
  284|   438k|	}
  285|       |
  286|   222k|	for (i = parser->toknext - 1; i >= 0; i--) {
  ------------------
  |  Branch (286:32): [True: 220k, False: 1.97k]
  ------------------
  287|       |		/* Unmatched opened object or array */
  288|   220k|		if (tokens[i].start != JSMN_POS_INVALID && tokens[i].end == JSMN_POS_INVALID) {
  ------------------
  |  |   35|   440k|#define JSMN_POS_INVALID ((size_t)SIZE_MAX)
  ------------------
              		if (tokens[i].start != JSMN_POS_INVALID && tokens[i].end == JSMN_POS_INVALID) {
  ------------------
  |  |   35|   220k|#define JSMN_POS_INVALID ((size_t)SIZE_MAX)
  ------------------
  |  Branch (288:7): [True: 220k, False: 0]
  |  Branch (288:46): [True: 186, False: 219k]
  ------------------
  289|    186|			return JSMN_ERROR_PART;
  290|    186|		}
  291|   220k|	}
  292|       |
  293|  1.97k|	return JSMN_SUCCESS;
  294|  2.16k|}
jsmn_init:
  300|  2.36k|void jsmn_init(jsmn_parser *parser) {
  301|  2.36k|	parser->pos = 0;
  302|  2.36k|	parser->end = 0;
  303|  2.36k|	parser->toknext = 0;
  304|  2.36k|	parser->toksuper = -1;
  305|  2.36k|}
jsmn.c:jsmn_alloc_token:
   41|   326k|		jsmntok_t *tokens, unsigned int num_tokens) {
   42|   326k|	jsmntok_t *tok;
   43|   326k|	if ((unsigned int)parser->toknext >= num_tokens) {
  ------------------
  |  Branch (43:6): [True: 11.0k, False: 315k]
  ------------------
   44|  11.0k|		return NULL;
   45|  11.0k|	}
   46|   315k|	tok = &tokens[parser->toknext++];
   47|   315k|	tok->start = tok->end = JSMN_POS_INVALID;
  ------------------
  |  |   35|   315k|#define JSMN_POS_INVALID ((size_t)SIZE_MAX)
  ------------------
   48|   315k|	tok->size = 0;
   49|       |#ifdef JSMN_PARENT_LINKS
   50|       |	tok->parent = -1;
   51|       |#endif
   52|   315k|	return tok;
   53|   326k|}
jsmn.c:jsmn_parse_string:
  117|   115k|		jsmntok_t *tokens, unsigned int num_tokens) {
  118|   115k|	jsmntok_t *token;
  119|       |
  120|   115k|	size_t start = parser->pos;
  121|       |
  122|   115k|	parser->pos++;
  123|       |
  124|       |	/* Skip starting quote */
  125|   312k|	for (; (parser->end > 0 && parser->pos < parser->end) && js[parser->pos] != '\0'; parser->pos++) {
  ------------------
  |  Branch (125:10): [True: 312k, False: 0]
  |  Branch (125:29): [True: 312k, False: 127]
  |  Branch (125:59): [True: 312k, False: 4]
  ------------------
  126|   312k|		char c = js[parser->pos];
  127|       |
  128|       |		/* Quote: end of string */
  129|   312k|		if (c == '\"') {
  ------------------
  |  Branch (129:7): [True: 114k, False: 197k]
  ------------------
  130|   114k|			token = jsmn_alloc_token(parser, tokens, num_tokens);
  131|   114k|			if (token == NULL) {
  ------------------
  |  Branch (131:8): [True: 2.54k, False: 112k]
  ------------------
  132|  2.54k|				parser->pos = start;
  133|  2.54k|				return JSMN_ERROR_NOMEM;
  134|  2.54k|			}
  135|   112k|			jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
  136|       |#ifdef JSMN_PARENT_LINKS
  137|       |			token->parent = parser->toksuper;
  138|       |#endif
  139|   112k|			return JSMN_SUCCESS;
  140|   114k|		}
  141|       |
  142|       |		/* Backslash: Quoted symbol expected */
  143|   197k|		if (c == '\\') {
  ------------------
  |  Branch (143:7): [True: 24.1k, False: 173k]
  ------------------
  144|  24.1k|			parser->pos++;
  145|  24.1k|			if (parser->end > 0 && parser->pos >= parser->end) {
  ------------------
  |  Branch (145:8): [True: 24.1k, False: 0]
  |  Branch (145:27): [True: 2, False: 24.1k]
  ------------------
  146|      2|				parser->pos = start;
  147|      2|				return JSMN_ERROR_INVAL;
  148|      2|			}
  149|  24.1k|			switch (js[parser->pos]) {
  150|       |				/* Allowed escaped symbols */
  151|  6.86k|				case '\"': case '/' : case '\\' : case 'b' :
  ------------------
  |  Branch (151:5): [True: 762, False: 23.3k]
  |  Branch (151:16): [True: 535, False: 23.5k]
  |  Branch (151:27): [True: 5.10k, False: 19.0k]
  |  Branch (151:39): [True: 459, False: 23.6k]
  ------------------
  152|  22.4k|				case 'f' : case 'r' : case 'n'  : case 't' :
  ------------------
  |  Branch (152:5): [True: 764, False: 23.3k]
  |  Branch (152:16): [True: 477, False: 23.6k]
  |  Branch (152:27): [True: 13.5k, False: 10.5k]
  |  Branch (152:39): [True: 818, False: 23.3k]
  ------------------
  153|  22.4k|					break;
  154|       |				/* Allows escaped symbol \uXXXX */
  155|  1.66k|				case 'u':
  ------------------
  |  Branch (155:5): [True: 1.66k, False: 22.4k]
  ------------------
  156|       |					/* TODO */
  157|  1.66k|					break;
  158|       |				/* Unexpected symbol */
  159|      2|				default:
  ------------------
  |  Branch (159:5): [True: 2, False: 24.1k]
  ------------------
  160|      2|					parser->pos = start;
  161|      2|					return JSMN_ERROR_INVAL;
  162|  24.1k|			}
  163|  24.1k|		}
  164|   197k|	}
  165|    131|	parser->pos = start;
  166|    131|	return JSMN_ERROR_PART;
  167|   115k|}
jsmn.c:jsmn_fill_token:
   59|   144k|                            size_t start, size_t end) {
   60|   144k|	token->type = type;
   61|   144k|	token->start = start;
   62|   144k|	token->end = end;
   63|   144k|	token->size = 0;
   64|   144k|}
jsmn.c:jsmn_parse_primitive:
   70|  33.6k|		jsmntok_t *tokens, unsigned int num_tokens) {
   71|  33.6k|	jsmntok_t *token;
   72|  33.6k|	size_t start;
   73|       |
   74|  33.6k|	start = parser->pos;
   75|       |
   76|   103k|	for (; (parser->end > 0 && parser->pos < parser->end) && js[parser->pos] != '\0'; parser->pos++) {
  ------------------
  |  Branch (76:10): [True: 103k, False: 0]
  |  Branch (76:29): [True: 103k, False: 674]
  |  Branch (76:59): [True: 103k, False: 1]
  ------------------
   77|   103k|		switch (js[parser->pos]) {
   78|      0|#ifndef JSMN_STRICT
   79|       |			/* In strict mode primitive must be followed by "," or "}" or "]" */
   80|  7.42k|			case ':':
  ------------------
  |  Branch (80:4): [True: 7.42k, False: 95.6k]
  ------------------
   81|  7.42k|#endif
   82|  20.1k|			case '\t' : case '\r' : case '\n' : case ' ' :
  ------------------
  |  Branch (82:4): [True: 550, False: 102k]
  |  Branch (82:16): [True: 913, False: 102k]
  |  Branch (82:28): [True: 10.8k, False: 92.2k]
  |  Branch (82:40): [True: 460, False: 102k]
  ------------------
   83|  32.9k|			case ','  : case ']'  : case '}' :
  ------------------
  |  Branch (83:4): [True: 4.83k, False: 98.2k]
  |  Branch (83:16): [True: 6.79k, False: 96.3k]
  |  Branch (83:28): [True: 1.10k, False: 102k]
  ------------------
   84|  32.9k|				goto found;
   85|  70.2k|			default:
  ------------------
  |  Branch (85:4): [True: 70.2k, False: 32.9k]
  ------------------
   86|  70.2k|				break;
   87|   103k|		}
   88|  70.2k|		if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
  ------------------
  |  Branch (88:7): [True: 20, False: 70.1k]
  |  Branch (88:31): [True: 3, False: 70.1k]
  ------------------
   89|     23|			parser->pos = start;
   90|     23|			return JSMN_ERROR_INVAL;
   91|     23|		}
   92|  70.2k|	}
   93|       |#ifdef JSMN_STRICT
   94|       |	/* In strict mode primitive must be followed by a comma/object/array */
   95|       |	parser->pos = start;
   96|       |	return JSMN_ERROR_PART;
   97|       |#endif
   98|       |
   99|  33.5k|found:
  100|  33.5k|	token = jsmn_alloc_token(parser, tokens, num_tokens);
  101|  33.5k|	if (token == NULL) {
  ------------------
  |  Branch (101:6): [True: 1.12k, False: 32.4k]
  ------------------
  102|  1.12k|		parser->pos = start;
  103|  1.12k|		return JSMN_ERROR_NOMEM;
  104|  1.12k|	}
  105|  32.4k|	jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
  106|       |#ifdef JSMN_PARENT_LINKS
  107|       |	token->parent = parser->toksuper;
  108|       |#endif
  109|  32.4k|	parser->pos--;
  110|  32.4k|	return JSMN_SUCCESS;
  111|  33.5k|}

plist_ostep_init:
   54|      2|{
   55|       |    /* init OpenStep stuff */
   56|      2|#ifdef DEBUG
   57|      2|    char *env_debug = getenv("PLIST_OSTEP_DEBUG");
   58|      2|    if (env_debug && !strcmp(env_debug, "1")) {
  ------------------
  |  Branch (58:9): [True: 0, False: 2]
  |  Branch (58:22): [True: 0, False: 0]
  ------------------
   59|      0|        plist_ostep_debug = 1;
   60|      0|    }
   61|      2|#endif
   62|      2|}

plist.c:internal_plist_init:
  153|      2|{
  154|      2|    plist_bin_init();
  155|      2|    plist_xml_init();
  156|      2|    plist_json_init();
  157|      2|    plist_ostep_init();
  158|      2|    atexit(internal_plist_deinit);
  159|      2|}
plist_new_node:
  348|   198k|{
  349|       |    return (plist_t) node_create(NULL, data);
  350|   198k|}
plist_get_data:
  353|  23.7M|{
  354|  23.7M|    if (!node)
  ------------------
  |  Branch (354:9): [True: 0, False: 23.7M]
  ------------------
  355|      0|        return NULL;
  356|  23.7M|    return (plist_data_t)((node_t)node)->data;
  357|  23.7M|}
plist_new_plist_data:
  360|   198k|{
  361|   198k|    return (plist_data_t) calloc(1, sizeof(struct plist_data_s));
  362|   198k|}
plist_free_data:
  421|   198k|{
  422|   198k|    if (!data) return;
  ------------------
  |  Branch (422:9): [True: 0, False: 198k]
  ------------------
  423|   198k|    _plist_free_data(data);
  424|   198k|    free(data);
  425|   198k|}
plist_new_dict:
  528|  12.7k|{
  529|  12.7k|    plist_data_t data = plist_new_plist_data();
  530|  12.7k|    if (!data) {
  ------------------
  |  Branch (530:9): [True: 0, False: 12.7k]
  ------------------
  531|      0|        PLIST_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  532|      0|        return NULL;
  533|      0|    }
  534|  12.7k|    data->type = PLIST_DICT;
  535|  12.7k|    return plist_new_node(data);
  536|  12.7k|}
plist_new_array:
  539|  57.8k|{
  540|  57.8k|    plist_data_t data = plist_new_plist_data();
  541|  57.8k|    if (!data) {
  ------------------
  |  Branch (541:9): [True: 0, False: 57.8k]
  ------------------
  542|      0|        PLIST_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  543|      0|        return NULL;
  544|      0|    }
  545|  57.8k|    data->type = PLIST_ARRAY;
  546|  57.8k|    return plist_new_node(data);
  547|  57.8k|}
plist_new_bool:
  589|  8.56k|{
  590|  8.56k|    plist_data_t data = plist_new_plist_data();
  591|  8.56k|    if (!data) {
  ------------------
  |  Branch (591:9): [True: 0, False: 8.56k]
  ------------------
  592|      0|        PLIST_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  593|      0|        return NULL;
  594|      0|    }
  595|  8.56k|    data->type = PLIST_BOOLEAN;
  596|  8.56k|    data->boolval = val;
  597|  8.56k|    data->length = sizeof(uint8_t);
  598|  8.56k|    return plist_new_node(data);
  599|  8.56k|}
plist_new_int:
  615|  4.18k|{
  616|  4.18k|    plist_data_t data = plist_new_plist_data();
  617|  4.18k|    if (!data) {
  ------------------
  |  Branch (617:9): [True: 0, False: 4.18k]
  ------------------
  618|      0|        PLIST_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  619|      0|        return NULL;
  620|      0|    }
  621|  4.18k|    data->type = PLIST_INT;
  622|  4.18k|    data->intval = val;
  623|  4.18k|    data->length = sizeof(uint64_t);
  624|  4.18k|    return plist_new_node(data);
  625|  4.18k|}
plist_new_real:
  641|  2.21k|{
  642|  2.21k|    plist_data_t data = plist_new_plist_data();
  643|  2.21k|    if (!data) {
  ------------------
  |  Branch (643:9): [True: 0, False: 2.21k]
  ------------------
  644|      0|        PLIST_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  645|      0|        return NULL;
  646|      0|    }
  647|  2.21k|    data->type = PLIST_REAL;
  648|  2.21k|    data->realval = val;
  649|  2.21k|    data->length = sizeof(double);
  650|  2.21k|    return plist_new_node(data);
  651|  2.21k|}
plist_free:
  713|  6.83k|{
  714|  6.83k|    if (plist)
  ------------------
  |  Branch (714:9): [True: 5.98k, False: 853]
  ------------------
  715|  5.98k|    {
  716|  5.98k|        plist_free_node((node_t)plist);
  717|  5.98k|    }
  718|  6.83k|}
plist_array_append_item:
 1080|  59.0k|{
 1081|  59.0k|    if (!PLIST_IS_ARRAY(node) || !item) {
  ------------------
  |  | 1252|  59.0k|    #define PLIST_IS_ARRAY(__plist)   _PLIST_IS_TYPE(__plist, ARRAY)
  |  |  ------------------
  |  |  |  | 1240|   118k|    #define _PLIST_IS_TYPE(__plist, __plist_type) (__plist && (plist_get_node_type(__plist) == PLIST_##__plist_type))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1240:52): [True: 59.0k, False: 0]
  |  |  |  |  |  Branch (1240:63): [True: 59.0k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1081:34): [True: 0, False: 59.0k]
  ------------------
 1082|      0|        PLIST_ERR("invalid argument passed to %s (node=%p, item=%p)\n", __func__, node, item);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1083|      0|        return PLIST_ERR_INVALID_ARG;
 1084|      0|    }
 1085|  59.0k|    node_t it = (node_t)item;
 1086|  59.0k|    if (it->parent != NULL) {
  ------------------
  |  Branch (1086:9): [True: 0, False: 59.0k]
  ------------------
 1087|      0|        assert(it->parent == NULL && "item already has a parent; use plist_copy() or detach first");
  ------------------
  |  Branch (1087:9): [True: 0, False: 0]
  |  Branch (1087:9): [True: 0, False: 0]
  |  Branch (1087:9): [True: 0, False: 0]
  |  Branch (1087:9): [True: 0, False: 0]
  ------------------
 1088|      0|        PLIST_ERR("%s: item already has a parent; use plist_copy() or detach first\n", __func__);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1089|      0|        return PLIST_ERR_INVALID_ARG;
 1090|      0|    }
 1091|       |
 1092|  59.0k|    int r = node_attach((node_t)node, (node_t)item);
 1093|  59.0k|    if (r != NODE_ERR_SUCCESS) {
  ------------------
  |  |   36|  59.0k|#define NODE_ERR_SUCCESS       0
  ------------------
  |  Branch (1093:9): [True: 2, False: 59.0k]
  ------------------
 1094|      2|        PLIST_ERR("%s: failed to append item (err=%d)\n", __func__, r);
  ------------------
  |  |   57|      2|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 2]
  |  |  ------------------
  ------------------
 1095|      2|        return PLIST_ERR_UNKNOWN;
 1096|      2|    }
 1097|  59.0k|    _plist_array_post_insert(node, item, -1);
 1098|       |
 1099|  59.0k|    return PLIST_ERR_SUCCESS;
 1100|  59.0k|}
plist_dict_get_item:
 1281|  68.5k|{
 1282|  68.5k|    plist_t ret = NULL;
 1283|  68.5k|    if (!PLIST_IS_DICT(node) || !key) {
  ------------------
  |  | 1254|  68.5k|    #define PLIST_IS_DICT(__plist)    _PLIST_IS_TYPE(__plist, DICT)
  |  |  ------------------
  |  |  |  | 1240|   137k|    #define _PLIST_IS_TYPE(__plist, __plist_type) (__plist && (plist_get_node_type(__plist) == PLIST_##__plist_type))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1240:52): [True: 68.5k, False: 0]
  |  |  |  |  |  Branch (1240:63): [True: 68.5k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1283:33): [True: 0, False: 68.5k]
  ------------------
 1284|      0|        PLIST_ERR("invalid argument passed to %s (node=%p, key=%p)\n", __func__, node, key);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1285|      0|        return NULL;
 1286|      0|    }
 1287|  68.5k|    plist_data_t data = plist_get_data(node);
 1288|  68.5k|    if (!data) {
  ------------------
  |  Branch (1288:9): [True: 0, False: 68.5k]
  ------------------
 1289|      0|        PLIST_ERR("%s: invalid node\n", __func__);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1290|      0|        return NULL;
 1291|      0|    }
 1292|  68.5k|    size_t keylen = strlen(key);
 1293|  68.5k|    hashtable_t *ht = (hashtable_t*)data->hashtable;
 1294|  68.5k|    if (ht) {
  ------------------
  |  Branch (1294:9): [True: 955, False: 67.5k]
  ------------------
 1295|    955|        struct plist_data_s sdata = { 0 };
 1296|    955|        sdata.strval = (char*)key;
 1297|    955|        sdata.length = keylen;
 1298|    955|        return (plist_t)hash_table_lookup(ht, &sdata);
 1299|  67.5k|    } else {
 1300|  67.5k|        plist_t k = NULL;
 1301|  7.83M|        for (k = (plist_t)node_first_child((node_t)node); k; ) {
  ------------------
  |  Branch (1301:59): [True: 7.77M, False: 64.2k]
  ------------------
 1302|  7.77M|            plist_t v = (plist_t)node_next_sibling(k);
 1303|  7.77M|            if (!v) break;
  ------------------
  |  Branch (1303:17): [True: 0, False: 7.77M]
  ------------------
 1304|  7.77M|            data = plist_get_data(k);
 1305|  7.77M|            assert(PLIST_IS_KEY(k));
  ------------------
  |  Branch (1305:13): [True: 0, False: 7.77M]
  |  Branch (1305:13): [True: 0, False: 0]
  |  Branch (1305:13): [True: 7.77M, False: 0]
  |  Branch (1305:13): [True: 7.77M, False: 0]
  ------------------
 1306|  7.77M|            if (!PLIST_IS_KEY(k) || !data || !data->strval) {
  ------------------
  |  | 1260|  7.77M|    #define PLIST_IS_KEY(__plist)     _PLIST_IS_TYPE(__plist, KEY)
  |  |  ------------------
  |  |  |  | 1240|  15.5M|    #define _PLIST_IS_TYPE(__plist, __plist_type) (__plist && (plist_get_node_type(__plist) == PLIST_##__plist_type))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1240:52): [True: 7.77M, False: 0]
  |  |  |  |  |  Branch (1240:63): [True: 7.77M, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1306:37): [True: 0, False: 7.77M]
  |  Branch (1306:46): [True: 0, False: 7.77M]
  ------------------
 1307|      0|                PLIST_ERR("invalid key node at %p\n", k);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1308|      0|                break;
 1309|      0|            }
 1310|  7.77M|            if (data->length == keylen && !memcmp(key, data->strval, keylen+1)) {
  ------------------
  |  Branch (1310:17): [True: 4.15M, False: 3.61M]
  |  Branch (1310:43): [True: 3.29k, False: 4.15M]
  ------------------
 1311|  3.29k|                ret = v;
 1312|  3.29k|                break;
 1313|  3.29k|            }
 1314|  7.77M|            k = node_next_sibling(v);
 1315|  7.77M|        }
 1316|  67.5k|    }
 1317|  67.5k|    return ret;
 1318|  68.5k|}
plist_dict_set_item:
 1321|  68.5k|{
 1322|  68.5k|    if (!PLIST_IS_DICT(node) || !key || !item) {
  ------------------
  |  | 1254|  68.5k|    #define PLIST_IS_DICT(__plist)    _PLIST_IS_TYPE(__plist, DICT)
  |  |  ------------------
  |  |  |  | 1240|   137k|    #define _PLIST_IS_TYPE(__plist, __plist_type) (__plist && (plist_get_node_type(__plist) == PLIST_##__plist_type))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1240:52): [True: 68.5k, False: 0]
  |  |  |  |  |  Branch (1240:63): [True: 68.5k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1322:33): [True: 0, False: 68.5k]
  |  Branch (1322:41): [True: 0, False: 68.5k]
  ------------------
 1323|      0|        PLIST_ERR("invalid argument passed to %s (node=%p, key=%p, item=%p)\n", __func__, node, key, item);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1324|      0|        return PLIST_ERR_INVALID_ARG;
 1325|      0|    }
 1326|  68.5k|    node_t it = (node_t)item;
 1327|  68.5k|    if (it->parent != NULL) {
  ------------------
  |  Branch (1327:9): [True: 0, False: 68.5k]
  ------------------
 1328|      0|        assert(it->parent == NULL && "item already has a parent");
  ------------------
  |  Branch (1328:9): [True: 0, False: 0]
  |  Branch (1328:9): [True: 0, False: 0]
  |  Branch (1328:9): [True: 0, False: 0]
  |  Branch (1328:9): [True: 0, False: 0]
  ------------------
 1329|      0|        PLIST_ERR("%s: item already has a parent\n", __func__);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1330|      0|        return PLIST_ERR_INVALID_ARG;
 1331|      0|    }
 1332|       |
 1333|  68.5k|    hashtable_t *ht = (hashtable_t*)((plist_data_t)((node_t)node)->data)->hashtable;
 1334|       |
 1335|  68.5k|    plist_t old_item = plist_dict_get_item(node, key);
 1336|  68.5k|    plist_t key_node = NULL;
 1337|       |
 1338|  68.5k|    if (old_item) {
  ------------------
  |  Branch (1338:9): [True: 3.86k, False: 64.6k]
  ------------------
 1339|       |        // --- REPLACE EXISTING VALUE ---
 1340|  3.86k|        node_t old_val = (node_t)old_item;
 1341|  3.86k|        node_t old_key = node_prev_sibling(old_val);
 1342|  3.86k|        if (!old_key) {
  ------------------
  |  Branch (1342:13): [True: 0, False: 3.86k]
  ------------------
 1343|      0|            PLIST_ERR("%s: corrupt dict (value without key)\n", __func__);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1344|      0|            return PLIST_ERR_UNKNOWN;
 1345|      0|        }
 1346|  3.86k|        if (!PLIST_IS_KEY((plist_t)old_key)) {
  ------------------
  |  | 1260|  3.86k|    #define PLIST_IS_KEY(__plist)     _PLIST_IS_TYPE(__plist, KEY)
  |  |  ------------------
  |  |  |  | 1240|  3.86k|    #define _PLIST_IS_TYPE(__plist, __plist_type) (__plist && (plist_get_node_type(__plist) == PLIST_##__plist_type))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1240:52): [True: 3.86k, False: 0]
  |  |  |  |  |  Branch (1240:63): [True: 3.86k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1347|      0|            PLIST_ERR("%s: corrupt dict ('key' node is not PLIST_KEY\n", __func__);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1348|      0|            return PLIST_ERR_UNKNOWN;
 1349|      0|        }
 1350|       |
 1351|       |        // detach old value (do NOT free yet)
 1352|  3.86k|        int idx = node_detach((node_t)node, old_val);
 1353|  3.86k|        if (idx < 0) {
  ------------------
  |  Branch (1353:13): [True: 0, False: 3.86k]
  ------------------
 1354|      0|            PLIST_ERR("%s: failed to detach old value (err=%d)\n", __func__, idx);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1355|      0|            return PLIST_ERR_UNKNOWN;
 1356|      0|        }
 1357|       |
 1358|       |        // insert new value at same position
 1359|  3.86k|        int r = node_insert((node_t)node, (unsigned)idx, (node_t)item);
 1360|  3.86k|        if (r != NODE_ERR_SUCCESS) {
  ------------------
  |  |   36|  3.86k|#define NODE_ERR_SUCCESS       0
  ------------------
  |  Branch (1360:13): [True: 3, False: 3.85k]
  ------------------
 1361|       |            // rollback: reinsert old value
 1362|      3|            int rb = node_insert((node_t)node, (unsigned)idx, old_val);
 1363|      3|            if (rb == NODE_ERR_SUCCESS && ht) {
  ------------------
  |  |   36|      6|#define NODE_ERR_SUCCESS       0
  ------------------
  |  Branch (1363:17): [True: 3, False: 0]
  |  Branch (1363:43): [True: 1, False: 2]
  ------------------
 1364|      1|                hash_table_insert(ht, ((node_t)old_key)->data, old_item);
 1365|      1|            }
 1366|      3|            PLIST_ERR("%s: failed to replace dict value (err=%d)\n", __func__, r);
  ------------------
  |  |   57|      3|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 3]
  |  |  ------------------
  ------------------
 1367|      3|            return PLIST_ERR_UNKNOWN;
 1368|      3|        }
 1369|  3.85k|        key_node = old_key;
 1370|       |
 1371|       |        // update hash table
 1372|  3.85k|        if (ht) {
  ------------------
  |  Branch (1372:13): [True: 564, False: 3.29k]
  ------------------
 1373|    564|            hash_table_insert(ht, (plist_data_t)((node_t)key_node)->data, item);
 1374|    564|        }
 1375|       |
 1376|       |        // now it’s safe to free old value
 1377|  3.85k|        plist_free_node(old_val);
 1378|  64.6k|    } else {
 1379|       |        // --- INSERT NEW KEY/VALUE PAIR ---
 1380|  64.6k|        key_node = plist_new_key(key);
 1381|  64.6k|        if (!key_node) return PLIST_ERR_NO_MEM;
  ------------------
  |  Branch (1381:13): [True: 0, False: 64.6k]
  ------------------
 1382|       |
 1383|  64.6k|        int r = node_attach((node_t)node, (node_t)key_node);
 1384|  64.6k|        if (r != NODE_ERR_SUCCESS) {
  ------------------
  |  |   36|  64.6k|#define NODE_ERR_SUCCESS       0
  ------------------
  |  Branch (1384:13): [True: 0, False: 64.6k]
  ------------------
 1385|      0|            plist_free_node((node_t)key_node);
 1386|      0|            PLIST_ERR("%s: failed to attach dict key (err=%d)\n", __func__, r);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1387|      0|            return PLIST_ERR_UNKNOWN;
 1388|      0|        }
 1389|  64.6k|        r = node_attach((node_t)node, (node_t)item);
 1390|  64.6k|        if (r != NODE_ERR_SUCCESS) {
  ------------------
  |  |   36|  64.6k|#define NODE_ERR_SUCCESS       0
  ------------------
  |  Branch (1390:13): [True: 2, False: 64.6k]
  ------------------
 1391|       |            // rollback key insertion
 1392|      2|            node_detach((node_t)node, (node_t)key_node);
 1393|      2|            plist_free_node((node_t)key_node);
 1394|      2|            PLIST_ERR("%s: failed to attach dict value (err=%d)\n", __func__, r);
  ------------------
  |  |   57|      2|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 2]
  |  |  ------------------
  ------------------
 1395|      2|            return PLIST_ERR_UNKNOWN;
 1396|      2|        }
 1397|       |
 1398|  64.6k|        if (ht) {
  ------------------
  |  Branch (1398:13): [True: 389, False: 64.2k]
  ------------------
 1399|       |            // store pointer to item in hash table
 1400|    389|            hash_table_insert(ht, (plist_data_t)((node_t)key_node)->data, item);
 1401|  64.2k|        } else if (((node_t)node)->count > 500) {
  ------------------
  |  Branch (1401:20): [True: 240, False: 64.0k]
  ------------------
 1402|       |            // make new hash table
 1403|    240|            ht = hash_table_new(dict_key_hash, dict_key_compare, NULL);
 1404|       |            // calculate the hashes for all entries we have so far
 1405|    240|            plist_t current = NULL;
 1406|    240|            for (current = (plist_t)node_first_child((node_t)node);
 1407|  60.4k|                 ht && current;
  ------------------
  |  Branch (1407:18): [True: 60.4k, False: 0]
  |  Branch (1407:24): [True: 60.2k, False: 240]
  ------------------
 1408|  60.2k|                 current = (plist_t)node_next_sibling(node_next_sibling((node_t)current)))
 1409|  60.2k|            {
 1410|  60.2k|                hash_table_insert(ht, ((node_t)current)->data, node_next_sibling((node_t)current));
 1411|  60.2k|            }
 1412|    240|            ((plist_data_t)((node_t)node)->data)->hashtable = ht;
 1413|    240|        }
 1414|  64.6k|    }
 1415|  68.5k|    return PLIST_ERR_SUCCESS;
 1416|  68.5k|}
plist_get_node_type:
 1746|  15.7M|{
 1747|  15.7M|    if (node)
  ------------------
  |  Branch (1747:9): [True: 15.7M, False: 0]
  ------------------
 1748|  15.7M|    {
 1749|  15.7M|        plist_data_t data = plist_get_data(node);
 1750|  15.7M|        if (data)
  ------------------
  |  Branch (1750:13): [True: 15.7M, False: 0]
  ------------------
 1751|  15.7M|            return data->type;
 1752|  15.7M|    }
 1753|      0|    return PLIST_NONE;
 1754|  15.7M|}
plist.c:_plist_free_data:
  390|   198k|{
  391|   198k|    if (!data) return;
  ------------------
  |  Branch (391:9): [True: 0, False: 198k]
  ------------------
  392|   198k|    switch (data->type) {
  393|  64.6k|        case PLIST_KEY:
  ------------------
  |  Branch (393:9): [True: 64.6k, False: 133k]
  ------------------
  394|  99.9k|        case PLIST_STRING:
  ------------------
  |  Branch (394:9): [True: 35.3k, False: 162k]
  ------------------
  395|  99.9k|            free(data->strval);
  396|  99.9k|            data->strval = NULL;
  397|  99.9k|            break;
  398|      0|        case PLIST_DATA:
  ------------------
  |  Branch (398:9): [True: 0, False: 198k]
  ------------------
  399|      0|            free(data->buff);
  400|      0|            data->buff = NULL;
  401|      0|            break;
  402|  57.8k|        case PLIST_ARRAY:
  ------------------
  |  Branch (402:9): [True: 57.8k, False: 140k]
  ------------------
  403|  57.8k|            ptr_array_free((ptrarray_t*)data->hashtable);
  404|  57.8k|            data->hashtable = NULL;
  405|  57.8k|            break;
  406|  12.7k|        case PLIST_DICT: {
  ------------------
  |  Branch (406:9): [True: 12.7k, False: 185k]
  ------------------
  407|  12.7k|            hashtable_t *ht = (hashtable_t*)data->hashtable;
  408|       |            // PLIST_DICT hashtables must not own/free values; values are freed via node tree.
  409|  12.7k|            assert(!ht || ht->free_func == NULL);
  ------------------
  |  Branch (409:13): [True: 12.7k, False: 0]
  |  Branch (409:13): [True: 0, False: 0]
  |  Branch (409:13): [True: 12.5k, False: 240]
  |  Branch (409:13): [True: 240, False: 0]
  ------------------
  410|  12.7k|            if (ht) ht->free_func = NULL;
  ------------------
  |  Branch (410:17): [True: 240, False: 12.5k]
  ------------------
  411|  12.7k|            hash_table_destroy(ht);
  412|  12.7k|            data->hashtable = NULL;
  413|  12.7k|            break;
  414|  12.7k|        }
  415|  27.5k|        default:
  ------------------
  |  Branch (415:9): [True: 27.5k, False: 170k]
  ------------------
  416|  27.5k|            break;
  417|   198k|    }
  418|   198k|}
plist.c:plist_free_node:
  500|  9.84k|{
  501|  9.84k|    if (!root) return NODE_ERR_INVALID_ARG;
  ------------------
  |  |   37|      0|#define NODE_ERR_INVALID_ARG  -1
  ------------------
  |  Branch (501:9): [True: 0, False: 9.84k]
  ------------------
  502|       |
  503|  9.84k|    int root_index = -1;
  504|       |
  505|  9.84k|    if (root->parent) {
  ------------------
  |  Branch (505:9): [True: 0, False: 9.84k]
  ------------------
  506|      0|        root_index = node_detach(root->parent, root);
  507|      0|        if (root_index < 0) {
  ------------------
  |  Branch (507:13): [True: 0, False: 0]
  ------------------
  508|      0|            return root_index;
  509|      0|        }
  510|      0|    }
  511|       |
  512|  9.84k|    int r = plist_free_children(root);
  513|  9.84k|    if (r < 0) {
  ------------------
  |  Branch (513:9): [True: 0, False: 9.84k]
  ------------------
  514|       |        // root is already detached; caller should treat as error.
  515|      0|        return r;
  516|      0|    }
  517|       |
  518|  9.84k|    plist_data_t data = plist_get_data(root);
  519|  9.84k|    plist_free_data(data);
  520|  9.84k|    root->data = NULL;
  521|       |
  522|  9.84k|    node_destroy(root);
  523|       |
  524|  9.84k|    return root_index;
  525|  9.84k|}
plist.c:plist_free_children:
  428|  9.84k|{
  429|  9.84k|    if (!root) return NODE_ERR_INVALID_ARG;
  ------------------
  |  |   37|      0|#define NODE_ERR_INVALID_ARG  -1
  ------------------
  |  Branch (429:9): [True: 0, False: 9.84k]
  ------------------
  430|       |
  431|  9.84k|    if (!node_first_child(root)) {
  ------------------
  |  Branch (431:9): [True: 8.29k, False: 1.54k]
  ------------------
  432|  8.29k|        return NODE_ERR_SUCCESS;
  ------------------
  |  |   36|  8.29k|#define NODE_ERR_SUCCESS       0
  ------------------
  433|  8.29k|    }
  434|       |
  435|  1.54k|    size_t cap = 64, sp = 0;
  436|  1.54k|    node_t *stack = (node_t*)malloc(cap * sizeof(*stack));
  437|  1.54k|    if (!stack) return NODE_ERR_NO_MEM;
  ------------------
  |  |   38|      0|#define NODE_ERR_NO_MEM       -2
  ------------------
  |  Branch (437:9): [True: 0, False: 1.54k]
  ------------------
  438|       |
  439|       |    // Push *direct* children onto the stack, detached from root.
  440|   147k|    for (;;) {
  441|   147k|        node_t ch = node_first_child(root);
  442|   147k|        if (!ch) break;
  ------------------
  |  Branch (442:13): [True: 1.54k, False: 146k]
  ------------------
  443|       |
  444|   146k|        int di = node_detach(root, ch);
  445|   146k|        if (di < 0) {
  ------------------
  |  Branch (445:13): [True: 0, False: 146k]
  ------------------
  446|      0|            free(stack);
  447|      0|            return di;
  448|      0|        }
  449|       |
  450|   146k|        if (sp == cap) {
  ------------------
  |  Branch (450:13): [True: 1.95k, False: 144k]
  ------------------
  451|  1.95k|            cap += 64;
  452|  1.95k|            node_t *tmp = (node_t*)realloc(stack, cap * sizeof(*stack));
  453|  1.95k|            if (!tmp) {
  ------------------
  |  Branch (453:17): [True: 0, False: 1.95k]
  ------------------
  454|      0|                free(stack);
  455|      0|                return NODE_ERR_NO_MEM;
  ------------------
  |  |   38|      0|#define NODE_ERR_NO_MEM       -2
  ------------------
  456|      0|            }
  457|  1.95k|            stack = tmp;
  458|  1.95k|        }
  459|   146k|        stack[sp++] = ch;
  460|   146k|    }
  461|       |
  462|       |    // Now free the detached subtree nodes (and their descendants).
  463|   232k|    while (sp) {
  ------------------
  |  Branch (463:12): [True: 230k, False: 1.54k]
  ------------------
  464|   230k|        node_t node = stack[sp - 1];
  465|   230k|        node_t ch = node_first_child(node);
  466|   230k|        if (ch) {
  ------------------
  |  Branch (466:13): [True: 42.1k, False: 188k]
  ------------------
  467|  42.1k|            int di = node_detach(node, ch);
  468|  42.1k|            if (di < 0) {
  ------------------
  |  Branch (468:17): [True: 0, False: 42.1k]
  ------------------
  469|      0|                free(stack);
  470|      0|                return di;
  471|      0|            }
  472|       |
  473|  42.1k|            if (sp == cap) {
  ------------------
  |  Branch (473:17): [True: 338, False: 41.8k]
  ------------------
  474|    338|                cap += 64;
  475|    338|                node_t *tmp = (node_t*)realloc(stack, cap * sizeof(*stack));
  476|    338|                if (!tmp) {
  ------------------
  |  Branch (476:21): [True: 0, False: 338]
  ------------------
  477|      0|                    free(stack);
  478|      0|                    return NODE_ERR_NO_MEM;
  ------------------
  |  |   38|      0|#define NODE_ERR_NO_MEM       -2
  ------------------
  479|      0|                }
  480|    338|                stack = tmp;
  481|    338|            }
  482|  42.1k|            stack[sp++] = ch;
  483|  42.1k|            continue;
  484|  42.1k|        }
  485|       |
  486|   188k|        plist_data_t data = plist_get_data(node);
  487|   188k|        plist_free_data(data);
  488|   188k|        node->data = NULL;
  489|       |
  490|   188k|        node_destroy(node);
  491|       |
  492|   188k|        sp--;
  493|   188k|    }
  494|       |
  495|  1.54k|    free(stack);
  496|  1.54k|    return NODE_ERR_SUCCESS;
  ------------------
  |  |   36|  1.54k|#define NODE_ERR_SUCCESS       0
  ------------------
  497|  1.54k|}
plist.c:_plist_array_post_insert:
  986|  59.0k|{
  987|  59.0k|    ptrarray_t *pa = (ptrarray_t*)((plist_data_t)((node_t)node)->data)->hashtable;
  988|  59.0k|    if (pa) {
  ------------------
  |  Branch (988:9): [True: 10.8k, False: 48.2k]
  ------------------
  989|       |        /* store pointer to item in array */
  990|  10.8k|        ptr_array_insert(pa, item, n);
  991|  10.8k|        return;
  992|  10.8k|    }
  993|       |
  994|  48.2k|    if (((node_t)node)->count > 100) {
  ------------------
  |  Branch (994:9): [True: 113, False: 48.1k]
  ------------------
  995|       |       /* make new lookup array */
  996|    113|       pa = ptr_array_new(128);
  997|    113|       plist_t current = NULL;
  998|    113|       for (current = (plist_t)node_first_child((node_t)node);
  999|  11.5k|            pa && current;
  ------------------
  |  Branch (999:13): [True: 11.5k, False: 0]
  |  Branch (999:19): [True: 11.4k, False: 113]
  ------------------
 1000|  11.4k|            current = (plist_t)node_next_sibling((node_t)current))
 1001|  11.4k|       {
 1002|  11.4k|           ptr_array_add(pa, current);
 1003|  11.4k|       }
 1004|    113|       ((plist_data_t)((node_t)node)->data)->hashtable = pa;
 1005|    113|    }
 1006|  48.2k|}
plist.c:plist_new_key:
  551|  64.6k|{
  552|  64.6k|    plist_data_t data = plist_new_plist_data();
  553|  64.6k|    if (!data) {
  ------------------
  |  Branch (553:9): [True: 0, False: 64.6k]
  ------------------
  554|      0|        PLIST_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  555|      0|        return NULL;
  556|      0|    }
  557|  64.6k|    data->type = PLIST_KEY;
  558|  64.6k|    data->strval = strdup(val);
  559|  64.6k|    if (!data->strval) {
  ------------------
  |  Branch (559:9): [True: 0, False: 64.6k]
  ------------------
  560|      0|        plist_free_data(data);
  561|      0|        PLIST_ERR("%s: strdup failed\n", __func__);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  562|      0|        return NULL;
  563|  64.6k|    } else {
  564|  64.6k|        data->length = strlen(val);
  565|  64.6k|    }
  566|  64.6k|    return plist_new_node(data);
  567|  64.6k|}
plist.c:dict_key_hash:
  365|  62.1k|{
  366|  62.1k|    plist_data_t keydata = (plist_data_t)data;
  367|  62.1k|    unsigned int hash = 5381;
  368|  62.1k|    size_t i;
  369|  62.1k|    char *str = keydata->strval;
  370|   163k|    for (i = 0; i < keydata->length; str++, i++) {
  ------------------
  |  Branch (370:17): [True: 101k, False: 62.1k]
  ------------------
  371|   101k|        hash = ((hash << 5) + hash) + *str;
  372|   101k|    }
  373|  62.1k|    return hash;
  374|  62.1k|}
plist.c:dict_key_compare:
  377|  3.45k|{
  378|  3.45k|    plist_data_t data_a = (plist_data_t)a;
  379|  3.45k|    plist_data_t data_b = (plist_data_t)b;
  380|  3.45k|    if (data_a->strval == NULL || data_b->strval == NULL) {
  ------------------
  |  Branch (380:9): [True: 0, False: 3.45k]
  |  Branch (380:35): [True: 0, False: 3.45k]
  ------------------
  381|      0|        return FALSE;
  ------------------
  |  |   32|      0|#define FALSE 0
  ------------------
  382|      0|    }
  383|  3.45k|    if (data_a->length != data_b->length) {
  ------------------
  |  Branch (383:9): [True: 1.64k, False: 1.80k]
  ------------------
  384|  1.64k|        return FALSE;
  ------------------
  |  |   32|  1.64k|#define FALSE 0
  ------------------
  385|  1.64k|    }
  386|  1.80k|    return (strcmp(data_a->strval, data_b->strval) == 0) ? TRUE : FALSE;
  ------------------
  |  |   28|  1.13k|#define TRUE 1
  ------------------
                  return (strcmp(data_a->strval, data_b->strval) == 0) ? TRUE : FALSE;
  ------------------
  |  |   32|    674|#define FALSE 0
  ------------------
  |  Branch (386:12): [True: 1.13k, False: 674]
  ------------------
  387|  3.45k|}

ptr_array_new:
   25|    113|{
   26|    113|	ptrarray_t *pa = (ptrarray_t*)malloc(sizeof(ptrarray_t));
   27|    113|	pa->pdata = (void**)malloc(sizeof(void*) * capacity);
   28|    113|	pa->capacity = capacity;
   29|    113|	pa->capacity_step = (capacity > 4096) ? 4096 : capacity;
  ------------------
  |  Branch (29:22): [True: 0, False: 113]
  ------------------
   30|    113|	pa->len = 0;
   31|    113|	return pa;
   32|    113|}
ptr_array_free:
   35|  57.8k|{
   36|  57.8k|	if (!pa) return;
  ------------------
  |  Branch (36:6): [True: 57.7k, False: 113]
  ------------------
   37|    113|	if (pa->pdata) {
  ------------------
  |  Branch (37:6): [True: 113, False: 0]
  ------------------
   38|    113|		free(pa->pdata);
   39|    113|	}
   40|    113|	free(pa);
   41|    113|}
ptr_array_insert:
   44|  22.2k|{
   45|  22.2k|	if (!pa || !pa->pdata) return;
  ------------------
  |  Branch (45:6): [True: 0, False: 22.2k]
  |  Branch (45:13): [True: 0, False: 22.2k]
  ------------------
   46|  22.2k|	long remaining = pa->capacity-pa->len;
   47|  22.2k|	if (remaining == 0) {
  ------------------
  |  Branch (47:6): [True: 86, False: 22.1k]
  ------------------
   48|     86|		pa->pdata = (void**)realloc(pa->pdata, sizeof(void*) * (pa->capacity + pa->capacity_step));
   49|     86|		pa->capacity += pa->capacity_step;
   50|     86|	}
   51|  22.2k|	if (array_index < 0 || array_index >= pa->len) {
  ------------------
  |  Branch (51:6): [True: 22.2k, False: 0]
  |  Branch (51:25): [True: 0, False: 0]
  ------------------
   52|  22.2k|		pa->pdata[pa->len] = data;
   53|  22.2k|	} else {
   54|      0|		memmove(&pa->pdata[array_index+1], &pa->pdata[array_index], (pa->len-array_index) * sizeof(void*));
   55|      0|		pa->pdata[array_index] = data;
   56|      0|	}
   57|  22.2k|	pa->len++;
   58|  22.2k|}
ptr_array_add:
   61|  11.4k|{
   62|  11.4k|	ptr_array_insert(pa, data, -1);
   63|  11.4k|}

plist_xml_init:
   91|      2|{
   92|       |    /* init XML stuff */
   93|      2|#ifdef DEBUG
   94|      2|    char *env_debug = getenv("PLIST_XML_DEBUG");
   95|      2|    if (env_debug && !strcmp(env_debug, "1")) {
  ------------------
  |  Branch (95:9): [True: 0, False: 2]
  |  Branch (95:22): [True: 0, False: 0]
  ------------------
   96|      0|        plist_xml_debug = 1;
   97|      0|    }
   98|      2|#endif
   99|      2|}

