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

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

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

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|    230|{
   25|    230|	hashtable_t* ht = (hashtable_t*)malloc(sizeof(hashtable_t));
   26|    230|	int i;
   27|   942k|	for (i = 0; i < 4096; i++) {
  ------------------
  |  Branch (27:14): [True: 942k, False: 230]
  ------------------
   28|       |		ht->entries[i] = NULL;
   29|   942k|	}
   30|    230|	ht->count = 0;
   31|    230|	ht->hash_func = hash_func;
   32|    230|	ht->compare_func = compare_func;
   33|    230|	ht->free_func = free_func;
   34|    230|	return ht;
   35|    230|}
hash_table_destroy:
   38|  12.3k|{
   39|  12.3k|	if (!ht) return;
  ------------------
  |  Branch (39:6): [True: 12.1k, False: 230]
  ------------------
   40|       |
   41|    230|	int i = 0;
   42|   942k|	for (i = 0; i < 4096; i++) {
  ------------------
  |  Branch (42:14): [True: 942k, False: 230]
  ------------------
   43|   942k|		if (ht->entries[i]) {
  ------------------
  |  Branch (43:7): [True: 56.9k, False: 885k]
  ------------------
   44|  56.9k|			hashentry_t* e = ht->entries[i];
   45|   115k|			while (e) {
  ------------------
  |  Branch (45:11): [True: 58.1k, False: 56.9k]
  ------------------
   46|  58.1k|				if (ht->free_func) {
  ------------------
  |  Branch (46:9): [True: 0, False: 58.1k]
  ------------------
   47|      0|					ht->free_func(e->value);
   48|      0|				}
   49|  58.1k|				hashentry_t* old = e;
   50|  58.1k|				e = e->next;
   51|  58.1k|				free(old);
   52|  58.1k|			}
   53|  56.9k|		}
   54|   942k|	}
   55|    230|	free(ht);
   56|    230|}
hash_table_insert:
   59|  58.7k|{
   60|  58.7k|	if (!ht || !key) return;
  ------------------
  |  Branch (60:6): [True: 0, False: 58.7k]
  |  Branch (60:13): [True: 0, False: 58.7k]
  ------------------
   61|       |
   62|  58.7k|	unsigned int hash = ht->hash_func(key);
   63|       |
   64|  58.7k|	int idx0 = hash & 0xFFF;
   65|       |
   66|       |	// get the idx0 list
   67|  58.7k|	hashentry_t* e = ht->entries[idx0];
   68|  60.5k|	while (e) {
  ------------------
  |  Branch (68:9): [True: 2.41k, False: 58.1k]
  ------------------
   69|  2.41k|		if (ht->compare_func(e->key, key)) {
  ------------------
  |  Branch (69:7): [True: 573, False: 1.83k]
  ------------------
   70|       |			// element already present. replace value.
   71|    573|			e->value = value;
   72|    573|			return;
   73|    573|		}
   74|  1.83k|		e = e->next;
   75|  1.83k|	}
   76|       |
   77|       |	// if we get here, the element is not yet in the list.
   78|       |
   79|       |	// make a new entry.
   80|  58.1k|	hashentry_t* entry = (hashentry_t*)malloc(sizeof(hashentry_t));
   81|  58.1k|	entry->key = key;
   82|  58.1k|	entry->value = value;
   83|  58.1k|	if (!ht->entries[idx0]) {
  ------------------
  |  Branch (83:6): [True: 56.9k, False: 1.19k]
  ------------------
   84|       |		// first entry
   85|  56.9k|		entry->next = NULL;
   86|  56.9k|	} else {
   87|       |		// add to list
   88|  1.19k|		entry->next = ht->entries[idx0];
   89|  1.19k|	}
   90|  58.1k|	ht->entries[idx0] = entry;
   91|  58.1k|	ht->count++;
   92|  58.1k|}
hash_table_lookup:
   95|    977|{
   96|    977|	if (!ht || !key) return NULL;
  ------------------
  |  Branch (96:6): [True: 0, False: 977]
  |  Branch (96:13): [True: 0, False: 977]
  ------------------
   97|    977|	unsigned int hash = ht->hash_func(key);
   98|       |
   99|    977|	int idx0 = hash & 0xFFF;
  100|       |
  101|    977|	hashentry_t* e = ht->entries[idx0];
  102|  1.47k|	while (e) {
  ------------------
  |  Branch (102:9): [True: 1.07k, False: 404]
  ------------------
  103|  1.07k|		if (ht->compare_func(e->key, key)) {
  ------------------
  |  Branch (103:7): [True: 573, False: 499]
  ------------------
  104|    573|			return e->value;
  105|    573|		}
  106|    499|		e = e->next;
  107|    499|	}
  108|    404|	return NULL;
  109|    977|}

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.33k|{
  898|  2.33k|    if (!plist) {
  ------------------
  |  Branch (898:9): [True: 0, False: 2.33k]
  ------------------
  899|      0|        return PLIST_ERR_INVALID_ARG;
  900|      0|    }
  901|  2.33k|    *plist = NULL;
  902|  2.33k|    if (!json || (length == 0)) {
  ------------------
  |  Branch (902:9): [True: 0, False: 2.33k]
  |  Branch (902:18): [True: 0, False: 2.33k]
  ------------------
  903|      0|        return PLIST_ERR_INVALID_ARG;
  904|      0|    }
  905|       |
  906|  2.33k|    jsmn_parser parser;
  907|  2.33k|    jsmn_init(&parser);
  908|  2.33k|    unsigned int maxtoks = 256;
  909|  2.33k|    unsigned int curtoks = 0;
  910|  2.33k|    int r = 0;
  911|  2.33k|    jsmntok_t *tokens = NULL;
  912|       |
  913|  12.7k|    do {
  914|  12.7k|        jsmntok_t* newtokens = (jsmntok_t*)realloc(tokens, sizeof(jsmntok_t)*maxtoks);
  915|  12.7k|        if (!newtokens) {
  ------------------
  |  Branch (915:13): [True: 0, False: 12.7k]
  ------------------
  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|  12.7k|        memset((unsigned char*)newtokens + sizeof(jsmntok_t)*curtoks, '\0', sizeof(jsmntok_t)*(maxtoks-curtoks));
  921|  12.7k|        tokens = newtokens;
  922|  12.7k|        curtoks = maxtoks;
  923|       |
  924|  12.7k|        r = jsmn_parse(&parser, json, length, tokens, maxtoks);
  925|  12.7k|        if (r == JSMN_ERROR_NOMEM) {
  ------------------
  |  Branch (925:13): [True: 10.4k, False: 2.33k]
  ------------------
  926|  10.4k|            if (maxtoks > (unsigned int)INT_MAX - 16) {
  ------------------
  |  Branch (926:17): [True: 0, False: 10.4k]
  ------------------
  927|      0|                free(tokens);
  928|      0|                return PLIST_ERR_NO_MEM;
  929|      0|            }
  930|  10.4k|            maxtoks+=16;
  931|  10.4k|            continue;
  932|  10.4k|        } else if (r < 0) {
  ------------------
  |  Branch (932:20): [True: 378, False: 1.95k]
  ------------------
  933|    378|            break;
  934|    378|        }
  935|  12.7k|    } while (r == JSMN_ERROR_NOMEM);
  ------------------
  |  Branch (935:14): [True: 10.4k, False: 1.95k]
  ------------------
  936|       |
  937|  2.33k|    switch(r) {
  938|      0|        case JSMN_ERROR_NOMEM:
  ------------------
  |  Branch (938:9): [True: 0, False: 2.33k]
  ------------------
  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|     68|        case JSMN_ERROR_INVAL:
  ------------------
  |  Branch (942:9): [True: 68, False: 2.26k]
  ------------------
  943|     68|            PLIST_JSON_ERR("%s: Invalid character inside JSON string\n", __func__);
  ------------------
  |  |   48|     68|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 68]
  |  |  ------------------
  ------------------
  944|     68|            free(tokens);
  945|     68|            return PLIST_ERR_PARSE;
  946|    310|        case JSMN_ERROR_PART:
  ------------------
  |  Branch (946:9): [True: 310, False: 2.02k]
  ------------------
  947|    310|            PLIST_JSON_ERR("%s: Incomplete JSON, more bytes expected\n", __func__);
  ------------------
  |  |   48|    310|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 310]
  |  |  ------------------
  ------------------
  948|    310|            free(tokens);
  949|    310|            return PLIST_ERR_PARSE;
  950|      0|        case JSMN_ERROR_LIMIT:
  ------------------
  |  Branch (950:9): [True: 0, False: 2.33k]
  ------------------
  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.95k|        default:
  ------------------
  |  Branch (954:9): [True: 1.95k, False: 378]
  ------------------
  955|  1.95k|            break;
  956|  2.33k|    }
  957|       |
  958|  1.95k|    int startindex = 0;
  959|  1.95k|    jsmntok_info_t ti = { tokens, parser.toknext, PLIST_ERR_SUCCESS };
  960|  1.95k|    switch (tokens[startindex].type) {
  961|    714|        case JSMN_PRIMITIVE:
  ------------------
  |  Branch (961:9): [True: 714, False: 1.24k]
  ------------------
  962|    714|            *plist = parse_primitive(json, &ti, &startindex);
  963|    714|            break;
  964|    190|        case JSMN_STRING:
  ------------------
  |  Branch (964:9): [True: 190, False: 1.76k]
  ------------------
  965|    190|            *plist = parse_string(json, &ti, &startindex);
  966|    190|            break;
  967|    446|        case JSMN_ARRAY:
  ------------------
  |  Branch (967:9): [True: 446, False: 1.51k]
  ------------------
  968|    446|            *plist = parse_array(json, &ti, &startindex, 0);
  969|    446|            break;
  970|    609|        case JSMN_OBJECT:
  ------------------
  |  Branch (970:9): [True: 609, False: 1.35k]
  ------------------
  971|    609|            *plist = parse_object(json, &ti, &startindex, 0);
  972|    609|            break;
  973|      0|        default:
  ------------------
  |  Branch (973:9): [True: 0, False: 1.95k]
  ------------------
  974|      0|            break;
  975|  1.95k|    }
  976|  1.95k|    free(tokens);
  977|  1.95k|    if (!*plist) {
  ------------------
  |  Branch (977:9): [True: 486, False: 1.47k]
  ------------------
  978|    486|        return (ti.err != PLIST_ERR_SUCCESS) ? ti.err : PLIST_ERR_PARSE;
  ------------------
  |  Branch (978:16): [True: 144, False: 342]
  ------------------
  979|    486|    }
  980|  1.47k|    return PLIST_ERR_SUCCESS;
  981|  1.95k|}
jplist.c:parse_primitive:
  545|  29.2k|{
  546|  29.2k|    if (ti->tokens[*index].type != JSMN_PRIMITIVE) {
  ------------------
  |  Branch (546:9): [True: 0, False: 29.2k]
  ------------------
  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|  29.2k|    plist_t val = NULL;
  551|  29.2k|    const char* str_val = js + ti->tokens[*index].start;
  552|  29.2k|    const char* str_end = js + ti->tokens[*index].end;
  553|  29.2k|    size_t str_len = ti->tokens[*index].end - ti->tokens[*index].start;
  554|  29.2k|    if (!strncmp("false", str_val, str_len)) {
  ------------------
  |  Branch (554:9): [True: 4.08k, False: 25.1k]
  ------------------
  555|  4.08k|        val = plist_new_bool(0);
  556|  25.1k|    } else if (!strncmp("true", str_val, str_len)) {
  ------------------
  |  Branch (556:16): [True: 2.86k, False: 22.2k]
  ------------------
  557|  2.86k|        val = plist_new_bool(1);
  558|  22.2k|    } else if (!strncmp("null", str_val, str_len)) {
  ------------------
  |  Branch (558:16): [True: 15.2k, False: 6.96k]
  ------------------
  559|  15.2k|        plist_data_t data = plist_new_plist_data();
  560|  15.2k|        if (!data) {
  ------------------
  |  Branch (560:13): [True: 0, False: 15.2k]
  ------------------
  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|  15.2k|        data->type = PLIST_NULL;
  565|  15.2k|        val = plist_new_node(data);
  566|  15.2k|    } else if (isdigit(str_val[0]) || (str_val[0] == '-' && str_val+1 < str_end && isdigit(str_val[1]))) {
  ------------------
  |  Branch (566:16): [True: 5.99k, False: 971]
  |  Branch (566:40): [True: 807, False: 164]
  |  Branch (566:61): [True: 800, False: 7]
  |  Branch (566:84): [True: 793, False: 7]
  ------------------
  567|  6.78k|        char* endp = (char*)str_val;
  568|  6.78k|        int is_neg = (str_val[0] == '-');
  569|  6.78k|        int64_t intpart = parse_decimal(str_val, str_end, &endp);
  570|  6.78k|        if (endp >= str_end) {
  ------------------
  |  Branch (570:13): [True: 4.30k, False: 2.48k]
  ------------------
  571|       |            /* integer */
  572|  4.30k|            if (is_neg || intpart <= INT64_MAX) {
  ------------------
  |  Branch (572:17): [True: 493, False: 3.81k]
  |  Branch (572:27): [True: 3.81k, False: 0]
  ------------------
  573|  4.30k|                val = plist_new_int(intpart);
  574|  4.30k|            } else {
  575|      0|                val = plist_new_uint((uint64_t)intpart);
  576|      0|            }
  577|  4.30k|        } 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: 555, False: 1.92k]
  |  Branch (577:37): [True: 553, False: 2]
  |  Branch (577:57): [True: 552, False: 1]
  |  Branch (577:82): [True: 1.47k, False: 452]
  |  Branch (577:98): [True: 428, False: 24]
  |  Branch (577:115): [True: 1.88k, False: 17]
  |  Branch (577:136): [True: 688, False: 1.20k]
  |  Branch (577:160): [True: 909, False: 292]
  |  Branch (577:182): [True: 279, False: 13]
  |  Branch (577:205): [True: 1.17k, False: 14]
  |  Branch (577:225): [True: 1.17k, False: 1]
  ------------------
  578|       |            /* floating point */
  579|  2.41k|            double dval = (double)intpart;
  580|  2.41k|            char* fendp = endp;
  581|  2.41k|            int err = 0;
  582|  2.41k|            do {
  583|  2.41k|                if (*endp == '.') {
  ------------------
  |  Branch (583:21): [True: 552, False: 1.86k]
  ------------------
  584|    552|                    fendp++;
  585|    552|                    double frac = 0;
  586|    552|                    double p = 0.1;
  587|  1.51k|                    while (fendp < str_end && isdigit(*fendp)) {
  ------------------
  |  Branch (587:28): [True: 1.03k, False: 481]
  |  Branch (587:47): [True: 963, False: 71]
  ------------------
  588|    963|                        frac = frac + (*fendp - '0') * p;
  589|    963|                        p *= 0.1;
  590|    963|                        fendp++;
  591|    963|                    }
  592|    552|                    if (is_neg) {
  ------------------
  |  Branch (592:25): [True: 298, False: 254]
  ------------------
  593|    298|                        dval -= frac;
  594|    298|                    } else {
  595|    254|                        dval += frac;
  596|    254|                    }
  597|    552|                }
  598|  2.41k|                if (fendp >= str_end) {
  ------------------
  |  Branch (598:21): [True: 481, False: 1.93k]
  ------------------
  599|    481|                    break;
  600|    481|                }
  601|  1.93k|                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.92k, False: 3]
  |  Branch (601:43): [True: 1.50k, False: 429]
  |  Branch (601:60): [True: 415, False: 14]
  |  Branch (601:79): [True: 688, False: 1.22k]
  |  Branch (601:104): [True: 904, False: 323]
  |  Branch (601:127): [True: 315, False: 8]
  |  Branch (601:151): [True: 1.21k, False: 1]
  |  Branch (601:172): [True: 1.21k, False: 2]
  ------------------
  602|  1.90k|                    int64_t exp = parse_decimal(fendp+1, str_end, &fendp);
  603|  1.90k|                    dval = dval * pow(10, (double)exp);
  604|  1.90k|                } else {
  605|     28|                    PLIST_JSON_ERR("%s: invalid character at offset %d when parsing floating point value\n", __func__, (int)(fendp - js));
  ------------------
  |  |   48|     28|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 28]
  |  |  ------------------
  ------------------
  606|     28|                    err++;
  607|     28|                }
  608|  1.93k|            } while (0);
  ------------------
  |  Branch (608:22): [Folded, False: 1.93k]
  ------------------
  609|  2.41k|            if (!err) {
  ------------------
  |  Branch (609:17): [True: 2.38k, False: 28]
  ------------------
  610|  2.38k|                if (isinf(dval) || isnan(dval)) {
  ------------------
  |  Branch (610:21): [True: 127, False: 2.25k]
  |  Branch (610:36): [True: 30, False: 2.22k]
  ------------------
  611|    157|                   PLIST_JSON_ERR("%s: unrepresentable floating point value at offset %d when parsing numerical value\n", __func__, (int)(str_val - js));
  ------------------
  |  |   48|    157|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 157]
  |  |  ------------------
  ------------------
  612|  2.22k|                } else {
  613|  2.22k|                    val = plist_new_real(dval);
  614|  2.22k|                }
  615|  2.38k|            }
  616|  2.41k|        } else {
  617|     69|            PLIST_JSON_ERR("%s: invalid character at offset %d when parsing numerical value\n", __func__, (int)(endp - js));
  ------------------
  |  |   48|     69|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 69]
  |  |  ------------------
  ------------------
  618|     69|        }
  619|  6.78k|    } else {
  620|    178|        PLIST_JSON_ERR("%s: invalid primitive value '%.*s' encountered\n", __func__, (int)str_len, str_val);
  ------------------
  |  |   48|    178|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 178]
  |  |  ------------------
  ------------------
  621|    178|    }
  622|  29.2k|    if (!val) {
  ------------------
  |  Branch (622:9): [True: 432, False: 28.7k]
  ------------------
  623|    432|        PLIST_JSON_ERR("%s: failed to create node\n", __func__);
  ------------------
  |  |   48|    432|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 432]
  |  |  ------------------
  ------------------
  624|    432|        return NULL;
  625|    432|    }
  626|  28.7k|    (*index)++;
  627|  28.7k|    return val;
  628|  29.2k|}
jplist.c:parse_decimal:
  499|  8.69k|{
  500|  8.69k|    const uint64_t po10i_limit = INT64_MAX / 10;
  501|  8.69k|    uint64_t MAX = INT64_MAX;
  502|  8.69k|    uint64_t x = 0;
  503|  8.69k|    int is_neg = 0;
  504|  8.69k|    *endp = (char*)str;
  505|       |
  506|  8.69k|    if (str[0] == '-') {
  ------------------
  |  Branch (506:9): [True: 1.69k, False: 6.99k]
  ------------------
  507|  1.69k|        is_neg = 1;
  508|  1.69k|        (*endp)++;
  509|  6.99k|    } else if (str[0] == '+') {
  ------------------
  |  Branch (509:16): [True: 314, False: 6.68k]
  ------------------
  510|    314|        (*endp)++;
  511|    314|    }
  512|  8.69k|    if (is_neg) {
  ------------------
  |  Branch (512:9): [True: 1.69k, False: 6.99k]
  ------------------
  513|  1.69k|        MAX++;
  514|  1.69k|    }
  515|  44.3k|    while (*endp < str_end && isdigit(**endp)) {
  ------------------
  |  Branch (515:12): [True: 39.4k, False: 4.93k]
  |  Branch (515:31): [True: 36.8k, False: 2.55k]
  ------------------
  516|  36.8k|        if (x > po10i_limit) {
  ------------------
  |  Branch (516:13): [True: 654, False: 36.2k]
  ------------------
  517|    654|            x = MAX;
  518|    654|            break;
  519|    654|        }
  520|  36.2k|        x = x * 10;
  521|  36.2k|        unsigned int add = (**endp - '0');
  522|  36.2k|        if (x + add > MAX) {
  ------------------
  |  Branch (522:13): [True: 551, False: 35.6k]
  ------------------
  523|    551|            x = MAX;
  524|    551|            break;
  525|    551|        }
  526|  35.6k|        x += add;
  527|  35.6k|        (*endp)++;
  528|  35.6k|    }
  529|       |
  530|       |    // swallow the rest of the digits in case we dropped out early
  531|  10.6k|    while (*endp < str_end && isdigit(**endp)) (*endp)++;
  ------------------
  |  Branch (531:12): [True: 4.48k, False: 6.13k]
  |  Branch (531:31): [True: 1.92k, False: 2.55k]
  ------------------
  532|       |
  533|  8.69k|    int64_t result = x;
  534|  8.69k|    if (is_neg) {
  ------------------
  |  Branch (534:9): [True: 1.69k, False: 6.99k]
  ------------------
  535|  1.69k|        if (x == MAX) {
  ------------------
  |  Branch (535:13): [True: 771, False: 924]
  ------------------
  536|    771|            result = INT64_MIN;
  537|    924|        } else {
  538|    924|            result = -(int64_t)x;
  539|    924|        }
  540|  1.69k|    }
  541|  8.69k|    return result;
  542|  8.69k|}
jplist.c:parse_string:
  710|  33.8k|{
  711|  33.8k|    if (ti->tokens[*index].type != JSMN_STRING) {
  ------------------
  |  Branch (711:9): [True: 0, False: 33.8k]
  ------------------
  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|  33.8k|    size_t str_len = 0; ;
  717|  33.8k|    char* strval = unescape_string(js + ti->tokens[*index].start, ti->tokens[*index].end - ti->tokens[*index].start, &str_len);
  718|  33.8k|    if (!strval) {
  ------------------
  |  Branch (718:9): [True: 23, False: 33.8k]
  ------------------
  719|     23|        return NULL;
  720|     23|    }
  721|  33.8k|    plist_t node;
  722|       |
  723|  33.8k|    plist_data_t data = plist_new_plist_data();
  724|  33.8k|    if (!data) {
  ------------------
  |  Branch (724:9): [True: 0, False: 33.8k]
  ------------------
  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|  33.8k|    data->type = PLIST_STRING;
  730|  33.8k|    data->strval = strval;
  731|  33.8k|    data->length = str_len;
  732|  33.8k|    node = plist_new_node(data);
  733|  33.8k|    if (!node) {
  ------------------
  |  Branch (733:9): [True: 0, False: 33.8k]
  ------------------
  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|  33.8k|    (*index)++;
  740|  33.8k|    return node;
  741|  33.8k|}
jplist.c:unescape_string:
  631|   100k|{
  632|   100k|    char* strval = strndup(str_val, str_len);
  633|   100k|    if (!strval) return NULL;
  ------------------
  |  Branch (633:9): [True: 0, False: 100k]
  ------------------
  634|   100k|    size_t i = 0;
  635|   237k|    while (i < str_len) {
  ------------------
  |  Branch (635:12): [True: 137k, False: 100k]
  ------------------
  636|   137k|        if (strval[i] == '\\' && i < str_len-1) {
  ------------------
  |  Branch (636:13): [True: 3.64k, False: 133k]
  |  Branch (636:34): [True: 3.64k, False: 0]
  ------------------
  637|  3.64k|            switch (strval[i+1]) {
  638|  1.31k|                case '\"': case '/' : case '\\' : case 'b' :
  ------------------
  |  Branch (638:17): [True: 244, False: 3.40k]
  |  Branch (638:28): [True: 199, False: 3.44k]
  |  Branch (638:39): [True: 458, False: 3.18k]
  |  Branch (638:51): [True: 410, False: 3.23k]
  ------------------
  639|  2.77k|                case 'f' : case 'r' : case 'n'  : case 't' :
  ------------------
  |  Branch (639:17): [True: 390, False: 3.25k]
  |  Branch (639:28): [True: 229, False: 3.41k]
  |  Branch (639:39): [True: 531, False: 3.11k]
  |  Branch (639:51): [True: 316, False: 3.32k]
  ------------------
  640|  2.77k|                    memmove(strval+i, strval+i+1, str_len - (i+1));
  641|  2.77k|                    str_len--;
  642|  2.77k|                    switch (strval[i]) {
  643|    410|                        case 'b':
  ------------------
  |  Branch (643:25): [True: 410, False: 2.36k]
  ------------------
  644|    410|                            strval[i] = '\b';
  645|    410|                            break;
  646|    390|                        case 'f':
  ------------------
  |  Branch (646:25): [True: 390, False: 2.38k]
  ------------------
  647|    390|                            strval[i] = '\f';
  648|    390|                            break;
  649|    229|                        case 'r':
  ------------------
  |  Branch (649:25): [True: 229, False: 2.54k]
  ------------------
  650|    229|                            strval[i] = '\r';
  651|    229|                            break;
  652|    531|                        case 'n':
  ------------------
  |  Branch (652:25): [True: 531, False: 2.24k]
  ------------------
  653|    531|                            strval[i] = '\n';
  654|    531|                            break;
  655|    316|                        case 't':
  ------------------
  |  Branch (655:25): [True: 316, False: 2.46k]
  ------------------
  656|    316|                            strval[i] = '\t';
  657|    316|                            break;
  658|    901|                        default:
  ------------------
  |  Branch (658:25): [True: 901, False: 1.87k]
  ------------------
  659|    901|                            break;
  660|  2.77k|                    }
  661|  2.77k|                    break;
  662|  2.77k|                case 'u': {
  ------------------
  |  Branch (662:17): [True: 867, False: 2.77k]
  ------------------
  663|    867|                    unsigned int val = 0;
  664|    867|                    if (str_len-(i+2) < 4) {
  ------------------
  |  Branch (664:25): [True: 10, False: 857]
  ------------------
  665|     10|                        PLIST_JSON_ERR("%s: invalid escape sequence '%s' (too short)\n", __func__, strval+i);
  ------------------
  |  |   48|     10|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 10]
  |  |  ------------------
  ------------------
  666|     10|                        free(strval);
  667|     10|                        return NULL;
  668|     10|                    }
  669|    857|                    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: 852, False: 5]
  |  Branch (669:52): [True: 849, False: 3]
  |  Branch (669:77): [True: 846, False: 3]
  |  Branch (669:102): [True: 841, False: 5]
  |  Branch (669:128): [True: 0, False: 841]
  ------------------
  670|     16|                        PLIST_JSON_ERR("%s: invalid escape sequence '%.*s'\n", __func__, 6, strval+i);
  ------------------
  |  |   48|     16|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 16]
  |  |  ------------------
  ------------------
  671|     16|                        free(strval);
  672|     16|                        return NULL;
  673|     16|                    }
  674|    841|                    int bytelen = 0;
  675|    841|                    if (val >= 0x800) {
  ------------------
  |  Branch (675:25): [True: 282, False: 559]
  ------------------
  676|       |                        /* three bytes */
  677|    282|                        strval[i]   = (char)(0xE0 + ((val >> 12) & 0xF));
  678|    282|                        strval[i+1] = (char)(0x80 + ((val >> 6) & 0x3F));
  679|    282|                        strval[i+2] = (char)(0x80 + (val & 0x3F));
  680|    282|                        bytelen = 3;
  681|    559|                    } else if (val >= 0x80) {
  ------------------
  |  Branch (681:32): [True: 330, False: 229]
  ------------------
  682|       |                        /* two bytes */
  683|    330|                        strval[i]   = (char)(0xC0 + ((val >> 6) & 0x1F));
  684|    330|                        strval[i+1] = (char)(0x80 + (val & 0x3F));
  685|    330|                        bytelen = 2;
  686|    330|                    } else {
  687|       |                        /* one byte */
  688|    229|                        strval[i] = (char)(val & 0x7F);
  689|    229|                        bytelen = 1;
  690|    229|                    }
  691|    841|                    memmove(strval+i+bytelen, strval+i+6, str_len - (i+5));
  692|    841|                    str_len -= (6-bytelen);
  693|    841|                }   break;
  694|      0|                default:
  ------------------
  |  Branch (694:17): [True: 0, False: 3.64k]
  ------------------
  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|  3.64k|            }
  699|  3.64k|        }
  700|   137k|        i++;
  701|   137k|    }
  702|   100k|    strval[str_len] = '\0';
  703|   100k|    if (new_len) {
  ------------------
  |  Branch (703:9): [True: 33.8k, False: 66.5k]
  ------------------
  704|  33.8k|        *new_len = str_len;
  705|  33.8k|    }
  706|   100k|    return strval;
  707|   100k|}
jplist.c:parse_array:
  746|  53.3k|{
  747|  53.3k|    if (ti->tokens[*index].type != JSMN_ARRAY) {
  ------------------
  |  Branch (747:9): [True: 0, False: 53.3k]
  ------------------
  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|  53.3k|    if (depth > PLIST_MAX_NESTING_DEPTH) {
  ------------------
  |  |   56|  53.3k|#define PLIST_MAX_NESTING_DEPTH NODE_MAX_DEPTH
  |  |  ------------------
  |  |  |  |   33|  53.3k|#define NODE_MAX_DEPTH 512
  |  |  ------------------
  ------------------
  |  Branch (752:9): [True: 1, False: 53.3k]
  ------------------
  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|  53.3k|    plist_t arr = plist_new_array();
  758|  53.3k|    if (!arr) {
  ------------------
  |  Branch (758:9): [True: 0, False: 53.3k]
  ------------------
  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|  53.3k|    size_t num_tokens = ti->tokens[*index].size;
  764|  53.3k|    size_t num;
  765|  53.3k|    int j = (*index)+1;
  766|   107k|    for (num = 0; num < num_tokens; num++) {
  ------------------
  |  Branch (766:19): [True: 60.2k, False: 47.5k]
  ------------------
  767|  60.2k|        if (j >= ti->count) {
  ------------------
  |  Branch (767:13): [True: 0, False: 60.2k]
  ------------------
  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|  60.2k|        plist_t val = NULL;
  774|  60.2k|        switch (ti->tokens[j].type) {
  775|    569|            case JSMN_OBJECT:
  ------------------
  |  Branch (775:13): [True: 569, False: 59.6k]
  ------------------
  776|    569|                val = parse_object(js, ti, &j, depth+1);
  777|    569|                break;
  778|  32.3k|            case JSMN_ARRAY:
  ------------------
  |  Branch (778:13): [True: 32.3k, False: 27.9k]
  ------------------
  779|  32.3k|                val = parse_array(js, ti, &j, depth+1);
  780|  32.3k|                break;
  781|  1.02k|            case JSMN_STRING:
  ------------------
  |  Branch (781:13): [True: 1.02k, False: 59.2k]
  ------------------
  782|  1.02k|                val = parse_string(js, ti, &j);
  783|  1.02k|                break;
  784|  26.3k|            case JSMN_PRIMITIVE:
  ------------------
  |  Branch (784:13): [True: 26.3k, False: 33.9k]
  ------------------
  785|  26.3k|                val = parse_primitive(js, ti, &j);
  786|  26.3k|                break;
  787|      0|            default:
  ------------------
  |  Branch (787:13): [True: 0, False: 60.2k]
  ------------------
  788|      0|                break;
  789|  60.2k|        }
  790|  60.2k|        if (val) {
  ------------------
  |  Branch (790:13): [True: 54.4k, False: 5.80k]
  ------------------
  791|  54.4k|            plist_array_append_item(arr, val);
  792|       |            // if append failed, val still has no parent, free it and abort
  793|  54.4k|            if (((node_t)val)->parent == NULL) {
  ------------------
  |  Branch (793:17): [True: 2, False: 54.4k]
  ------------------
  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|  54.4k|        } else {
  800|  5.80k|            plist_free(arr);
  801|  5.80k|            ti->err = PLIST_ERR_PARSE;
  802|  5.80k|            return NULL;
  803|  5.80k|        }
  804|  60.2k|    }
  805|  47.5k|    *(index) = j;
  806|  47.5k|    return arr;
  807|  53.3k|}
jplist.c:parse_object:
  810|  12.3k|{
  811|  12.3k|    if (ti->tokens[*index].type != JSMN_OBJECT) {
  ------------------
  |  Branch (811:9): [True: 0, False: 12.3k]
  ------------------
  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.3k|    if (depth > PLIST_MAX_NESTING_DEPTH) {
  ------------------
  |  |   56|  12.3k|#define PLIST_MAX_NESTING_DEPTH NODE_MAX_DEPTH
  |  |  ------------------
  |  |  |  |   33|  12.3k|#define NODE_MAX_DEPTH 512
  |  |  ------------------
  ------------------
  |  Branch (816:9): [True: 1, False: 12.3k]
  ------------------
  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.3k|    size_t num_tokens = ti->tokens[*index].size;
  822|  12.3k|    size_t num;
  823|  12.3k|    int j = (*index)+1;
  824|  12.3k|    if (num_tokens % 2 != 0) {
  ------------------
  |  Branch (824:9): [True: 13, False: 12.3k]
  ------------------
  825|     13|        PLIST_JSON_ERR("%s: number of children must be even\n", __func__);
  ------------------
  |  |   48|     13|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 13]
  |  |  ------------------
  ------------------
  826|     13|        ti->err = PLIST_ERR_PARSE;
  827|     13|        return NULL;
  828|     13|    }
  829|  12.3k|    plist_t obj = plist_new_dict();
  830|  12.3k|    if (!obj) {
  ------------------
  |  Branch (830:9): [True: 0, False: 12.3k]
  ------------------
  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|  78.7k|    for (num = 0; num < num_tokens; num++) {
  ------------------
  |  Branch (835:19): [True: 66.5k, False: 12.1k]
  ------------------
  836|  66.5k|        if (j+1 >= ti->count) {
  ------------------
  |  Branch (836:13): [True: 0, False: 66.5k]
  ------------------
  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|  66.5k|        if (ti->tokens[j].type == JSMN_STRING) {
  ------------------
  |  Branch (842:13): [True: 66.5k, False: 6]
  ------------------
  843|  66.5k|            char* key = unescape_string(js + ti->tokens[j].start, ti->tokens[j].end - ti->tokens[j].start, NULL);
  844|  66.5k|            if (!key) {
  ------------------
  |  Branch (844:17): [True: 3, False: 66.5k]
  ------------------
  845|      3|                plist_free(obj);
  846|      3|                ti->err = PLIST_ERR_PARSE;
  847|      3|                return NULL;
  848|      3|            }
  849|  66.5k|            plist_t val = NULL;
  850|  66.5k|            j++;
  851|  66.5k|            num++;
  852|  66.5k|            switch (ti->tokens[j].type) {
  853|  11.1k|                case JSMN_OBJECT:
  ------------------
  |  Branch (853:17): [True: 11.1k, False: 55.4k]
  ------------------
  854|  11.1k|                    val = parse_object(js, ti, &j, depth+1);
  855|  11.1k|                    break;
  856|  20.6k|                case JSMN_ARRAY:
  ------------------
  |  Branch (856:17): [True: 20.6k, False: 45.9k]
  ------------------
  857|  20.6k|                    val = parse_array(js, ti, &j, depth+1);
  858|  20.6k|                    break;
  859|  32.6k|                case JSMN_STRING:
  ------------------
  |  Branch (859:17): [True: 32.6k, False: 33.9k]
  ------------------
  860|  32.6k|                    val = parse_string(js, ti, &j);
  861|  32.6k|                    break;
  862|  2.13k|                case JSMN_PRIMITIVE:
  ------------------
  |  Branch (862:17): [True: 2.13k, False: 64.4k]
  ------------------
  863|  2.13k|                    val = parse_primitive(js, ti, &j);
  864|  2.13k|                    break;
  865|      0|                default:
  ------------------
  |  Branch (865:17): [True: 0, False: 66.5k]
  ------------------
  866|      0|                    break;
  867|  66.5k|            }
  868|  66.5k|            if (val) {
  ------------------
  |  Branch (868:17): [True: 66.3k, False: 202]
  ------------------
  869|  66.3k|                plist_dict_set_item(obj, key, val);
  870|       |                // if set failed, val still has no parent, free it and abort
  871|  66.3k|                if (((node_t)val)->parent == NULL) {
  ------------------
  |  Branch (871:21): [True: 5, False: 66.3k]
  ------------------
  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|  66.3k|            } else {
  879|    202|                free(key);
  880|    202|                plist_free(obj);
  881|    202|                ti->err = PLIST_ERR_PARSE;
  882|    202|                return NULL;
  883|    202|            }
  884|  66.3k|            free(key);
  885|  66.3k|        } 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|  66.5k|    }
  892|  12.1k|    (*index) = j;
  893|  12.1k|    return obj;
  894|  12.3k|}

jsmn_parse:
  173|  12.7k|		unsigned int num_tokens) {
  174|  12.7k|	jsmnerr_t r;
  175|  12.7k|	int i;
  176|  12.7k|	jsmntok_t *token;
  177|       |
  178|  12.7k|	parser->end = length;
  179|       |
  180|  12.7k|	if (num_tokens >= INT_MAX) {
  ------------------
  |  Branch (180:6): [True: 0, False: 12.7k]
  ------------------
  181|      0|		return JSMN_ERROR_LIMIT;
  182|      0|	}
  183|  12.7k|	if (length > SIZE_MAX / 2) {
  ------------------
  |  Branch (183:6): [True: 0, False: 12.7k]
  ------------------
  184|      0|		return JSMN_ERROR_LIMIT;
  185|      0|	}
  186|       |
  187|   420k|	for (; (parser->end > 0 && parser->pos < parser->end) && js[parser->pos] != '\0'; parser->pos++) {
  ------------------
  |  Branch (187:10): [True: 420k, False: 0]
  |  Branch (187:29): [True: 418k, False: 2.13k]
  |  Branch (187:59): [True: 418k, False: 5]
  ------------------
  188|   418k|		char c;
  189|   418k|		jsmntype_t type;
  190|       |
  191|   418k|		c = js[parser->pos];
  192|   418k|		switch (c) {
  193|   162k|			case '{': case '[':
  ------------------
  |  Branch (193:4): [True: 62.3k, False: 355k]
  |  Branch (193:14): [True: 100k, False: 317k]
  ------------------
  194|   162k|				token = jsmn_alloc_token(parser, tokens, num_tokens);
  195|   162k|				if (token == NULL)
  ------------------
  |  Branch (195:9): [True: 6.72k, False: 155k]
  ------------------
  196|  6.72k|					return JSMN_ERROR_NOMEM;
  197|   155k|				if (parser->toksuper != -1) {
  ------------------
  |  Branch (197:9): [True: 149k, False: 6.29k]
  ------------------
  198|   149k|					tokens[parser->toksuper].size++;
  199|       |#ifdef JSMN_PARENT_LINKS
  200|       |					token->parent = parser->toksuper;
  201|       |#endif
  202|   149k|				}
  203|   155k|				token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
  ------------------
  |  Branch (203:20): [True: 58.9k, False: 96.8k]
  ------------------
  204|   155k|				token->start = parser->pos;
  205|   155k|				parser->toksuper = parser->toknext - 1;
  206|   155k|				break;
  207|  73.6k|			case '}': case ']':
  ------------------
  |  Branch (207:4): [True: 18.0k, False: 400k]
  |  Branch (207:14): [True: 55.6k, False: 362k]
  ------------------
  208|  73.6k|				type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
  ------------------
  |  Branch (208:13): [True: 18.0k, False: 55.6k]
  ------------------
  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|  5.92M|				for (i = parser->toknext - 1; i >= 0; i--) {
  ------------------
  |  Branch (232:35): [True: 5.92M, False: 37]
  ------------------
  233|  5.92M|					token = &tokens[i];
  234|  5.92M|					if (token->start != JSMN_POS_INVALID && token->end == JSMN_POS_INVALID) {
  ------------------
  |  |   35|  11.8M|#define JSMN_POS_INVALID ((size_t)SIZE_MAX)
  ------------------
              					if (token->start != JSMN_POS_INVALID && token->end == JSMN_POS_INVALID) {
  ------------------
  |  |   35|  5.92M|#define JSMN_POS_INVALID ((size_t)SIZE_MAX)
  ------------------
  |  Branch (234:10): [True: 5.92M, False: 0]
  |  Branch (234:46): [True: 73.6k, False: 5.84M]
  ------------------
  235|  73.6k|						if (token->type != type) {
  ------------------
  |  Branch (235:11): [True: 3, False: 73.6k]
  ------------------
  236|      3|							return JSMN_ERROR_INVAL;
  237|      3|						}
  238|  73.6k|						parser->toksuper = -1;
  239|  73.6k|						token->end = parser->pos + 1;
  240|  73.6k|						break;
  241|  73.6k|					}
  242|  5.92M|				}
  243|       |				/* Error if unmatched closing bracket */
  244|  73.6k|				if (i == -1) return JSMN_ERROR_INVAL;
  ------------------
  |  Branch (244:9): [True: 37, False: 73.6k]
  ------------------
  245|  27.1M|				for (; i >= 0; i--) {
  ------------------
  |  Branch (245:12): [True: 27.1M, False: 6.07k]
  ------------------
  246|  27.1M|					token = &tokens[i];
  247|  27.1M|					if (token->start != JSMN_POS_INVALID && token->end == JSMN_POS_INVALID) {
  ------------------
  |  |   35|  54.2M|#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: 67.5k, False: 27.0M]
  ------------------
  248|  67.5k|						parser->toksuper = i;
  249|  67.5k|						break;
  250|  67.5k|					}
  251|  27.1M|				}
  252|  73.6k|#endif
  253|  73.6k|				break;
  254|   112k|			case '\"':
  ------------------
  |  Branch (254:4): [True: 112k, False: 305k]
  ------------------
  255|   112k|				r = jsmn_parse_string(parser, js, tokens, num_tokens);
  256|   112k|				if (r < 0) return r;
  ------------------
  |  Branch (256:9): [True: 2.65k, False: 109k]
  ------------------
  257|   109k|				if (parser->toksuper != -1)
  ------------------
  |  Branch (257:9): [True: 109k, False: 427]
  ------------------
  258|   109k|					tokens[parser->toksuper].size++;
  259|   109k|				break;
  260|  34.5k|			case '\t' : case '\r' : case '\n' : case ':' : case ',': case ' ':
  ------------------
  |  Branch (260:4): [True: 1.18k, False: 416k]
  |  Branch (260:16): [True: 1.31k, False: 416k]
  |  Branch (260:28): [True: 14.4k, False: 403k]
  |  Branch (260:40): [True: 12.0k, False: 406k]
  |  Branch (260:51): [True: 4.78k, False: 413k]
  |  Branch (260:61): [True: 802, False: 417k]
  ------------------
  261|  34.5k|				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|  35.1k|			default:
  ------------------
  |  Branch (269:4): [True: 35.1k, False: 382k]
  ------------------
  270|  35.1k|#endif
  271|  35.1k|				r = jsmn_parse_primitive(parser, js, tokens, num_tokens);
  272|  35.1k|				if (r < 0) return r;
  ------------------
  |  Branch (272:9): [True: 1.20k, False: 33.9k]
  ------------------
  273|  33.9k|				if (parser->toksuper != -1)
  ------------------
  |  Branch (273:9): [True: 31.8k, False: 2.05k]
  ------------------
  274|  31.8k|					tokens[parser->toksuper].size++;
  275|  33.9k|				break;
  276|       |
  277|       |#ifdef JSMN_STRICT
  278|       |			/* Unexpected char in strict mode */
  279|       |			default:
  280|       |				return JSMN_ERROR_INVAL;
  281|       |#endif
  282|       |
  283|   418k|		}
  284|   418k|	}
  285|       |
  286|   213k|	for (i = parser->toknext - 1; i >= 0; i--) {
  ------------------
  |  Branch (286:32): [True: 211k, False: 1.95k]
  ------------------
  287|       |		/* Unmatched opened object or array */
  288|   211k|		if (tokens[i].start != JSMN_POS_INVALID && tokens[i].end == JSMN_POS_INVALID) {
  ------------------
  |  |   35|   422k|#define JSMN_POS_INVALID ((size_t)SIZE_MAX)
  ------------------
              		if (tokens[i].start != JSMN_POS_INVALID && tokens[i].end == JSMN_POS_INVALID) {
  ------------------
  |  |   35|   211k|#define JSMN_POS_INVALID ((size_t)SIZE_MAX)
  ------------------
  |  Branch (288:7): [True: 211k, False: 0]
  |  Branch (288:46): [True: 182, False: 210k]
  ------------------
  289|    182|			return JSMN_ERROR_PART;
  290|    182|		}
  291|   211k|	}
  292|       |
  293|  1.95k|	return JSMN_SUCCESS;
  294|  2.14k|}
jsmn_init:
  300|  2.33k|void jsmn_init(jsmn_parser *parser) {
  301|  2.33k|	parser->pos = 0;
  302|  2.33k|	parser->end = 0;
  303|  2.33k|	parser->toknext = 0;
  304|  2.33k|	parser->toksuper = -1;
  305|  2.33k|}
jsmn.c:jsmn_alloc_token:
   41|   309k|		jsmntok_t *tokens, unsigned int num_tokens) {
   42|   309k|	jsmntok_t *tok;
   43|   309k|	if ((unsigned int)parser->toknext >= num_tokens) {
  ------------------
  |  Branch (43:6): [True: 10.4k, False: 299k]
  ------------------
   44|  10.4k|		return NULL;
   45|  10.4k|	}
   46|   299k|	tok = &tokens[parser->toknext++];
   47|   299k|	tok->start = tok->end = JSMN_POS_INVALID;
  ------------------
  |  |   35|   299k|#define JSMN_POS_INVALID ((size_t)SIZE_MAX)
  ------------------
   48|   299k|	tok->size = 0;
   49|       |#ifdef JSMN_PARENT_LINKS
   50|       |	tok->parent = -1;
   51|       |#endif
   52|   299k|	return tok;
   53|   309k|}
jsmn.c:jsmn_parse_string:
  117|   112k|		jsmntok_t *tokens, unsigned int num_tokens) {
  118|   112k|	jsmntok_t *token;
  119|       |
  120|   112k|	size_t start = parser->pos;
  121|       |
  122|   112k|	parser->pos++;
  123|       |
  124|       |	/* Skip starting quote */
  125|   309k|	for (; (parser->end > 0 && parser->pos < parser->end) && js[parser->pos] != '\0'; parser->pos++) {
  ------------------
  |  Branch (125:10): [True: 309k, False: 0]
  |  Branch (125:29): [True: 309k, False: 127]
  |  Branch (125:59): [True: 309k, False: 1]
  ------------------
  126|   309k|		char c = js[parser->pos];
  127|       |
  128|       |		/* Quote: end of string */
  129|   309k|		if (c == '\"') {
  ------------------
  |  Branch (129:7): [True: 112k, False: 197k]
  ------------------
  130|   112k|			token = jsmn_alloc_token(parser, tokens, num_tokens);
  131|   112k|			if (token == NULL) {
  ------------------
  |  Branch (131:8): [True: 2.52k, False: 109k]
  ------------------
  132|  2.52k|				parser->pos = start;
  133|  2.52k|				return JSMN_ERROR_NOMEM;
  134|  2.52k|			}
  135|   109k|			jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
  136|       |#ifdef JSMN_PARENT_LINKS
  137|       |			token->parent = parser->toksuper;
  138|       |#endif
  139|   109k|			return JSMN_SUCCESS;
  140|   112k|		}
  141|       |
  142|       |		/* Backslash: Quoted symbol expected */
  143|   197k|		if (c == '\\') {
  ------------------
  |  Branch (143:7): [True: 24.7k, False: 172k]
  ------------------
  144|  24.7k|			parser->pos++;
  145|  24.7k|			if (parser->end > 0 && parser->pos >= parser->end) {
  ------------------
  |  Branch (145:8): [True: 24.7k, False: 0]
  |  Branch (145:27): [True: 6, False: 24.7k]
  ------------------
  146|      6|				parser->pos = start;
  147|      6|				return JSMN_ERROR_INVAL;
  148|      6|			}
  149|  24.7k|			switch (js[parser->pos]) {
  150|       |				/* Allowed escaped symbols */
  151|  7.13k|				case '\"': case '/' : case '\\' : case 'b' :
  ------------------
  |  Branch (151:5): [True: 915, False: 23.8k]
  |  Branch (151:16): [True: 469, False: 24.2k]
  |  Branch (151:27): [True: 5.11k, False: 19.6k]
  |  Branch (151:39): [True: 639, False: 24.1k]
  ------------------
  152|  23.1k|				case 'f' : case 'r' : case 'n'  : case 't' :
  ------------------
  |  Branch (152:5): [True: 658, False: 24.0k]
  |  Branch (152:16): [True: 663, False: 24.0k]
  |  Branch (152:27): [True: 13.9k, False: 10.7k]
  |  Branch (152:39): [True: 676, False: 24.0k]
  ------------------
  153|  23.1k|					break;
  154|       |				/* Allows escaped symbol \uXXXX */
  155|  1.61k|				case 'u':
  ------------------
  |  Branch (155:5): [True: 1.61k, False: 23.1k]
  ------------------
  156|       |					/* TODO */
  157|  1.61k|					break;
  158|       |				/* Unexpected symbol */
  159|      3|				default:
  ------------------
  |  Branch (159:5): [True: 3, False: 24.7k]
  ------------------
  160|      3|					parser->pos = start;
  161|      3|					return JSMN_ERROR_INVAL;
  162|  24.7k|			}
  163|  24.7k|		}
  164|   197k|	}
  165|    128|	parser->pos = start;
  166|    128|	return JSMN_ERROR_PART;
  167|   112k|}
jsmn.c:jsmn_fill_token:
   59|   143k|                            size_t start, size_t end) {
   60|   143k|	token->type = type;
   61|   143k|	token->start = start;
   62|   143k|	token->end = end;
   63|   143k|	token->size = 0;
   64|   143k|}
jsmn.c:jsmn_parse_primitive:
   70|  35.1k|		jsmntok_t *tokens, unsigned int num_tokens) {
   71|  35.1k|	jsmntok_t *token;
   72|  35.1k|	size_t start;
   73|       |
   74|  35.1k|	start = parser->pos;
   75|       |
   76|   110k|	for (; (parser->end > 0 && parser->pos < parser->end) && js[parser->pos] != '\0'; parser->pos++) {
  ------------------
  |  Branch (76:10): [True: 110k, False: 0]
  |  Branch (76:29): [True: 109k, False: 672]
  |  Branch (76:59): [True: 109k, False: 2]
  ------------------
   77|   109k|		switch (js[parser->pos]) {
   78|      0|#ifndef JSMN_STRICT
   79|       |			/* In strict mode primitive must be followed by "," or "}" or "]" */
   80|  5.68k|			case ':':
  ------------------
  |  Branch (80:4): [True: 5.68k, False: 103k]
  ------------------
   81|  5.68k|#endif
   82|  23.1k|			case '\t' : case '\r' : case '\n' : case ' ' :
  ------------------
  |  Branch (82:4): [True: 992, False: 108k]
  |  Branch (82:16): [True: 1.12k, False: 108k]
  |  Branch (82:28): [True: 14.7k, False: 94.6k]
  |  Branch (82:40): [True: 606, False: 108k]
  ------------------
   83|  34.4k|			case ','  : case ']'  : case '}' :
  ------------------
  |  Branch (83:4): [True: 4.61k, False: 104k]
  |  Branch (83:16): [True: 5.51k, False: 103k]
  |  Branch (83:28): [True: 1.20k, False: 108k]
  ------------------
   84|  34.4k|				goto found;
   85|  74.9k|			default:
  ------------------
  |  Branch (85:4): [True: 74.9k, False: 34.4k]
  ------------------
   86|  74.9k|				break;
   87|   109k|		}
   88|  74.9k|		if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
  ------------------
  |  Branch (88:7): [True: 18, False: 74.8k]
  |  Branch (88:31): [True: 1, False: 74.8k]
  ------------------
   89|     19|			parser->pos = start;
   90|     19|			return JSMN_ERROR_INVAL;
   91|     19|		}
   92|  74.9k|	}
   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|  35.1k|found:
  100|  35.1k|	token = jsmn_alloc_token(parser, tokens, num_tokens);
  101|  35.1k|	if (token == NULL) {
  ------------------
  |  Branch (101:6): [True: 1.18k, False: 33.9k]
  ------------------
  102|  1.18k|		parser->pos = start;
  103|  1.18k|		return JSMN_ERROR_NOMEM;
  104|  1.18k|	}
  105|  33.9k|	jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
  106|       |#ifdef JSMN_PARENT_LINKS
  107|       |	token->parent = parser->toksuper;
  108|       |#endif
  109|  33.9k|	parser->pos--;
  110|  33.9k|	return JSMN_SUCCESS;
  111|  35.1k|}

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|   190k|{
  349|       |    return (plist_t) node_create(NULL, data);
  350|   190k|}
plist_get_data:
  353|  22.8M|{
  354|  22.8M|    if (!node)
  ------------------
  |  Branch (354:9): [True: 0, False: 22.8M]
  ------------------
  355|      0|        return NULL;
  356|  22.8M|    return (plist_data_t)((node_t)node)->data;
  357|  22.8M|}
plist_new_plist_data:
  360|   190k|{
  361|   190k|    return (plist_data_t) calloc(1, sizeof(struct plist_data_s));
  362|   190k|}
plist_free_data:
  421|   190k|{
  422|   190k|    if (!data) return;
  ------------------
  |  Branch (422:9): [True: 0, False: 190k]
  ------------------
  423|   190k|    _plist_free_data(data);
  424|   190k|    free(data);
  425|   190k|}
plist_new_dict:
  528|  12.3k|{
  529|  12.3k|    plist_data_t data = plist_new_plist_data();
  530|  12.3k|    if (!data) {
  ------------------
  |  Branch (530:9): [True: 0, False: 12.3k]
  ------------------
  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.3k|    data->type = PLIST_DICT;
  535|  12.3k|    return plist_new_node(data);
  536|  12.3k|}
plist_new_array:
  539|  53.3k|{
  540|  53.3k|    plist_data_t data = plist_new_plist_data();
  541|  53.3k|    if (!data) {
  ------------------
  |  Branch (541:9): [True: 0, False: 53.3k]
  ------------------
  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|  53.3k|    data->type = PLIST_ARRAY;
  546|  53.3k|    return plist_new_node(data);
  547|  53.3k|}
plist_new_bool:
  589|  6.94k|{
  590|  6.94k|    plist_data_t data = plist_new_plist_data();
  591|  6.94k|    if (!data) {
  ------------------
  |  Branch (591:9): [True: 0, False: 6.94k]
  ------------------
  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|  6.94k|    data->type = PLIST_BOOLEAN;
  596|  6.94k|    data->boolval = val;
  597|  6.94k|    data->length = sizeof(uint8_t);
  598|  6.94k|    return plist_new_node(data);
  599|  6.94k|}
plist_new_int:
  615|  4.30k|{
  616|  4.30k|    plist_data_t data = plist_new_plist_data();
  617|  4.30k|    if (!data) {
  ------------------
  |  Branch (617:9): [True: 0, False: 4.30k]
  ------------------
  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.30k|    data->type = PLIST_INT;
  622|  4.30k|    data->intval = val;
  623|  4.30k|    data->length = sizeof(uint64_t);
  624|  4.30k|    return plist_new_node(data);
  625|  4.30k|}
plist_new_real:
  641|  2.22k|{
  642|  2.22k|    plist_data_t data = plist_new_plist_data();
  643|  2.22k|    if (!data) {
  ------------------
  |  Branch (643:9): [True: 0, False: 2.22k]
  ------------------
  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.22k|    data->type = PLIST_REAL;
  648|  2.22k|    data->realval = val;
  649|  2.22k|    data->length = sizeof(double);
  650|  2.22k|    return plist_new_node(data);
  651|  2.22k|}
plist_free:
  713|  8.36k|{
  714|  8.36k|    if (plist)
  ------------------
  |  Branch (714:9): [True: 7.50k, False: 864]
  ------------------
  715|  7.50k|    {
  716|  7.50k|        plist_free_node((node_t)plist);
  717|  7.50k|    }
  718|  8.36k|}
plist_array_append_item:
 1080|  54.4k|{
 1081|  54.4k|    if (!PLIST_IS_ARRAY(node) || !item) {
  ------------------
  |  | 1252|  54.4k|    #define PLIST_IS_ARRAY(__plist)   _PLIST_IS_TYPE(__plist, ARRAY)
  |  |  ------------------
  |  |  |  | 1240|   108k|    #define _PLIST_IS_TYPE(__plist, __plist_type) (__plist && (plist_get_node_type(__plist) == PLIST_##__plist_type))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1240:52): [True: 54.4k, False: 0]
  |  |  |  |  |  Branch (1240:63): [True: 54.4k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1081:34): [True: 0, False: 54.4k]
  ------------------
 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|  54.4k|    node_t it = (node_t)item;
 1086|  54.4k|    if (it->parent != NULL) {
  ------------------
  |  Branch (1086:9): [True: 0, False: 54.4k]
  ------------------
 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|  54.4k|    int r = node_attach((node_t)node, (node_t)item);
 1093|  54.4k|    if (r != NODE_ERR_SUCCESS) {
  ------------------
  |  |   36|  54.4k|#define NODE_ERR_SUCCESS       0
  ------------------
  |  Branch (1093:9): [True: 2, False: 54.4k]
  ------------------
 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|  54.4k|    _plist_array_post_insert(node, item, -1);
 1098|       |
 1099|  54.4k|    return PLIST_ERR_SUCCESS;
 1100|  54.4k|}
plist_dict_get_item:
 1281|  66.3k|{
 1282|  66.3k|    plist_t ret = NULL;
 1283|  66.3k|    if (!PLIST_IS_DICT(node) || !key) {
  ------------------
  |  | 1254|  66.3k|    #define PLIST_IS_DICT(__plist)    _PLIST_IS_TYPE(__plist, DICT)
  |  |  ------------------
  |  |  |  | 1240|   132k|    #define _PLIST_IS_TYPE(__plist, __plist_type) (__plist && (plist_get_node_type(__plist) == PLIST_##__plist_type))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1240:52): [True: 66.3k, False: 0]
  |  |  |  |  |  Branch (1240:63): [True: 66.3k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1283:33): [True: 0, False: 66.3k]
  ------------------
 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|  66.3k|    plist_data_t data = plist_get_data(node);
 1288|  66.3k|    if (!data) {
  ------------------
  |  Branch (1288:9): [True: 0, False: 66.3k]
  ------------------
 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|  66.3k|    size_t keylen = strlen(key);
 1293|  66.3k|    hashtable_t *ht = (hashtable_t*)data->hashtable;
 1294|  66.3k|    if (ht) {
  ------------------
  |  Branch (1294:9): [True: 977, False: 65.4k]
  ------------------
 1295|    977|        struct plist_data_s sdata = { 0 };
 1296|    977|        sdata.strval = (char*)key;
 1297|    977|        sdata.length = keylen;
 1298|    977|        return (plist_t)hash_table_lookup(ht, &sdata);
 1299|  65.4k|    } else {
 1300|  65.4k|        plist_t k = NULL;
 1301|  7.54M|        for (k = (plist_t)node_first_child((node_t)node); k; ) {
  ------------------
  |  Branch (1301:59): [True: 7.48M, False: 61.7k]
  ------------------
 1302|  7.48M|            plist_t v = (plist_t)node_next_sibling(k);
 1303|  7.48M|            if (!v) break;
  ------------------
  |  Branch (1303:17): [True: 0, False: 7.48M]
  ------------------
 1304|  7.48M|            data = plist_get_data(k);
 1305|  7.48M|            assert(PLIST_IS_KEY(k));
  ------------------
  |  Branch (1305:13): [True: 0, False: 7.48M]
  |  Branch (1305:13): [True: 0, False: 0]
  |  Branch (1305:13): [True: 7.48M, False: 0]
  |  Branch (1305:13): [True: 7.48M, False: 0]
  ------------------
 1306|  7.48M|            if (!PLIST_IS_KEY(k) || !data || !data->strval) {
  ------------------
  |  | 1260|  7.48M|    #define PLIST_IS_KEY(__plist)     _PLIST_IS_TYPE(__plist, KEY)
  |  |  ------------------
  |  |  |  | 1240|  14.9M|    #define _PLIST_IS_TYPE(__plist, __plist_type) (__plist && (plist_get_node_type(__plist) == PLIST_##__plist_type))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1240:52): [True: 7.48M, False: 0]
  |  |  |  |  |  Branch (1240:63): [True: 7.48M, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1306:37): [True: 0, False: 7.48M]
  |  Branch (1306:46): [True: 0, False: 7.48M]
  ------------------
 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.48M|            if (data->length == keylen && !memcmp(key, data->strval, keylen+1)) {
  ------------------
  |  Branch (1310:17): [True: 3.93M, False: 3.54M]
  |  Branch (1310:43): [True: 3.65k, False: 3.93M]
  ------------------
 1311|  3.65k|                ret = v;
 1312|  3.65k|                break;
 1313|  3.65k|            }
 1314|  7.47M|            k = node_next_sibling(v);
 1315|  7.47M|        }
 1316|  65.4k|    }
 1317|  65.4k|    return ret;
 1318|  66.3k|}
plist_dict_set_item:
 1321|  66.3k|{
 1322|  66.3k|    if (!PLIST_IS_DICT(node) || !key || !item) {
  ------------------
  |  | 1254|  66.3k|    #define PLIST_IS_DICT(__plist)    _PLIST_IS_TYPE(__plist, DICT)
  |  |  ------------------
  |  |  |  | 1240|   132k|    #define _PLIST_IS_TYPE(__plist, __plist_type) (__plist && (plist_get_node_type(__plist) == PLIST_##__plist_type))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1240:52): [True: 66.3k, False: 0]
  |  |  |  |  |  Branch (1240:63): [True: 66.3k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1322:33): [True: 0, False: 66.3k]
  |  Branch (1322:41): [True: 0, False: 66.3k]
  ------------------
 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|  66.3k|    node_t it = (node_t)item;
 1327|  66.3k|    if (it->parent != NULL) {
  ------------------
  |  Branch (1327:9): [True: 0, False: 66.3k]
  ------------------
 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|  66.3k|    hashtable_t *ht = (hashtable_t*)((plist_data_t)((node_t)node)->data)->hashtable;
 1334|       |
 1335|  66.3k|    plist_t old_item = plist_dict_get_item(node, key);
 1336|  66.3k|    plist_t key_node = NULL;
 1337|       |
 1338|  66.3k|    if (old_item) {
  ------------------
  |  Branch (1338:9): [True: 4.22k, False: 62.1k]
  ------------------
 1339|       |        // --- REPLACE EXISTING VALUE ---
 1340|  4.22k|        node_t old_val = (node_t)old_item;
 1341|  4.22k|        node_t old_key = node_prev_sibling(old_val);
 1342|  4.22k|        if (!old_key) {
  ------------------
  |  Branch (1342:13): [True: 0, False: 4.22k]
  ------------------
 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|  4.22k|        if (!PLIST_IS_KEY((plist_t)old_key)) {
  ------------------
  |  | 1260|  4.22k|    #define PLIST_IS_KEY(__plist)     _PLIST_IS_TYPE(__plist, KEY)
  |  |  ------------------
  |  |  |  | 1240|  4.22k|    #define _PLIST_IS_TYPE(__plist, __plist_type) (__plist && (plist_get_node_type(__plist) == PLIST_##__plist_type))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1240:52): [True: 4.22k, False: 0]
  |  |  |  |  |  Branch (1240:63): [True: 4.22k, 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|  4.22k|        int idx = node_detach((node_t)node, old_val);
 1353|  4.22k|        if (idx < 0) {
  ------------------
  |  Branch (1353:13): [True: 0, False: 4.22k]
  ------------------
 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|  4.22k|        int r = node_insert((node_t)node, (unsigned)idx, (node_t)item);
 1360|  4.22k|        if (r != NODE_ERR_SUCCESS) {
  ------------------
  |  |   36|  4.22k|#define NODE_ERR_SUCCESS       0
  ------------------
  |  Branch (1360:13): [True: 3, False: 4.22k]
  ------------------
 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|  4.22k|        key_node = old_key;
 1370|       |
 1371|       |        // update hash table
 1372|  4.22k|        if (ht) {
  ------------------
  |  Branch (1372:13): [True: 572, False: 3.65k]
  ------------------
 1373|    572|            hash_table_insert(ht, (plist_data_t)((node_t)key_node)->data, item);
 1374|    572|        }
 1375|       |
 1376|       |        // now it’s safe to free old value
 1377|  4.22k|        plist_free_node(old_val);
 1378|  62.1k|    } else {
 1379|       |        // --- INSERT NEW KEY/VALUE PAIR ---
 1380|  62.1k|        key_node = plist_new_key(key);
 1381|  62.1k|        if (!key_node) return PLIST_ERR_NO_MEM;
  ------------------
  |  Branch (1381:13): [True: 0, False: 62.1k]
  ------------------
 1382|       |
 1383|  62.1k|        int r = node_attach((node_t)node, (node_t)key_node);
 1384|  62.1k|        if (r != NODE_ERR_SUCCESS) {
  ------------------
  |  |   36|  62.1k|#define NODE_ERR_SUCCESS       0
  ------------------
  |  Branch (1384:13): [True: 0, False: 62.1k]
  ------------------
 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|  62.1k|        r = node_attach((node_t)node, (node_t)item);
 1390|  62.1k|        if (r != NODE_ERR_SUCCESS) {
  ------------------
  |  |   36|  62.1k|#define NODE_ERR_SUCCESS       0
  ------------------
  |  Branch (1390:13): [True: 2, False: 62.1k]
  ------------------
 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|  62.1k|        if (ht) {
  ------------------
  |  Branch (1398:13): [True: 403, False: 61.7k]
  ------------------
 1399|       |            // store pointer to item in hash table
 1400|    403|            hash_table_insert(ht, (plist_data_t)((node_t)key_node)->data, item);
 1401|  61.7k|        } else if (((node_t)node)->count > 500) {
  ------------------
  |  Branch (1401:20): [True: 230, False: 61.5k]
  ------------------
 1402|       |            // make new hash table
 1403|    230|            ht = hash_table_new(dict_key_hash, dict_key_compare, NULL);
 1404|       |            // calculate the hashes for all entries we have so far
 1405|    230|            plist_t current = NULL;
 1406|    230|            for (current = (plist_t)node_first_child((node_t)node);
 1407|  57.9k|                 ht && current;
  ------------------
  |  Branch (1407:18): [True: 57.9k, False: 0]
  |  Branch (1407:24): [True: 57.7k, False: 230]
  ------------------
 1408|  57.7k|                 current = (plist_t)node_next_sibling(node_next_sibling((node_t)current)))
 1409|  57.7k|            {
 1410|  57.7k|                hash_table_insert(ht, ((node_t)current)->data, node_next_sibling((node_t)current));
 1411|  57.7k|            }
 1412|    230|            ((plist_data_t)((node_t)node)->data)->hashtable = ht;
 1413|    230|        }
 1414|  62.1k|    }
 1415|  66.3k|    return PLIST_ERR_SUCCESS;
 1416|  66.3k|}
plist_get_node_type:
 1746|  15.1M|{
 1747|  15.1M|    if (node)
  ------------------
  |  Branch (1747:9): [True: 15.1M, False: 0]
  ------------------
 1748|  15.1M|    {
 1749|  15.1M|        plist_data_t data = plist_get_data(node);
 1750|  15.1M|        if (data)
  ------------------
  |  Branch (1750:13): [True: 15.1M, False: 0]
  ------------------
 1751|  15.1M|            return data->type;
 1752|  15.1M|    }
 1753|      0|    return PLIST_NONE;
 1754|  15.1M|}
plist.c:_plist_free_data:
  390|   190k|{
  391|   190k|    if (!data) return;
  ------------------
  |  Branch (391:9): [True: 0, False: 190k]
  ------------------
  392|   190k|    switch (data->type) {
  393|  62.1k|        case PLIST_KEY:
  ------------------
  |  Branch (393:9): [True: 62.1k, False: 128k]
  ------------------
  394|  96.0k|        case PLIST_STRING:
  ------------------
  |  Branch (394:9): [True: 33.8k, False: 156k]
  ------------------
  395|  96.0k|            free(data->strval);
  396|  96.0k|            data->strval = NULL;
  397|  96.0k|            break;
  398|      0|        case PLIST_DATA:
  ------------------
  |  Branch (398:9): [True: 0, False: 190k]
  ------------------
  399|      0|            free(data->buff);
  400|      0|            data->buff = NULL;
  401|      0|            break;
  402|  53.3k|        case PLIST_ARRAY:
  ------------------
  |  Branch (402:9): [True: 53.3k, False: 137k]
  ------------------
  403|  53.3k|            ptr_array_free((ptrarray_t*)data->hashtable);
  404|  53.3k|            data->hashtable = NULL;
  405|  53.3k|            break;
  406|  12.3k|        case PLIST_DICT: {
  ------------------
  |  Branch (406:9): [True: 12.3k, False: 178k]
  ------------------
  407|  12.3k|            hashtable_t *ht = (hashtable_t*)data->hashtable;
  408|       |            // PLIST_DICT hashtables must not own/free values; values are freed via node tree.
  409|  12.3k|            assert(!ht || ht->free_func == NULL);
  ------------------
  |  Branch (409:13): [True: 12.3k, False: 0]
  |  Branch (409:13): [True: 0, False: 0]
  |  Branch (409:13): [True: 12.1k, False: 230]
  |  Branch (409:13): [True: 230, False: 0]
  ------------------
  410|  12.3k|            if (ht) ht->free_func = NULL;
  ------------------
  |  Branch (410:17): [True: 230, False: 12.1k]
  ------------------
  411|  12.3k|            hash_table_destroy(ht);
  412|  12.3k|            data->hashtable = NULL;
  413|  12.3k|            break;
  414|  12.3k|        }
  415|  28.7k|        default:
  ------------------
  |  Branch (415:9): [True: 28.7k, False: 161k]
  ------------------
  416|  28.7k|            break;
  417|   190k|    }
  418|   190k|}
plist.c:plist_free_node:
  500|  11.7k|{
  501|  11.7k|    if (!root) return NODE_ERR_INVALID_ARG;
  ------------------
  |  |   37|      0|#define NODE_ERR_INVALID_ARG  -1
  ------------------
  |  Branch (501:9): [True: 0, False: 11.7k]
  ------------------
  502|       |
  503|  11.7k|    int root_index = -1;
  504|       |
  505|  11.7k|    if (root->parent) {
  ------------------
  |  Branch (505:9): [True: 0, False: 11.7k]
  ------------------
  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|  11.7k|    int r = plist_free_children(root);
  513|  11.7k|    if (r < 0) {
  ------------------
  |  Branch (513:9): [True: 0, False: 11.7k]
  ------------------
  514|       |        // root is already detached; caller should treat as error.
  515|      0|        return r;
  516|      0|    }
  517|       |
  518|  11.7k|    plist_data_t data = plist_get_data(root);
  519|  11.7k|    plist_free_data(data);
  520|  11.7k|    root->data = NULL;
  521|       |
  522|  11.7k|    node_destroy(root);
  523|       |
  524|  11.7k|    return root_index;
  525|  11.7k|}
plist.c:plist_free_children:
  428|  11.7k|{
  429|  11.7k|    if (!root) return NODE_ERR_INVALID_ARG;
  ------------------
  |  |   37|      0|#define NODE_ERR_INVALID_ARG  -1
  ------------------
  |  Branch (429:9): [True: 0, False: 11.7k]
  ------------------
  430|       |
  431|  11.7k|    if (!node_first_child(root)) {
  ------------------
  |  Branch (431:9): [True: 10.4k, False: 1.29k]
  ------------------
  432|  10.4k|        return NODE_ERR_SUCCESS;
  ------------------
  |  |   36|  10.4k|#define NODE_ERR_SUCCESS       0
  ------------------
  433|  10.4k|    }
  434|       |
  435|  1.29k|    size_t cap = 64, sp = 0;
  436|  1.29k|    node_t *stack = (node_t*)malloc(cap * sizeof(*stack));
  437|  1.29k|    if (!stack) return NODE_ERR_NO_MEM;
  ------------------
  |  |   38|      0|#define NODE_ERR_NO_MEM       -2
  ------------------
  |  Branch (437:9): [True: 0, False: 1.29k]
  ------------------
  438|       |
  439|       |    // Push *direct* children onto the stack, detached from root.
  440|   143k|    for (;;) {
  441|   143k|        node_t ch = node_first_child(root);
  442|   143k|        if (!ch) break;
  ------------------
  |  Branch (442:13): [True: 1.29k, False: 142k]
  ------------------
  443|       |
  444|   142k|        int di = node_detach(root, ch);
  445|   142k|        if (di < 0) {
  ------------------
  |  Branch (445:13): [True: 0, False: 142k]
  ------------------
  446|      0|            free(stack);
  447|      0|            return di;
  448|      0|        }
  449|       |
  450|   142k|        if (sp == cap) {
  ------------------
  |  Branch (450:13): [True: 1.91k, False: 140k]
  ------------------
  451|  1.91k|            cap += 64;
  452|  1.91k|            node_t *tmp = (node_t*)realloc(stack, cap * sizeof(*stack));
  453|  1.91k|            if (!tmp) {
  ------------------
  |  Branch (453:17): [True: 0, False: 1.91k]
  ------------------
  454|      0|                free(stack);
  455|      0|                return NODE_ERR_NO_MEM;
  ------------------
  |  |   38|      0|#define NODE_ERR_NO_MEM       -2
  ------------------
  456|      0|            }
  457|  1.91k|            stack = tmp;
  458|  1.91k|        }
  459|   142k|        stack[sp++] = ch;
  460|   142k|    }
  461|       |
  462|       |    // Now free the detached subtree nodes (and their descendants).
  463|   216k|    while (sp) {
  ------------------
  |  Branch (463:12): [True: 215k, False: 1.29k]
  ------------------
  464|   215k|        node_t node = stack[sp - 1];
  465|   215k|        node_t ch = node_first_child(node);
  466|   215k|        if (ch) {
  ------------------
  |  Branch (466:13): [True: 36.4k, False: 178k]
  ------------------
  467|  36.4k|            int di = node_detach(node, ch);
  468|  36.4k|            if (di < 0) {
  ------------------
  |  Branch (468:17): [True: 0, False: 36.4k]
  ------------------
  469|      0|                free(stack);
  470|      0|                return di;
  471|      0|            }
  472|       |
  473|  36.4k|            if (sp == cap) {
  ------------------
  |  Branch (473:17): [True: 265, False: 36.1k]
  ------------------
  474|    265|                cap += 64;
  475|    265|                node_t *tmp = (node_t*)realloc(stack, cap * sizeof(*stack));
  476|    265|                if (!tmp) {
  ------------------
  |  Branch (476:21): [True: 0, False: 265]
  ------------------
  477|      0|                    free(stack);
  478|      0|                    return NODE_ERR_NO_MEM;
  ------------------
  |  |   38|      0|#define NODE_ERR_NO_MEM       -2
  ------------------
  479|      0|                }
  480|    265|                stack = tmp;
  481|    265|            }
  482|  36.4k|            stack[sp++] = ch;
  483|  36.4k|            continue;
  484|  36.4k|        }
  485|       |
  486|   178k|        plist_data_t data = plist_get_data(node);
  487|   178k|        plist_free_data(data);
  488|   178k|        node->data = NULL;
  489|       |
  490|   178k|        node_destroy(node);
  491|       |
  492|   178k|        sp--;
  493|   178k|    }
  494|       |
  495|  1.29k|    free(stack);
  496|  1.29k|    return NODE_ERR_SUCCESS;
  ------------------
  |  |   36|  1.29k|#define NODE_ERR_SUCCESS       0
  ------------------
  497|  1.29k|}
plist.c:_plist_array_post_insert:
  986|  54.4k|{
  987|  54.4k|    ptrarray_t *pa = (ptrarray_t*)((plist_data_t)((node_t)node)->data)->hashtable;
  988|  54.4k|    if (pa) {
  ------------------
  |  Branch (988:9): [True: 12.6k, False: 41.7k]
  ------------------
  989|       |        /* store pointer to item in array */
  990|  12.6k|        ptr_array_insert(pa, item, n);
  991|  12.6k|        return;
  992|  12.6k|    }
  993|       |
  994|  41.7k|    if (((node_t)node)->count > 100) {
  ------------------
  |  Branch (994:9): [True: 113, False: 41.6k]
  ------------------
  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|  41.7k|}
plist.c:plist_new_key:
  551|  62.1k|{
  552|  62.1k|    plist_data_t data = plist_new_plist_data();
  553|  62.1k|    if (!data) {
  ------------------
  |  Branch (553:9): [True: 0, False: 62.1k]
  ------------------
  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|  62.1k|    data->type = PLIST_KEY;
  558|  62.1k|    data->strval = strdup(val);
  559|  62.1k|    if (!data->strval) {
  ------------------
  |  Branch (559:9): [True: 0, False: 62.1k]
  ------------------
  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|  62.1k|    } else {
  564|  62.1k|        data->length = strlen(val);
  565|  62.1k|    }
  566|  62.1k|    return plist_new_node(data);
  567|  62.1k|}
plist.c:dict_key_hash:
  365|  59.6k|{
  366|  59.6k|    plist_data_t keydata = (plist_data_t)data;
  367|  59.6k|    unsigned int hash = 5381;
  368|  59.6k|    size_t i;
  369|  59.6k|    char *str = keydata->strval;
  370|   161k|    for (i = 0; i < keydata->length; str++, i++) {
  ------------------
  |  Branch (370:17): [True: 101k, False: 59.6k]
  ------------------
  371|   101k|        hash = ((hash << 5) + hash) + *str;
  372|   101k|    }
  373|  59.6k|    return hash;
  374|  59.6k|}
plist.c:dict_key_compare:
  377|  3.48k|{
  378|  3.48k|    plist_data_t data_a = (plist_data_t)a;
  379|  3.48k|    plist_data_t data_b = (plist_data_t)b;
  380|  3.48k|    if (data_a->strval == NULL || data_b->strval == NULL) {
  ------------------
  |  Branch (380:9): [True: 0, False: 3.48k]
  |  Branch (380:35): [True: 0, False: 3.48k]
  ------------------
  381|      0|        return FALSE;
  ------------------
  |  |   32|      0|#define FALSE 0
  ------------------
  382|      0|    }
  383|  3.48k|    if (data_a->length != data_b->length) {
  ------------------
  |  Branch (383:9): [True: 1.68k, False: 1.79k]
  ------------------
  384|  1.68k|        return FALSE;
  ------------------
  |  |   32|  1.68k|#define FALSE 0
  ------------------
  385|  1.68k|    }
  386|  1.79k|    return (strcmp(data_a->strval, data_b->strval) == 0) ? TRUE : FALSE;
  ------------------
  |  |   28|  1.14k|#define TRUE 1
  ------------------
                  return (strcmp(data_a->strval, data_b->strval) == 0) ? TRUE : FALSE;
  ------------------
  |  |   32|    648|#define FALSE 0
  ------------------
  |  Branch (386:12): [True: 1.14k, False: 648]
  ------------------
  387|  3.48k|}

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|  53.3k|{
   36|  53.3k|	if (!pa) return;
  ------------------
  |  Branch (36:6): [True: 53.2k, 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|  24.0k|{
   45|  24.0k|	if (!pa || !pa->pdata) return;
  ------------------
  |  Branch (45:6): [True: 0, False: 24.0k]
  |  Branch (45:13): [True: 0, False: 24.0k]
  ------------------
   46|  24.0k|	long remaining = pa->capacity-pa->len;
   47|  24.0k|	if (remaining == 0) {
  ------------------
  |  Branch (47:6): [True: 99, False: 23.9k]
  ------------------
   48|     99|		pa->pdata = (void**)realloc(pa->pdata, sizeof(void*) * (pa->capacity + pa->capacity_step));
   49|     99|		pa->capacity += pa->capacity_step;
   50|     99|	}
   51|  24.0k|	if (array_index < 0 || array_index >= pa->len) {
  ------------------
  |  Branch (51:6): [True: 24.0k, False: 0]
  |  Branch (51:25): [True: 0, False: 0]
  ------------------
   52|  24.0k|		pa->pdata[pa->len] = data;
   53|  24.0k|	} 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|  24.0k|	pa->len++;
   58|  24.0k|}
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|}

