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

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

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

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

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:
  904|  2.29k|{
  905|  2.29k|    if (!plist) {
  ------------------
  |  Branch (905:9): [True: 0, False: 2.29k]
  ------------------
  906|      0|        return PLIST_ERR_INVALID_ARG;
  907|      0|    }
  908|  2.29k|    *plist = NULL;
  909|  2.29k|    if (!json || (length == 0)) {
  ------------------
  |  Branch (909:9): [True: 0, False: 2.29k]
  |  Branch (909:18): [True: 0, False: 2.29k]
  ------------------
  910|      0|        return PLIST_ERR_INVALID_ARG;
  911|      0|    }
  912|       |
  913|  2.29k|    jsmn_parser parser;
  914|  2.29k|    jsmn_init(&parser);
  915|  2.29k|    unsigned int maxtoks = 256;
  916|  2.29k|    unsigned int curtoks = 0;
  917|  2.29k|    int r = 0;
  918|  2.29k|    jsmntok_t *tokens = NULL;
  919|       |
  920|  13.0k|    do {
  921|  13.0k|        jsmntok_t* newtokens = (jsmntok_t*)realloc(tokens, sizeof(jsmntok_t)*maxtoks);
  922|  13.0k|        if (!newtokens) {
  ------------------
  |  Branch (922:13): [True: 0, False: 13.0k]
  ------------------
  923|      0|            free(tokens);
  924|      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]
  |  |  ------------------
  ------------------
  925|      0|            return PLIST_ERR_NO_MEM;
  926|      0|        }
  927|  13.0k|        memset((unsigned char*)newtokens + sizeof(jsmntok_t)*curtoks, '\0', sizeof(jsmntok_t)*(maxtoks-curtoks));
  928|  13.0k|        tokens = newtokens;
  929|  13.0k|        curtoks = maxtoks;
  930|       |
  931|  13.0k|        r = jsmn_parse(&parser, json, length, tokens, maxtoks);
  932|  13.0k|        if (r == JSMN_ERROR_NOMEM) {
  ------------------
  |  Branch (932:13): [True: 10.7k, False: 2.29k]
  ------------------
  933|  10.7k|            if (maxtoks > (unsigned int)INT_MAX - 16) {
  ------------------
  |  Branch (933:17): [True: 0, False: 10.7k]
  ------------------
  934|      0|                free(tokens);
  935|      0|                return PLIST_ERR_NO_MEM;
  936|      0|            }
  937|  10.7k|            maxtoks+=16;
  938|  10.7k|            continue;
  939|  10.7k|        } else if (r < 0) {
  ------------------
  |  Branch (939:20): [True: 370, False: 1.92k]
  ------------------
  940|    370|            break;
  941|    370|        }
  942|  13.0k|    } while (r == JSMN_ERROR_NOMEM);
  ------------------
  |  Branch (942:14): [True: 10.7k, False: 1.92k]
  ------------------
  943|       |
  944|  2.29k|    switch(r) {
  945|      0|        case JSMN_ERROR_NOMEM:
  ------------------
  |  Branch (945:9): [True: 0, False: 2.29k]
  ------------------
  946|      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]
  |  |  ------------------
  ------------------
  947|      0|            free(tokens);
  948|      0|            return PLIST_ERR_NO_MEM;
  949|     64|        case JSMN_ERROR_INVAL:
  ------------------
  |  Branch (949:9): [True: 64, False: 2.23k]
  ------------------
  950|     64|            PLIST_JSON_ERR("%s: Invalid character inside JSON string\n", __func__);
  ------------------
  |  |   48|     64|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 64]
  |  |  ------------------
  ------------------
  951|     64|            free(tokens);
  952|     64|            return PLIST_ERR_PARSE;
  953|    306|        case JSMN_ERROR_PART:
  ------------------
  |  Branch (953:9): [True: 306, False: 1.99k]
  ------------------
  954|    306|            PLIST_JSON_ERR("%s: Incomplete JSON, more bytes expected\n", __func__);
  ------------------
  |  |   48|    306|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 306]
  |  |  ------------------
  ------------------
  955|    306|            free(tokens);
  956|    306|            return PLIST_ERR_PARSE;
  957|      0|        case JSMN_ERROR_LIMIT:
  ------------------
  |  Branch (957:9): [True: 0, False: 2.29k]
  ------------------
  958|      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]
  |  |  ------------------
  ------------------
  959|      0|            free(tokens);
  960|      0|            return PLIST_ERR_PARSE;
  961|  1.92k|        default:
  ------------------
  |  Branch (961:9): [True: 1.92k, False: 370]
  ------------------
  962|  1.92k|            break;
  963|  2.29k|    }
  964|       |
  965|  1.92k|    int startindex = 0;
  966|  1.92k|    jsmntok_info_t ti = { tokens, parser.toknext, PLIST_ERR_SUCCESS };
  967|  1.92k|    switch (tokens[startindex].type) {
  968|    699|        case JSMN_PRIMITIVE:
  ------------------
  |  Branch (968:9): [True: 699, False: 1.22k]
  ------------------
  969|    699|            *plist = parse_primitive(json, &ti, &startindex);
  970|    699|            break;
  971|    178|        case JSMN_STRING:
  ------------------
  |  Branch (971:9): [True: 178, False: 1.74k]
  ------------------
  972|    178|            *plist = parse_string(json, &ti, &startindex);
  973|    178|            break;
  974|    455|        case JSMN_ARRAY:
  ------------------
  |  Branch (974:9): [True: 455, False: 1.47k]
  ------------------
  975|    455|            *plist = parse_array(json, &ti, &startindex, 0);
  976|    455|            break;
  977|    595|        case JSMN_OBJECT:
  ------------------
  |  Branch (977:9): [True: 595, False: 1.33k]
  ------------------
  978|    595|            *plist = parse_object(json, &ti, &startindex, 0);
  979|    595|            break;
  980|      0|        default:
  ------------------
  |  Branch (980:9): [True: 0, False: 1.92k]
  ------------------
  981|      0|            break;
  982|  1.92k|    }
  983|  1.92k|    free(tokens);
  984|  1.92k|    if (!*plist) {
  ------------------
  |  Branch (984:9): [True: 451, False: 1.47k]
  ------------------
  985|    451|        return (ti.err != PLIST_ERR_SUCCESS) ? ti.err : PLIST_ERR_PARSE;
  ------------------
  |  Branch (985:16): [True: 129, False: 322]
  ------------------
  986|    451|    }
  987|  1.47k|    return PLIST_ERR_SUCCESS;
  988|  1.92k|}
jplist.c:parse_primitive:
  552|  29.1k|{
  553|  29.1k|    if (ti->tokens[*index].type != JSMN_PRIMITIVE) {
  ------------------
  |  Branch (553:9): [True: 0, False: 29.1k]
  ------------------
  554|      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]
  |  |  ------------------
  ------------------
  555|      0|        return NULL;
  556|      0|    }
  557|  29.1k|    plist_t val = NULL;
  558|  29.1k|    const char* str_val = js + ti->tokens[*index].start;
  559|  29.1k|    const char* str_end = js + ti->tokens[*index].end;
  560|  29.1k|    size_t str_len = ti->tokens[*index].end - ti->tokens[*index].start;
  561|  29.1k|    if (!strncmp("false", str_val, str_len)) {
  ------------------
  |  Branch (561:9): [True: 4.43k, False: 24.7k]
  ------------------
  562|  4.43k|        val = plist_new_bool(0);
  563|  24.7k|    } else if (!strncmp("true", str_val, str_len)) {
  ------------------
  |  Branch (563:16): [True: 4.07k, False: 20.6k]
  ------------------
  564|  4.07k|        val = plist_new_bool(1);
  565|  20.6k|    } else if (!strncmp("null", str_val, str_len)) {
  ------------------
  |  Branch (565:16): [True: 14.0k, False: 6.61k]
  ------------------
  566|  14.0k|        plist_data_t data = plist_new_plist_data();
  567|  14.0k|        if (!data) {
  ------------------
  |  Branch (567:13): [True: 0, False: 14.0k]
  ------------------
  568|      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]
  |  |  ------------------
  ------------------
  569|      0|            return NULL;
  570|      0|        }
  571|  14.0k|        data->type = PLIST_NULL;
  572|  14.0k|        val = plist_new_node(data);
  573|  14.0k|    } else if (isdigit(str_val[0]) || (str_val[0] == '-' && str_val+1 < str_end && isdigit(str_val[1]))) {
  ------------------
  |  Branch (573:16): [True: 5.53k, False: 1.08k]
  |  Branch (573:40): [True: 933, False: 151]
  |  Branch (573:61): [True: 924, False: 9]
  |  Branch (573:84): [True: 917, False: 7]
  ------------------
  574|  6.44k|        char* endp = (char*)str_val;
  575|  6.44k|        int is_neg = (str_val[0] == '-');
  576|  6.44k|        int64_t intpart = parse_decimal(str_val, str_end, &endp);
  577|  6.44k|        if (endp >= str_end) {
  ------------------
  |  Branch (577:13): [True: 3.93k, False: 2.51k]
  ------------------
  578|       |            /* integer */
  579|  3.93k|            if (is_neg || intpart <= INT64_MAX) {
  ------------------
  |  Branch (579:17): [True: 658, False: 3.27k]
  |  Branch (579:27): [True: 3.27k, False: 0]
  ------------------
  580|  3.93k|                val = plist_new_int(intpart);
  581|  3.93k|            } else {
  582|      0|                val = plist_new_uint((uint64_t)intpart);
  583|      0|            }
  584|  3.93k|        } 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 (584:21): [True: 494, False: 2.02k]
  |  Branch (584:37): [True: 493, False: 1]
  |  Branch (584:57): [True: 492, False: 1]
  |  Branch (584:82): [True: 1.46k, False: 555]
  |  Branch (584:98): [True: 533, False: 22]
  |  Branch (584:115): [True: 1.98k, False: 15]
  |  Branch (584:136): [True: 847, False: 1.13k]
  |  Branch (584:160): [True: 807, False: 332]
  |  Branch (584:182): [True: 323, False: 9]
  |  Branch (584:205): [True: 1.11k, False: 15]
  |  Branch (584:225): [True: 1.11k, False: 1]
  ------------------
  585|       |            /* floating point */
  586|  2.45k|            double dval = (double)intpart;
  587|  2.45k|            char* fendp = endp;
  588|  2.45k|            int err = 0;
  589|  2.45k|            do {
  590|  2.45k|                if (*endp == '.') {
  ------------------
  |  Branch (590:21): [True: 492, False: 1.96k]
  ------------------
  591|    492|                    fendp++;
  592|    492|                    double frac = 0;
  593|    492|                    double p = 0.1;
  594|  1.28k|                    while (fendp < str_end && isdigit(*fendp)) {
  ------------------
  |  Branch (594:28): [True: 844, False: 441]
  |  Branch (594:47): [True: 793, False: 51]
  ------------------
  595|    793|                        frac = frac + (*fendp - '0') * p;
  596|    793|                        p *= 0.1;
  597|    793|                        fendp++;
  598|    793|                    }
  599|    492|                    if (is_neg) {
  ------------------
  |  Branch (599:25): [True: 254, False: 238]
  ------------------
  600|    254|                        dval -= frac;
  601|    254|                    } else {
  602|    238|                        dval += frac;
  603|    238|                    }
  604|    492|                }
  605|  2.45k|                if (fendp >= str_end) {
  ------------------
  |  Branch (605:21): [True: 441, False: 2.01k]
  ------------------
  606|    441|                    break;
  607|    441|                }
  608|  2.01k|                if (fendp+1 < str_end && (*fendp == 'e' || *fendp == 'E') && (isdigit(*(fendp+1)) || (((*(fendp+1) == '-') || (*(fendp+1) == '+')) && fendp+2 < str_end && isdigit(*(fendp+2))))) {
  ------------------
  |  Branch (608:21): [True: 2.01k, False: 1]
  |  Branch (608:43): [True: 1.48k, False: 525]
  |  Branch (608:60): [True: 513, False: 12]
  |  Branch (608:79): [True: 848, False: 1.15k]
  |  Branch (608:104): [True: 801, False: 350]
  |  Branch (608:127): [True: 344, False: 6]
  |  Branch (608:151): [True: 1.14k, False: 1]
  |  Branch (608:172): [True: 1.14k, False: 1]
  ------------------
  609|  1.99k|                    int64_t exp = parse_decimal(fendp+1, str_end, &fendp);
  610|  1.99k|                    dval = dval * pow(10, (double)exp);
  611|  1.99k|                } else {
  612|     21|                    PLIST_JSON_ERR("%s: invalid character at offset %d when parsing floating point value\n", __func__, (int)(fendp - js));
  ------------------
  |  |   48|     21|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 21]
  |  |  ------------------
  ------------------
  613|     21|                    err++;
  614|     21|                }
  615|  2.01k|            } while (0);
  ------------------
  |  Branch (615:22): [Folded, False: 2.01k]
  ------------------
  616|  2.45k|            if (!err) {
  ------------------
  |  Branch (616:17): [True: 2.43k, False: 21]
  ------------------
  617|  2.43k|                if (isinf(dval) || isnan(dval)) {
  ------------------
  |  Branch (617:21): [True: 133, False: 2.29k]
  |  Branch (617:36): [True: 24, False: 2.27k]
  ------------------
  618|    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]
  |  |  ------------------
  ------------------
  619|  2.27k|                } else {
  620|  2.27k|                    val = plist_new_real(dval);
  621|  2.27k|                }
  622|  2.43k|            }
  623|  2.45k|        } else {
  624|     62|            PLIST_JSON_ERR("%s: invalid character at offset %d when parsing numerical value\n", __func__, (int)(endp - js));
  ------------------
  |  |   48|     62|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 62]
  |  |  ------------------
  ------------------
  625|     62|        }
  626|  6.44k|    } else {
  627|    167|        PLIST_JSON_ERR("%s: invalid primitive value '%.*s' encountered\n", __func__, (int)str_len, str_val);
  ------------------
  |  |   48|    167|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 167]
  |  |  ------------------
  ------------------
  628|    167|    }
  629|  29.1k|    if (!val) {
  ------------------
  |  Branch (629:9): [True: 407, False: 28.7k]
  ------------------
  630|    407|        PLIST_JSON_ERR("%s: failed to create node\n", __func__);
  ------------------
  |  |   48|    407|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 407]
  |  |  ------------------
  ------------------
  631|    407|        return NULL;
  632|    407|    }
  633|  28.7k|    (*index)++;
  634|  28.7k|    return val;
  635|  29.1k|}
jplist.c:parse_decimal:
  506|  8.43k|{
  507|  8.43k|    const uint64_t po10i_limit = INT64_MAX / 10;
  508|  8.43k|    uint64_t MAX = INT64_MAX;
  509|  8.43k|    uint64_t x = 0;
  510|  8.43k|    int is_neg = 0;
  511|  8.43k|    *endp = (char*)str;
  512|       |
  513|  8.43k|    if (str[0] == '-') {
  ------------------
  |  Branch (513:9): [True: 1.71k, False: 6.72k]
  ------------------
  514|  1.71k|        is_neg = 1;
  515|  1.71k|        (*endp)++;
  516|  6.72k|    } else if (str[0] == '+') {
  ------------------
  |  Branch (516:16): [True: 343, False: 6.37k]
  ------------------
  517|    343|        (*endp)++;
  518|    343|    }
  519|  8.43k|    if (is_neg) {
  ------------------
  |  Branch (519:9): [True: 1.71k, False: 6.72k]
  ------------------
  520|  1.71k|        MAX++;
  521|  1.71k|    }
  522|  43.8k|    while (*endp < str_end && isdigit(**endp)) {
  ------------------
  |  Branch (522:12): [True: 39.2k, False: 4.58k]
  |  Branch (522:31): [True: 36.7k, False: 2.58k]
  ------------------
  523|  36.7k|        if (x > po10i_limit) {
  ------------------
  |  Branch (523:13): [True: 764, False: 35.9k]
  ------------------
  524|    764|            x = MAX;
  525|    764|            break;
  526|    764|        }
  527|  35.9k|        x = x * 10;
  528|  35.9k|        unsigned int add = (**endp - '0');
  529|  35.9k|        if (x + add > MAX) {
  ------------------
  |  Branch (529:13): [True: 507, False: 35.4k]
  ------------------
  530|    507|            x = MAX;
  531|    507|            break;
  532|    507|        }
  533|  35.4k|        x += add;
  534|  35.4k|        (*endp)++;
  535|  35.4k|    }
  536|       |
  537|       |    // swallow the rest of the digits in case we dropped out early
  538|  10.7k|    while (*endp < str_end && isdigit(**endp)) (*endp)++;
  ------------------
  |  Branch (538:12): [True: 4.86k, False: 5.84k]
  |  Branch (538:31): [True: 2.27k, False: 2.59k]
  ------------------
  539|       |
  540|  8.43k|    int64_t result = x;
  541|  8.43k|    if (is_neg) {
  ------------------
  |  Branch (541:9): [True: 1.71k, False: 6.72k]
  ------------------
  542|  1.71k|        if (x == MAX) {
  ------------------
  |  Branch (542:13): [True: 790, False: 927]
  ------------------
  543|    790|            result = INT64_MIN;
  544|    927|        } else {
  545|    927|            result = -(int64_t)x;
  546|    927|        }
  547|  1.71k|    }
  548|  8.43k|    return result;
  549|  8.43k|}
jplist.c:parse_string:
  717|  34.4k|{
  718|  34.4k|    if (ti->tokens[*index].type != JSMN_STRING) {
  ------------------
  |  Branch (718:9): [True: 0, False: 34.4k]
  ------------------
  719|      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]
  |  |  ------------------
  ------------------
  720|      0|        return NULL;
  721|      0|    }
  722|       |
  723|  34.4k|    size_t str_len = 0; ;
  724|  34.4k|    char* strval = unescape_string(js + ti->tokens[*index].start, ti->tokens[*index].end - ti->tokens[*index].start, &str_len);
  725|  34.4k|    if (!strval) {
  ------------------
  |  Branch (725:9): [True: 15, False: 34.4k]
  ------------------
  726|     15|        return NULL;
  727|     15|    }
  728|  34.4k|    plist_t node;
  729|       |
  730|  34.4k|    plist_data_t data = plist_new_plist_data();
  731|  34.4k|    if (!data) {
  ------------------
  |  Branch (731:9): [True: 0, False: 34.4k]
  ------------------
  732|      0|        free(strval);
  733|      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]
  |  |  ------------------
  ------------------
  734|      0|        return NULL;
  735|      0|    }
  736|  34.4k|    data->type = PLIST_STRING;
  737|  34.4k|    data->strval = strval;
  738|  34.4k|    data->length = str_len;
  739|  34.4k|    node = plist_new_node(data);
  740|  34.4k|    if (!node) {
  ------------------
  |  Branch (740:9): [True: 0, False: 34.4k]
  ------------------
  741|      0|        plist_free_data(data);
  742|      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]
  |  |  ------------------
  ------------------
  743|      0|        return NULL;
  744|      0|    }
  745|       |
  746|  34.4k|    (*index)++;
  747|  34.4k|    return node;
  748|  34.4k|}
jplist.c:unescape_string:
  638|   101k|{
  639|   101k|    char* strval = strndup(str_val, str_len);
  640|   101k|    if (!strval) return NULL;
  ------------------
  |  Branch (640:9): [True: 0, False: 101k]
  ------------------
  641|   101k|    size_t i = 0;
  642|   229k|    while (i < str_len) {
  ------------------
  |  Branch (642:12): [True: 127k, False: 101k]
  ------------------
  643|   127k|        if (strval[i] == '\\' && i < str_len-1) {
  ------------------
  |  Branch (643:13): [True: 3.42k, False: 124k]
  |  Branch (643:34): [True: 3.42k, False: 0]
  ------------------
  644|  3.42k|            switch (strval[i+1]) {
  645|  1.55k|                case '\"': case '/' : case '\\' : case 'b' :
  ------------------
  |  Branch (645:17): [True: 220, False: 3.20k]
  |  Branch (645:28): [True: 429, False: 2.99k]
  |  Branch (645:39): [True: 324, False: 3.09k]
  |  Branch (645:51): [True: 581, False: 2.83k]
  ------------------
  646|  2.63k|                case 'f' : case 'r' : case 'n'  : case 't' :
  ------------------
  |  Branch (646:17): [True: 299, False: 3.12k]
  |  Branch (646:28): [True: 269, False: 3.15k]
  |  Branch (646:39): [True: 210, False: 3.21k]
  |  Branch (646:51): [True: 300, False: 3.12k]
  ------------------
  647|  2.63k|                    memmove(strval+i, strval+i+1, str_len - (i+1));
  648|  2.63k|                    str_len--;
  649|  2.63k|                    switch (strval[i]) {
  650|    581|                        case 'b':
  ------------------
  |  Branch (650:25): [True: 581, False: 2.05k]
  ------------------
  651|    581|                            strval[i] = '\b';
  652|    581|                            break;
  653|    299|                        case 'f':
  ------------------
  |  Branch (653:25): [True: 299, False: 2.33k]
  ------------------
  654|    299|                            strval[i] = '\f';
  655|    299|                            break;
  656|    269|                        case 'r':
  ------------------
  |  Branch (656:25): [True: 269, False: 2.36k]
  ------------------
  657|    269|                            strval[i] = '\r';
  658|    269|                            break;
  659|    210|                        case 'n':
  ------------------
  |  Branch (659:25): [True: 210, False: 2.42k]
  ------------------
  660|    210|                            strval[i] = '\n';
  661|    210|                            break;
  662|    300|                        case 't':
  ------------------
  |  Branch (662:25): [True: 300, False: 2.33k]
  ------------------
  663|    300|                            strval[i] = '\t';
  664|    300|                            break;
  665|    973|                        default:
  ------------------
  |  Branch (665:25): [True: 973, False: 1.65k]
  ------------------
  666|    973|                            break;
  667|  2.63k|                    }
  668|  2.63k|                    break;
  669|  2.63k|                case 'u': {
  ------------------
  |  Branch (669:17): [True: 788, False: 2.63k]
  ------------------
  670|    788|                    unsigned int val = 0;
  671|    788|                    if (str_len-(i+2) < 4) {
  ------------------
  |  Branch (671:25): [True: 7, False: 781]
  ------------------
  672|      7|                        PLIST_JSON_ERR("%s: invalid escape sequence '%s' (too short)\n", __func__, strval+i);
  ------------------
  |  |   48|      7|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 7]
  |  |  ------------------
  ------------------
  673|      7|                        free(strval);
  674|      7|                        return NULL;
  675|      7|                    }
  676|    781|                    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 (676:27): [True: 779, False: 2]
  |  Branch (676:52): [True: 776, False: 3]
  |  Branch (676:77): [True: 772, False: 4]
  |  Branch (676:102): [True: 771, False: 1]
  |  Branch (676:128): [True: 0, False: 771]
  ------------------
  677|     10|                        PLIST_JSON_ERR("%s: invalid escape sequence '%.*s'\n", __func__, 6, 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]
  |  |  ------------------
  ------------------
  678|     10|                        free(strval);
  679|     10|                        return NULL;
  680|     10|                    }
  681|    771|                    int bytelen = 0;
  682|    771|                    if (val >= 0x800) {
  ------------------
  |  Branch (682:25): [True: 242, False: 529]
  ------------------
  683|       |                        /* three bytes */
  684|    242|                        strval[i]   = (char)(0xE0 + ((val >> 12) & 0xF));
  685|    242|                        strval[i+1] = (char)(0x80 + ((val >> 6) & 0x3F));
  686|    242|                        strval[i+2] = (char)(0x80 + (val & 0x3F));
  687|    242|                        bytelen = 3;
  688|    529|                    } else if (val >= 0x80) {
  ------------------
  |  Branch (688:32): [True: 223, False: 306]
  ------------------
  689|       |                        /* two bytes */
  690|    223|                        strval[i]   = (char)(0xC0 + ((val >> 6) & 0x1F));
  691|    223|                        strval[i+1] = (char)(0x80 + (val & 0x3F));
  692|    223|                        bytelen = 2;
  693|    306|                    } else {
  694|       |                        /* one byte */
  695|    306|                        strval[i] = (char)(val & 0x7F);
  696|    306|                        bytelen = 1;
  697|    306|                    }
  698|    771|                    memmove(strval+i+bytelen, strval+i+6, str_len - (i+5));
  699|    771|                    str_len -= (6-bytelen);
  700|    771|                }   break;
  701|      0|                default:
  ------------------
  |  Branch (701:17): [True: 0, False: 3.42k]
  ------------------
  702|      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]
  |  |  ------------------
  ------------------
  703|      0|                    free(strval);
  704|      0|                    return NULL;
  705|  3.42k|            }
  706|  3.42k|        }
  707|   127k|        i++;
  708|   127k|    }
  709|   101k|    strval[str_len] = '\0';
  710|   101k|    if (new_len) {
  ------------------
  |  Branch (710:9): [True: 34.4k, False: 67.1k]
  ------------------
  711|  34.4k|        *new_len = str_len;
  712|  34.4k|    }
  713|   101k|    return strval;
  714|   101k|}
jplist.c:parse_array:
  753|  57.9k|{
  754|  57.9k|    if (ti->tokens[*index].type != JSMN_ARRAY) {
  ------------------
  |  Branch (754:9): [True: 0, False: 57.9k]
  ------------------
  755|      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]
  |  |  ------------------
  ------------------
  756|      0|        ti->err = PLIST_ERR_PARSE;
  757|      0|        return NULL;
  758|      0|    }
  759|  57.9k|    if (depth > PLIST_MAX_NESTING_DEPTH) {
  ------------------
  |  |   56|  57.9k|#define PLIST_MAX_NESTING_DEPTH NODE_MAX_DEPTH
  |  |  ------------------
  |  |  |  |   33|  57.9k|#define NODE_MAX_DEPTH 512
  |  |  ------------------
  ------------------
  |  Branch (759:9): [True: 1, False: 57.9k]
  ------------------
  760|      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]
  |  |  ------------------
  ------------------
  761|      1|        ti->err = PLIST_ERR_MAX_NESTING;
  762|      1|        return NULL;
  763|      1|    }
  764|  57.9k|    plist_t arr = plist_new_array();
  765|  57.9k|    if (!arr) {
  ------------------
  |  Branch (765:9): [True: 0, False: 57.9k]
  ------------------
  766|      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]
  |  |  ------------------
  ------------------
  767|      0|        ti->err = PLIST_ERR_NO_MEM;
  768|      0|        return NULL;
  769|      0|    }
  770|  57.9k|    size_t num_tokens = ti->tokens[*index].size;
  771|  57.9k|    size_t num;
  772|  57.9k|    int j = (*index)+1;
  773|   118k|    for (num = 0; num < num_tokens; num++) {
  ------------------
  |  Branch (773:19): [True: 64.5k, False: 54.4k]
  ------------------
  774|  64.5k|        if (j >= ti->count) {
  ------------------
  |  Branch (774:13): [True: 0, False: 64.5k]
  ------------------
  775|      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]
  |  |  ------------------
  ------------------
  776|      0|            plist_free(arr);
  777|      0|            ti->err = PLIST_ERR_PARSE;
  778|      0|            return NULL;
  779|      0|        }
  780|  64.5k|        plist_t val = NULL;
  781|  64.5k|        switch (ti->tokens[j].type) {
  782|    396|            case JSMN_OBJECT:
  ------------------
  |  Branch (782:13): [True: 396, False: 64.1k]
  ------------------
  783|    396|                val = parse_object(js, ti, &j, depth+1);
  784|    396|                break;
  785|  36.5k|            case JSMN_ARRAY:
  ------------------
  |  Branch (785:13): [True: 36.5k, False: 27.9k]
  ------------------
  786|  36.5k|                val = parse_array(js, ti, &j, depth+1);
  787|  36.5k|                break;
  788|    849|            case JSMN_STRING:
  ------------------
  |  Branch (788:13): [True: 849, False: 63.6k]
  ------------------
  789|    849|                val = parse_string(js, ti, &j);
  790|    849|                break;
  791|  26.7k|            case JSMN_PRIMITIVE:
  ------------------
  |  Branch (791:13): [True: 26.7k, False: 37.7k]
  ------------------
  792|  26.7k|                val = parse_primitive(js, ti, &j);
  793|  26.7k|                break;
  794|      0|            default:
  ------------------
  |  Branch (794:13): [True: 0, False: 64.5k]
  ------------------
  795|      0|                break;
  796|  64.5k|        }
  797|  64.5k|        if (val) {
  ------------------
  |  Branch (797:13): [True: 61.0k, False: 3.51k]
  ------------------
  798|  61.0k|            plist_array_append_item(arr, val);
  799|       |            // if append failed, val still has no parent, free it and abort
  800|  61.0k|            if (((node_t)val)->parent == NULL) {
  ------------------
  |  Branch (800:17): [True: 2, False: 61.0k]
  ------------------
  801|      2|                plist_free(val);
  802|      2|                plist_free(arr);
  803|      2|                ti->err = PLIST_ERR_NO_MEM;
  804|      2|                return NULL;
  805|      2|            }
  806|  61.0k|        } else {
  807|  3.51k|            plist_free(arr);
  808|  3.51k|            ti->err = PLIST_ERR_PARSE;
  809|  3.51k|            return NULL;
  810|  3.51k|        }
  811|  64.5k|    }
  812|  54.4k|    *(index) = j;
  813|  54.4k|    return arr;
  814|  57.9k|}
jplist.c:parse_object:
  817|  12.0k|{
  818|  12.0k|    if (ti->tokens[*index].type != JSMN_OBJECT) {
  ------------------
  |  Branch (818:9): [True: 0, False: 12.0k]
  ------------------
  819|      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]
  |  |  ------------------
  ------------------
  820|      0|        ti->err = PLIST_ERR_PARSE;
  821|      0|        return NULL;
  822|      0|    }
  823|  12.0k|    if (depth > PLIST_MAX_NESTING_DEPTH) {
  ------------------
  |  |   56|  12.0k|#define PLIST_MAX_NESTING_DEPTH NODE_MAX_DEPTH
  |  |  ------------------
  |  |  |  |   33|  12.0k|#define NODE_MAX_DEPTH 512
  |  |  ------------------
  ------------------
  |  Branch (823:9): [True: 1, False: 12.0k]
  ------------------
  824|      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]
  |  |  ------------------
  ------------------
  825|      1|        ti->err = PLIST_ERR_MAX_NESTING;
  826|      1|        return NULL;
  827|      1|    }
  828|  12.0k|    size_t num_tokens = ti->tokens[*index].size;
  829|  12.0k|    size_t num;
  830|  12.0k|    int j = (*index)+1;
  831|  12.0k|    if (num_tokens % 2 != 0) {
  ------------------
  |  Branch (831:9): [True: 12, False: 11.9k]
  ------------------
  832|     12|        PLIST_JSON_ERR("%s: number of children must be even\n", __func__);
  ------------------
  |  |   48|     12|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (48:33): [True: 0, False: 12]
  |  |  ------------------
  ------------------
  833|     12|        ti->err = PLIST_ERR_PARSE;
  834|     12|        return NULL;
  835|     12|    }
  836|  11.9k|    plist_t obj = plist_new_dict();
  837|  11.9k|    if (!obj) {
  ------------------
  |  Branch (837:9): [True: 0, False: 11.9k]
  ------------------
  838|      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]
  |  |  ------------------
  ------------------
  839|      0|        ti->err = PLIST_ERR_NO_MEM;
  840|      0|        return NULL;
  841|      0|    }
  842|  78.9k|    for (num = 0; num < num_tokens; num++) {
  ------------------
  |  Branch (842:19): [True: 67.1k, False: 11.7k]
  ------------------
  843|  67.1k|        if (j+1 >= ti->count) {
  ------------------
  |  Branch (843:13): [True: 0, False: 67.1k]
  ------------------
  844|      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]
  |  |  ------------------
  ------------------
  845|      0|            plist_free(obj);
  846|      0|            ti->err = PLIST_ERR_PARSE;
  847|      0|            return NULL;
  848|      0|        }
  849|  67.1k|        if (ti->tokens[j].type == JSMN_STRING) {
  ------------------
  |  Branch (849:13): [True: 67.1k, False: 6]
  ------------------
  850|  67.1k|            char* key = unescape_string(js + ti->tokens[j].start, ti->tokens[j].end - ti->tokens[j].start, NULL);
  851|  67.1k|            if (!key) {
  ------------------
  |  Branch (851:17): [True: 2, False: 67.1k]
  ------------------
  852|      2|                plist_free(obj);
  853|      2|                ti->err = PLIST_ERR_PARSE;
  854|      2|                return NULL;
  855|      2|            }
  856|  67.1k|            plist_t val = NULL;
  857|  67.1k|            j++;
  858|  67.1k|            num++;
  859|  67.1k|            switch (ti->tokens[j].type) {
  860|  11.0k|                case JSMN_OBJECT:
  ------------------
  |  Branch (860:17): [True: 11.0k, False: 56.1k]
  ------------------
  861|  11.0k|                    val = parse_object(js, ti, &j, depth+1);
  862|  11.0k|                    break;
  863|  20.9k|                case JSMN_ARRAY:
  ------------------
  |  Branch (863:17): [True: 20.9k, False: 46.1k]
  ------------------
  864|  20.9k|                    val = parse_array(js, ti, &j, depth+1);
  865|  20.9k|                    break;
  866|  33.4k|                case JSMN_STRING:
  ------------------
  |  Branch (866:17): [True: 33.4k, False: 33.7k]
  ------------------
  867|  33.4k|                    val = parse_string(js, ti, &j);
  868|  33.4k|                    break;
  869|  1.74k|                case JSMN_PRIMITIVE:
  ------------------
  |  Branch (869:17): [True: 1.74k, False: 65.4k]
  ------------------
  870|  1.74k|                    val = parse_primitive(js, ti, &j);
  871|  1.74k|                    break;
  872|      0|                default:
  ------------------
  |  Branch (872:17): [True: 0, False: 67.1k]
  ------------------
  873|      0|                    break;
  874|  67.1k|            }
  875|  67.1k|            if (val) {
  ------------------
  |  Branch (875:17): [True: 66.9k, False: 198]
  ------------------
  876|  66.9k|                plist_dict_set_item(obj, key, val);
  877|       |                // if set failed, val still has no parent, free it and abort
  878|  66.9k|                if (((node_t)val)->parent == NULL) {
  ------------------
  |  Branch (878:21): [True: 5, False: 66.9k]
  ------------------
  879|      5|                    plist_free(val);
  880|      5|                    free(key);
  881|      5|                    plist_free(obj);
  882|      5|                    ti->err = PLIST_ERR_NO_MEM;
  883|      5|                    return NULL;
  884|      5|                }
  885|  66.9k|            } else {
  886|    198|                free(key);
  887|    198|                plist_free(obj);
  888|    198|                ti->err = PLIST_ERR_PARSE;
  889|    198|                return NULL;
  890|    198|            }
  891|  66.9k|            free(key);
  892|  66.9k|        } else {
  893|      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]
  |  |  ------------------
  ------------------
  894|      6|            plist_free(obj);
  895|      6|            ti->err = PLIST_ERR_PARSE;
  896|      6|            return NULL;
  897|      6|        }
  898|  67.1k|    }
  899|  11.7k|    (*index) = j;
  900|  11.7k|    return obj;
  901|  11.9k|}

jsmn_parse:
  173|  13.0k|		unsigned int num_tokens) {
  174|  13.0k|	jsmnerr_t r;
  175|  13.0k|	int i;
  176|  13.0k|	jsmntok_t *token;
  177|       |
  178|  13.0k|	parser->end = length;
  179|       |
  180|  13.0k|	if (num_tokens >= INT_MAX) {
  ------------------
  |  Branch (180:6): [True: 0, False: 13.0k]
  ------------------
  181|      0|		return JSMN_ERROR_LIMIT;
  182|      0|	}
  183|  13.0k|	if (length > SIZE_MAX / 2) {
  ------------------
  |  Branch (183:6): [True: 0, False: 13.0k]
  ------------------
  184|      0|		return JSMN_ERROR_LIMIT;
  185|      0|	}
  186|       |
  187|   430k|	for (; (parser->end > 0 && parser->pos < parser->end) && js[parser->pos] != '\0'; parser->pos++) {
  ------------------
  |  Branch (187:10): [True: 430k, False: 0]
  |  Branch (187:29): [True: 428k, False: 2.10k]
  |  Branch (187:59): [True: 428k, False: 5]
  ------------------
  188|   428k|		char c;
  189|   428k|		jsmntype_t type;
  190|       |
  191|   428k|		c = js[parser->pos];
  192|   428k|		switch (c) {
  193|   170k|			case '{': case '[':
  ------------------
  |  Branch (193:4): [True: 44.0k, False: 383k]
  |  Branch (193:14): [True: 126k, False: 301k]
  ------------------
  194|   170k|				token = jsmn_alloc_token(parser, tokens, num_tokens);
  195|   170k|				if (token == NULL)
  ------------------
  |  Branch (195:9): [True: 7.08k, False: 163k]
  ------------------
  196|  7.08k|					return JSMN_ERROR_NOMEM;
  197|   163k|				if (parser->toksuper != -1) {
  ------------------
  |  Branch (197:9): [True: 157k, False: 6.38k]
  ------------------
  198|   157k|					tokens[parser->toksuper].size++;
  199|       |#ifdef JSMN_PARENT_LINKS
  200|       |					token->parent = parser->toksuper;
  201|       |#endif
  202|   157k|				}
  203|   163k|				token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
  ------------------
  |  Branch (203:20): [True: 41.5k, False: 122k]
  ------------------
  204|   163k|				token->start = parser->pos;
  205|   163k|				parser->toksuper = parser->toknext - 1;
  206|   163k|				break;
  207|  76.8k|			case '}': case ']':
  ------------------
  |  Branch (207:4): [True: 17.4k, False: 410k]
  |  Branch (207:14): [True: 59.3k, False: 368k]
  ------------------
  208|  76.8k|				type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
  ------------------
  |  Branch (208:13): [True: 17.4k, False: 59.3k]
  ------------------
  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|  6.73M|				for (i = parser->toknext - 1; i >= 0; i--) {
  ------------------
  |  Branch (232:35): [True: 6.73M, False: 38]
  ------------------
  233|  6.73M|					token = &tokens[i];
  234|  6.73M|					if (token->start != JSMN_POS_INVALID && token->end == JSMN_POS_INVALID) {
  ------------------
  |  |   35|  13.4M|#define JSMN_POS_INVALID ((size_t)SIZE_MAX)
  ------------------
              					if (token->start != JSMN_POS_INVALID && token->end == JSMN_POS_INVALID) {
  ------------------
  |  |   35|  6.73M|#define JSMN_POS_INVALID ((size_t)SIZE_MAX)
  ------------------
  |  Branch (234:10): [True: 6.73M, False: 0]
  |  Branch (234:46): [True: 76.7k, False: 6.66M]
  ------------------
  235|  76.7k|						if (token->type != type) {
  ------------------
  |  Branch (235:11): [True: 3, False: 76.7k]
  ------------------
  236|      3|							return JSMN_ERROR_INVAL;
  237|      3|						}
  238|  76.7k|						parser->toksuper = -1;
  239|  76.7k|						token->end = parser->pos + 1;
  240|  76.7k|						break;
  241|  76.7k|					}
  242|  6.73M|				}
  243|       |				/* Error if unmatched closing bracket */
  244|  76.8k|				if (i == -1) return JSMN_ERROR_INVAL;
  ------------------
  |  Branch (244:9): [True: 38, False: 76.7k]
  ------------------
  245|  27.0M|				for (; i >= 0; i--) {
  ------------------
  |  Branch (245:12): [True: 27.0M, False: 6.17k]
  ------------------
  246|  27.0M|					token = &tokens[i];
  247|  27.0M|					if (token->start != JSMN_POS_INVALID && token->end == JSMN_POS_INVALID) {
  ------------------
  |  |   35|  54.1M|#define JSMN_POS_INVALID ((size_t)SIZE_MAX)
  ------------------
              					if (token->start != JSMN_POS_INVALID && token->end == JSMN_POS_INVALID) {
  ------------------
  |  |   35|  27.0M|#define JSMN_POS_INVALID ((size_t)SIZE_MAX)
  ------------------
  |  Branch (247:10): [True: 27.0M, False: 0]
  |  Branch (247:46): [True: 70.5k, False: 26.9M]
  ------------------
  248|  70.5k|						parser->toksuper = i;
  249|  70.5k|						break;
  250|  70.5k|					}
  251|  27.0M|				}
  252|  76.7k|#endif
  253|  76.7k|				break;
  254|   112k|			case '\"':
  ------------------
  |  Branch (254:4): [True: 112k, False: 315k]
  ------------------
  255|   112k|				r = jsmn_parse_string(parser, js, tokens, num_tokens);
  256|   112k|				if (r < 0) return r;
  ------------------
  |  Branch (256:9): [True: 2.61k, False: 109k]
  ------------------
  257|   109k|				if (parser->toksuper != -1)
  ------------------
  |  Branch (257:9): [True: 109k, False: 460]
  ------------------
  258|   109k|					tokens[parser->toksuper].size++;
  259|   109k|				break;
  260|  33.7k|			case '\t' : case '\r' : case '\n' : case ':' : case ',': case ' ':
  ------------------
  |  Branch (260:4): [True: 1.30k, False: 426k]
  |  Branch (260:16): [True: 1.82k, False: 426k]
  |  Branch (260:28): [True: 13.5k, False: 414k]
  |  Branch (260:40): [True: 12.4k, False: 415k]
  |  Branch (260:51): [True: 3.90k, False: 424k]
  |  Branch (260:61): [True: 779, False: 427k]
  ------------------
  261|  33.7k|				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|  34.2k|			default:
  ------------------
  |  Branch (269:4): [True: 34.2k, False: 393k]
  ------------------
  270|  34.2k|#endif
  271|  34.2k|				r = jsmn_parse_primitive(parser, js, tokens, num_tokens);
  272|  34.2k|				if (r < 0) return r;
  ------------------
  |  Branch (272:9): [True: 1.15k, False: 33.0k]
  ------------------
  273|  33.0k|				if (parser->toksuper != -1)
  ------------------
  |  Branch (273:9): [True: 31.2k, False: 1.87k]
  ------------------
  274|  31.2k|					tokens[parser->toksuper].size++;
  275|  33.0k|				break;
  276|       |
  277|       |#ifdef JSMN_STRICT
  278|       |			/* Unexpected char in strict mode */
  279|       |			default:
  280|       |				return JSMN_ERROR_INVAL;
  281|       |#endif
  282|       |
  283|   428k|		}
  284|   428k|	}
  285|       |
  286|   217k|	for (i = parser->toknext - 1; i >= 0; i--) {
  ------------------
  |  Branch (286:32): [True: 215k, False: 1.92k]
  ------------------
  287|       |		/* Unmatched opened object or array */
  288|   215k|		if (tokens[i].start != JSMN_POS_INVALID && tokens[i].end == JSMN_POS_INVALID) {
  ------------------
  |  |   35|   431k|#define JSMN_POS_INVALID ((size_t)SIZE_MAX)
  ------------------
              		if (tokens[i].start != JSMN_POS_INVALID && tokens[i].end == JSMN_POS_INVALID) {
  ------------------
  |  |   35|   215k|#define JSMN_POS_INVALID ((size_t)SIZE_MAX)
  ------------------
  |  Branch (288:7): [True: 215k, False: 0]
  |  Branch (288:46): [True: 179, False: 215k]
  ------------------
  289|    179|			return JSMN_ERROR_PART;
  290|    179|		}
  291|   215k|	}
  292|       |
  293|  1.92k|	return JSMN_SUCCESS;
  294|  2.10k|}
jsmn_init:
  300|  2.29k|void jsmn_init(jsmn_parser *parser) {
  301|  2.29k|	parser->pos = 0;
  302|  2.29k|	parser->end = 0;
  303|  2.29k|	parser->toknext = 0;
  304|  2.29k|	parser->toksuper = -1;
  305|  2.29k|}
jsmn.c:jsmn_alloc_token:
   41|   317k|		jsmntok_t *tokens, unsigned int num_tokens) {
   42|   317k|	jsmntok_t *tok;
   43|   317k|	if ((unsigned int)parser->toknext >= num_tokens) {
  ------------------
  |  Branch (43:6): [True: 10.7k, False: 306k]
  ------------------
   44|  10.7k|		return NULL;
   45|  10.7k|	}
   46|   306k|	tok = &tokens[parser->toknext++];
   47|   306k|	tok->start = tok->end = JSMN_POS_INVALID;
  ------------------
  |  |   35|   306k|#define JSMN_POS_INVALID ((size_t)SIZE_MAX)
  ------------------
   48|   306k|	tok->size = 0;
   49|       |#ifdef JSMN_PARENT_LINKS
   50|       |	tok->parent = -1;
   51|       |#endif
   52|   306k|	return tok;
   53|   317k|}
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|   299k|	for (; (parser->end > 0 && parser->pos < parser->end) && js[parser->pos] != '\0'; parser->pos++) {
  ------------------
  |  Branch (125:10): [True: 299k, False: 0]
  |  Branch (125:29): [True: 298k, False: 126]
  |  Branch (125:59): [True: 298k, False: 1]
  ------------------
  126|   298k|		char c = js[parser->pos];
  127|       |
  128|       |		/* Quote: end of string */
  129|   298k|		if (c == '\"') {
  ------------------
  |  Branch (129:7): [True: 112k, False: 186k]
  ------------------
  130|   112k|			token = jsmn_alloc_token(parser, tokens, num_tokens);
  131|   112k|			if (token == NULL) {
  ------------------
  |  Branch (131:8): [True: 2.48k, False: 109k]
  ------------------
  132|  2.48k|				parser->pos = start;
  133|  2.48k|				return JSMN_ERROR_NOMEM;
  134|  2.48k|			}
  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|   186k|		if (c == '\\') {
  ------------------
  |  Branch (143:7): [True: 25.0k, False: 161k]
  ------------------
  144|  25.0k|			parser->pos++;
  145|  25.0k|			if (parser->end > 0 && parser->pos >= parser->end) {
  ------------------
  |  Branch (145:8): [True: 25.0k, False: 0]
  |  Branch (145:27): [True: 4, False: 25.0k]
  ------------------
  146|      4|				parser->pos = start;
  147|      4|				return JSMN_ERROR_INVAL;
  148|      4|			}
  149|  25.0k|			switch (js[parser->pos]) {
  150|       |				/* Allowed escaped symbols */
  151|  7.03k|				case '\"': case '/' : case '\\' : case 'b' :
  ------------------
  |  Branch (151:5): [True: 653, False: 24.3k]
  |  Branch (151:16): [True: 674, False: 24.3k]
  |  Branch (151:27): [True: 4.93k, False: 20.0k]
  |  Branch (151:39): [True: 780, False: 24.2k]
  ------------------
  152|  23.4k|				case 'f' : case 'r' : case 'n'  : case 't' :
  ------------------
  |  Branch (152:5): [True: 1.47k, False: 23.5k]
  |  Branch (152:16): [True: 580, False: 24.4k]
  |  Branch (152:27): [True: 13.6k, False: 11.3k]
  |  Branch (152:39): [True: 752, False: 24.2k]
  ------------------
  153|  23.4k|					break;
  154|       |				/* Allows escaped symbol \uXXXX */
  155|  1.54k|				case 'u':
  ------------------
  |  Branch (155:5): [True: 1.54k, False: 23.4k]
  ------------------
  156|       |					/* TODO */
  157|  1.54k|					break;
  158|       |				/* Unexpected symbol */
  159|      2|				default:
  ------------------
  |  Branch (159:5): [True: 2, False: 25.0k]
  ------------------
  160|      2|					parser->pos = start;
  161|      2|					return JSMN_ERROR_INVAL;
  162|  25.0k|			}
  163|  25.0k|		}
  164|   186k|	}
  165|    127|	parser->pos = start;
  166|    127|	return JSMN_ERROR_PART;
  167|   112k|}
jsmn.c:jsmn_fill_token:
   59|   142k|                            size_t start, size_t end) {
   60|   142k|	token->type = type;
   61|   142k|	token->start = start;
   62|   142k|	token->end = end;
   63|   142k|	token->size = 0;
   64|   142k|}
jsmn.c:jsmn_parse_primitive:
   70|  34.2k|		jsmntok_t *tokens, unsigned int num_tokens) {
   71|  34.2k|	jsmntok_t *token;
   72|  34.2k|	size_t start;
   73|       |
   74|  34.2k|	start = parser->pos;
   75|       |
   76|   107k|	for (; (parser->end > 0 && parser->pos < parser->end) && js[parser->pos] != '\0'; parser->pos++) {
  ------------------
  |  Branch (76:10): [True: 107k, False: 0]
  |  Branch (76:29): [True: 107k, False: 662]
  |  Branch (76:59): [True: 107k, False: 2]
  ------------------
   77|   107k|		switch (js[parser->pos]) {
   78|      0|#ifndef JSMN_STRICT
   79|       |			/* In strict mode primitive must be followed by "," or "}" or "]" */
   80|  6.12k|			case ':':
  ------------------
  |  Branch (80:4): [True: 6.12k, False: 101k]
  ------------------
   81|  6.12k|#endif
   82|  23.0k|			case '\t' : case '\r' : case '\n' : case ' ' :
  ------------------
  |  Branch (82:4): [True: 1.01k, False: 106k]
  |  Branch (82:16): [True: 1.62k, False: 105k]
  |  Branch (82:28): [True: 13.7k, False: 93.4k]
  |  Branch (82:40): [True: 578, False: 106k]
  ------------------
   83|  33.5k|			case ','  : case ']'  : case '}' :
  ------------------
  |  Branch (83:4): [True: 3.68k, False: 103k]
  |  Branch (83:16): [True: 5.74k, False: 101k]
  |  Branch (83:28): [True: 1.04k, False: 106k]
  ------------------
   84|  33.5k|				goto found;
   85|  73.6k|			default:
  ------------------
  |  Branch (85:4): [True: 73.6k, False: 33.5k]
  ------------------
   86|  73.6k|				break;
   87|   107k|		}
   88|  73.6k|		if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
  ------------------
  |  Branch (88:7): [True: 16, False: 73.5k]
  |  Branch (88:31): [True: 1, False: 73.5k]
  ------------------
   89|     17|			parser->pos = start;
   90|     17|			return JSMN_ERROR_INVAL;
   91|     17|		}
   92|  73.6k|	}
   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|  34.2k|found:
  100|  34.2k|	token = jsmn_alloc_token(parser, tokens, num_tokens);
  101|  34.2k|	if (token == NULL) {
  ------------------
  |  Branch (101:6): [True: 1.14k, False: 33.0k]
  ------------------
  102|  1.14k|		parser->pos = start;
  103|  1.14k|		return JSMN_ERROR_NOMEM;
  104|  1.14k|	}
  105|  33.0k|	jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
  106|       |#ifdef JSMN_PARENT_LINKS
  107|       |	token->parent = parser->toksuper;
  108|       |#endif
  109|  33.0k|	parser->pos--;
  110|  33.0k|	return JSMN_SUCCESS;
  111|  34.2k|}

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|   195k|{
  349|       |    return (plist_t) node_create(NULL, data);
  350|   195k|}
plist_get_data:
  353|  23.2M|{
  354|  23.2M|    if (!node)
  ------------------
  |  Branch (354:9): [True: 0, False: 23.2M]
  ------------------
  355|      0|        return NULL;
  356|  23.2M|    return (plist_data_t)((node_t)node)->data;
  357|  23.2M|}
plist_new_plist_data:
  360|   195k|{
  361|   195k|    return (plist_data_t) calloc(1, sizeof(struct plist_data_s));
  362|   195k|}
plist_free_data:
  421|   195k|{
  422|   195k|    if (!data) return;
  ------------------
  |  Branch (422:9): [True: 0, False: 195k]
  ------------------
  423|   195k|    _plist_free_data(data);
  424|   195k|    free(data);
  425|   195k|}
plist_new_dict:
  528|  11.9k|{
  529|  11.9k|    plist_data_t data = plist_new_plist_data();
  530|  11.9k|    if (!data) {
  ------------------
  |  Branch (530:9): [True: 0, False: 11.9k]
  ------------------
  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|  11.9k|    data->type = PLIST_DICT;
  535|  11.9k|    return plist_new_node(data);
  536|  11.9k|}
plist_new_array:
  539|  57.9k|{
  540|  57.9k|    plist_data_t data = plist_new_plist_data();
  541|  57.9k|    if (!data) {
  ------------------
  |  Branch (541:9): [True: 0, False: 57.9k]
  ------------------
  542|      0|        PLIST_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  543|      0|        return NULL;
  544|      0|    }
  545|  57.9k|    data->type = PLIST_ARRAY;
  546|  57.9k|    return plist_new_node(data);
  547|  57.9k|}
plist_new_bool:
  589|  8.50k|{
  590|  8.50k|    plist_data_t data = plist_new_plist_data();
  591|  8.50k|    if (!data) {
  ------------------
  |  Branch (591:9): [True: 0, False: 8.50k]
  ------------------
  592|      0|        PLIST_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  593|      0|        return NULL;
  594|      0|    }
  595|  8.50k|    data->type = PLIST_BOOLEAN;
  596|  8.50k|    data->boolval = val;
  597|  8.50k|    data->length = sizeof(uint8_t);
  598|  8.50k|    return plist_new_node(data);
  599|  8.50k|}
plist_new_int:
  615|  3.93k|{
  616|  3.93k|    plist_data_t data = plist_new_plist_data();
  617|  3.93k|    if (!data) {
  ------------------
  |  Branch (617:9): [True: 0, False: 3.93k]
  ------------------
  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|  3.93k|    data->type = PLIST_INT;
  622|  3.93k|    data->intval = val;
  623|  3.93k|    data->length = sizeof(uint64_t);
  624|  3.93k|    return plist_new_node(data);
  625|  3.93k|}
plist_new_real:
  641|  2.27k|{
  642|  2.27k|    plist_data_t data = plist_new_plist_data();
  643|  2.27k|    if (!data) {
  ------------------
  |  Branch (643:9): [True: 0, False: 2.27k]
  ------------------
  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.27k|    data->type = PLIST_REAL;
  648|  2.27k|    data->realval = val;
  649|  2.27k|    data->length = sizeof(double);
  650|  2.27k|    return plist_new_node(data);
  651|  2.27k|}
plist_free:
  713|  6.03k|{
  714|  6.03k|    if (plist)
  ------------------
  |  Branch (714:9): [True: 5.21k, False: 821]
  ------------------
  715|  5.21k|    {
  716|  5.21k|        plist_free_node((node_t)plist);
  717|  5.21k|    }
  718|  6.03k|}
plist_array_append_item:
 1090|  61.0k|{
 1091|  61.0k|    if (!PLIST_IS_ARRAY(node) || !item) {
  ------------------
  |  | 1252|  61.0k|    #define PLIST_IS_ARRAY(__plist)   _PLIST_IS_TYPE(__plist, ARRAY)
  |  |  ------------------
  |  |  |  | 1240|   122k|    #define _PLIST_IS_TYPE(__plist, __plist_type) (__plist && (plist_get_node_type(__plist) == PLIST_##__plist_type))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1240:52): [True: 61.0k, False: 0]
  |  |  |  |  |  Branch (1240:63): [True: 61.0k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1091:34): [True: 0, False: 61.0k]
  ------------------
 1092|      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]
  |  |  ------------------
  ------------------
 1093|      0|        return PLIST_ERR_INVALID_ARG;
 1094|      0|    }
 1095|  61.0k|    node_t it = (node_t)item;
 1096|  61.0k|    if (it->parent != NULL) {
  ------------------
  |  Branch (1096:9): [True: 0, False: 61.0k]
  ------------------
 1097|      0|        assert(it->parent == NULL && "item already has a parent; use plist_copy() or detach first");
  ------------------
  |  Branch (1097:9): [True: 0, False: 0]
  |  Branch (1097:9): [True: 0, False: 0]
  |  Branch (1097:9): [True: 0, False: 0]
  |  Branch (1097:9): [True: 0, False: 0]
  ------------------
 1098|      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]
  |  |  ------------------
  ------------------
 1099|      0|        return PLIST_ERR_INVALID_ARG;
 1100|      0|    }
 1101|       |
 1102|  61.0k|    int r = node_attach((node_t)node, (node_t)item);
 1103|  61.0k|    if (r != NODE_ERR_SUCCESS) {
  ------------------
  |  |   36|  61.0k|#define NODE_ERR_SUCCESS       0
  ------------------
  |  Branch (1103:9): [True: 2, False: 61.0k]
  ------------------
 1104|      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]
  |  |  ------------------
  ------------------
 1105|      2|        return PLIST_ERR_UNKNOWN;
 1106|      2|    }
 1107|  61.0k|    _plist_array_post_insert(node, item, -1);
 1108|       |
 1109|  61.0k|    return PLIST_ERR_SUCCESS;
 1110|  61.0k|}
plist_dict_get_item:
 1291|  66.9k|{
 1292|  66.9k|    plist_t ret = NULL;
 1293|  66.9k|    if (!PLIST_IS_DICT(node) || !key) {
  ------------------
  |  | 1254|  66.9k|    #define PLIST_IS_DICT(__plist)    _PLIST_IS_TYPE(__plist, DICT)
  |  |  ------------------
  |  |  |  | 1240|   133k|    #define _PLIST_IS_TYPE(__plist, __plist_type) (__plist && (plist_get_node_type(__plist) == PLIST_##__plist_type))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1240:52): [True: 66.9k, False: 0]
  |  |  |  |  |  Branch (1240:63): [True: 66.9k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1293:33): [True: 0, False: 66.9k]
  ------------------
 1294|      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]
  |  |  ------------------
  ------------------
 1295|      0|        return NULL;
 1296|      0|    }
 1297|  66.9k|    plist_data_t data = plist_get_data(node);
 1298|  66.9k|    if (!data) {
  ------------------
  |  Branch (1298:9): [True: 0, False: 66.9k]
  ------------------
 1299|      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]
  |  |  ------------------
  ------------------
 1300|      0|        return NULL;
 1301|      0|    }
 1302|  66.9k|    size_t keylen = strlen(key);
 1303|  66.9k|    hashtable_t *ht = (hashtable_t*)data->hashtable;
 1304|  66.9k|    if (ht) {
  ------------------
  |  Branch (1304:9): [True: 1.17k, False: 65.7k]
  ------------------
 1305|  1.17k|        struct plist_data_s sdata = { 0 };
 1306|  1.17k|        sdata.strval = (char*)key;
 1307|  1.17k|        sdata.length = keylen;
 1308|  1.17k|        return (plist_t)hash_table_lookup(ht, &sdata);
 1309|  65.7k|    } else {
 1310|  65.7k|        plist_t k = NULL;
 1311|  7.64M|        for (k = (plist_t)node_first_child((node_t)node); k; ) {
  ------------------
  |  Branch (1311:59): [True: 7.58M, False: 62.3k]
  ------------------
 1312|  7.58M|            plist_t v = (plist_t)node_next_sibling(k);
 1313|  7.58M|            if (!v) break;
  ------------------
  |  Branch (1313:17): [True: 0, False: 7.58M]
  ------------------
 1314|  7.58M|            data = plist_get_data(k);
 1315|  7.58M|            assert(PLIST_IS_KEY(k));
  ------------------
  |  Branch (1315:13): [True: 0, False: 7.58M]
  |  Branch (1315:13): [True: 0, False: 0]
  |  Branch (1315:13): [True: 7.58M, False: 0]
  |  Branch (1315:13): [True: 7.58M, False: 0]
  ------------------
 1316|  7.58M|            if (!PLIST_IS_KEY(k) || !data || !data->strval) {
  ------------------
  |  | 1260|  7.58M|    #define PLIST_IS_KEY(__plist)     _PLIST_IS_TYPE(__plist, KEY)
  |  |  ------------------
  |  |  |  | 1240|  15.1M|    #define _PLIST_IS_TYPE(__plist, __plist_type) (__plist && (plist_get_node_type(__plist) == PLIST_##__plist_type))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1240:52): [True: 7.58M, False: 0]
  |  |  |  |  |  Branch (1240:63): [True: 7.58M, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1316:37): [True: 0, False: 7.58M]
  |  Branch (1316:46): [True: 0, False: 7.58M]
  ------------------
 1317|      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]
  |  |  ------------------
  ------------------
 1318|      0|                break;
 1319|      0|            }
 1320|  7.58M|            if (data->length == keylen && !memcmp(key, data->strval, keylen+1)) {
  ------------------
  |  Branch (1320:17): [True: 4.07M, False: 3.51M]
  |  Branch (1320:43): [True: 3.47k, False: 4.06M]
  ------------------
 1321|  3.47k|                ret = v;
 1322|  3.47k|                break;
 1323|  3.47k|            }
 1324|  7.58M|            k = node_next_sibling(v);
 1325|  7.58M|        }
 1326|  65.7k|    }
 1327|  65.7k|    return ret;
 1328|  66.9k|}
plist_dict_set_item:
 1331|  66.9k|{
 1332|  66.9k|    if (!PLIST_IS_DICT(node) || !key || !item) {
  ------------------
  |  | 1254|  66.9k|    #define PLIST_IS_DICT(__plist)    _PLIST_IS_TYPE(__plist, DICT)
  |  |  ------------------
  |  |  |  | 1240|   133k|    #define _PLIST_IS_TYPE(__plist, __plist_type) (__plist && (plist_get_node_type(__plist) == PLIST_##__plist_type))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1240:52): [True: 66.9k, False: 0]
  |  |  |  |  |  Branch (1240:63): [True: 66.9k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1332:33): [True: 0, False: 66.9k]
  |  Branch (1332:41): [True: 0, False: 66.9k]
  ------------------
 1333|      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]
  |  |  ------------------
  ------------------
 1334|      0|        return PLIST_ERR_INVALID_ARG;
 1335|      0|    }
 1336|  66.9k|    node_t it = (node_t)item;
 1337|  66.9k|    if (it->parent != NULL) {
  ------------------
  |  Branch (1337:9): [True: 0, False: 66.9k]
  ------------------
 1338|      0|        assert(it->parent == NULL && "item already has a parent");
  ------------------
  |  Branch (1338:9): [True: 0, False: 0]
  |  Branch (1338:9): [True: 0, False: 0]
  |  Branch (1338:9): [True: 0, False: 0]
  |  Branch (1338:9): [True: 0, False: 0]
  ------------------
 1339|      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]
  |  |  ------------------
  ------------------
 1340|      0|        return PLIST_ERR_INVALID_ARG;
 1341|      0|    }
 1342|       |
 1343|  66.9k|    hashtable_t *ht = (hashtable_t*)((plist_data_t)((node_t)node)->data)->hashtable;
 1344|       |
 1345|  66.9k|    plist_t old_item = plist_dict_get_item(node, key);
 1346|  66.9k|    plist_t key_node = NULL;
 1347|       |
 1348|  66.9k|    if (old_item) {
  ------------------
  |  Branch (1348:9): [True: 4.18k, False: 62.7k]
  ------------------
 1349|       |        // --- REPLACE EXISTING VALUE ---
 1350|  4.18k|        node_t old_val = (node_t)old_item;
 1351|  4.18k|        node_t old_key = node_prev_sibling(old_val);
 1352|  4.18k|        if (!old_key) {
  ------------------
  |  Branch (1352:13): [True: 0, False: 4.18k]
  ------------------
 1353|      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]
  |  |  ------------------
  ------------------
 1354|      0|            return PLIST_ERR_UNKNOWN;
 1355|      0|        }
 1356|  4.18k|        if (!PLIST_IS_KEY((plist_t)old_key)) {
  ------------------
  |  | 1260|  4.18k|    #define PLIST_IS_KEY(__plist)     _PLIST_IS_TYPE(__plist, KEY)
  |  |  ------------------
  |  |  |  | 1240|  4.18k|    #define _PLIST_IS_TYPE(__plist, __plist_type) (__plist && (plist_get_node_type(__plist) == PLIST_##__plist_type))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1240:52): [True: 4.18k, False: 0]
  |  |  |  |  |  Branch (1240:63): [True: 4.18k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1357|      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]
  |  |  ------------------
  ------------------
 1358|      0|            return PLIST_ERR_UNKNOWN;
 1359|      0|        }
 1360|       |
 1361|       |        // detach old value (do NOT free yet)
 1362|  4.18k|        int idx = node_detach((node_t)node, old_val);
 1363|  4.18k|        if (idx < 0) {
  ------------------
  |  Branch (1363:13): [True: 0, False: 4.18k]
  ------------------
 1364|      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]
  |  |  ------------------
  ------------------
 1365|      0|            return PLIST_ERR_UNKNOWN;
 1366|      0|        }
 1367|       |
 1368|       |        // insert new value at same position
 1369|  4.18k|        int r = node_insert((node_t)node, (unsigned)idx, (node_t)item);
 1370|  4.18k|        if (r != NODE_ERR_SUCCESS) {
  ------------------
  |  |   36|  4.18k|#define NODE_ERR_SUCCESS       0
  ------------------
  |  Branch (1370:13): [True: 3, False: 4.18k]
  ------------------
 1371|       |            // rollback: reinsert old value
 1372|      3|            int rb = node_insert((node_t)node, (unsigned)idx, old_val);
 1373|      3|            if (rb == NODE_ERR_SUCCESS && ht) {
  ------------------
  |  |   36|      6|#define NODE_ERR_SUCCESS       0
  ------------------
  |  Branch (1373:17): [True: 3, False: 0]
  |  Branch (1373:43): [True: 1, False: 2]
  ------------------
 1374|      1|                hash_table_insert(ht, ((node_t)old_key)->data, old_item);
 1375|      1|            }
 1376|      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]
  |  |  ------------------
  ------------------
 1377|      3|            return PLIST_ERR_UNKNOWN;
 1378|      3|        }
 1379|  4.18k|        key_node = old_key;
 1380|       |
 1381|       |        // update hash table
 1382|  4.18k|        if (ht) {
  ------------------
  |  Branch (1382:13): [True: 711, False: 3.47k]
  ------------------
 1383|    711|            hash_table_insert(ht, (plist_data_t)((node_t)key_node)->data, item);
 1384|    711|        }
 1385|       |
 1386|       |        // now it’s safe to free old value
 1387|  4.18k|        plist_free_node(old_val);
 1388|  62.7k|    } else {
 1389|       |        // --- INSERT NEW KEY/VALUE PAIR ---
 1390|  62.7k|        key_node = plist_new_key(key);
 1391|  62.7k|        if (!key_node) return PLIST_ERR_NO_MEM;
  ------------------
  |  Branch (1391:13): [True: 0, False: 62.7k]
  ------------------
 1392|       |
 1393|  62.7k|        int r = node_attach((node_t)node, (node_t)key_node);
 1394|  62.7k|        if (r != NODE_ERR_SUCCESS) {
  ------------------
  |  |   36|  62.7k|#define NODE_ERR_SUCCESS       0
  ------------------
  |  Branch (1394:13): [True: 0, False: 62.7k]
  ------------------
 1395|      0|            plist_free_node((node_t)key_node);
 1396|      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]
  |  |  ------------------
  ------------------
 1397|      0|            return PLIST_ERR_UNKNOWN;
 1398|      0|        }
 1399|  62.7k|        r = node_attach((node_t)node, (node_t)item);
 1400|  62.7k|        if (r != NODE_ERR_SUCCESS) {
  ------------------
  |  |   36|  62.7k|#define NODE_ERR_SUCCESS       0
  ------------------
  |  Branch (1400:13): [True: 2, False: 62.7k]
  ------------------
 1401|       |            // rollback key insertion
 1402|      2|            node_detach((node_t)node, (node_t)key_node);
 1403|      2|            plist_free_node((node_t)key_node);
 1404|      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]
  |  |  ------------------
  ------------------
 1405|      2|            return PLIST_ERR_UNKNOWN;
 1406|      2|        }
 1407|       |
 1408|  62.7k|        if (ht) {
  ------------------
  |  Branch (1408:13): [True: 466, False: 62.3k]
  ------------------
 1409|       |            // store pointer to item in hash table
 1410|    466|            hash_table_insert(ht, (plist_data_t)((node_t)key_node)->data, item);
 1411|  62.3k|        } else if (((node_t)node)->count > 500) {
  ------------------
  |  Branch (1411:20): [True: 235, False: 62.0k]
  ------------------
 1412|       |            // make new hash table
 1413|    235|            ht = hash_table_new(dict_key_hash, dict_key_compare, NULL);
 1414|       |            // calculate the hashes for all entries we have so far
 1415|    235|            plist_t current = NULL;
 1416|    235|            for (current = (plist_t)node_first_child((node_t)node);
 1417|  59.2k|                 ht && current;
  ------------------
  |  Branch (1417:18): [True: 59.2k, False: 0]
  |  Branch (1417:24): [True: 58.9k, False: 235]
  ------------------
 1418|  58.9k|                 current = (plist_t)node_next_sibling(node_next_sibling((node_t)current)))
 1419|  58.9k|            {
 1420|  58.9k|                hash_table_insert(ht, ((node_t)current)->data, node_next_sibling((node_t)current));
 1421|  58.9k|            }
 1422|    235|            ((plist_data_t)((node_t)node)->data)->hashtable = ht;
 1423|    235|        }
 1424|  62.7k|    }
 1425|  66.9k|    return PLIST_ERR_SUCCESS;
 1426|  66.9k|}
plist_get_node_type:
 1756|  15.3M|{
 1757|  15.3M|    if (node)
  ------------------
  |  Branch (1757:9): [True: 15.3M, False: 0]
  ------------------
 1758|  15.3M|    {
 1759|  15.3M|        plist_data_t data = plist_get_data(node);
 1760|  15.3M|        if (data)
  ------------------
  |  Branch (1760:13): [True: 15.3M, False: 0]
  ------------------
 1761|  15.3M|            return data->type;
 1762|  15.3M|    }
 1763|      0|    return PLIST_NONE;
 1764|  15.3M|}
plist.c:_plist_free_data:
  390|   195k|{
  391|   195k|    if (!data) return;
  ------------------
  |  Branch (391:9): [True: 0, False: 195k]
  ------------------
  392|   195k|    switch (data->type) {
  393|  62.7k|        case PLIST_KEY:
  ------------------
  |  Branch (393:9): [True: 62.7k, False: 133k]
  ------------------
  394|  97.2k|        case PLIST_STRING:
  ------------------
  |  Branch (394:9): [True: 34.4k, False: 161k]
  ------------------
  395|  97.2k|            free(data->strval);
  396|  97.2k|            data->strval = NULL;
  397|  97.2k|            break;
  398|      0|        case PLIST_DATA:
  ------------------
  |  Branch (398:9): [True: 0, False: 195k]
  ------------------
  399|      0|            free(data->buff);
  400|      0|            data->buff = NULL;
  401|      0|            break;
  402|  57.9k|        case PLIST_ARRAY:
  ------------------
  |  Branch (402:9): [True: 57.9k, False: 137k]
  ------------------
  403|  57.9k|            ptr_array_free((ptrarray_t*)data->hashtable);
  404|  57.9k|            data->hashtable = NULL;
  405|  57.9k|            break;
  406|  11.9k|        case PLIST_DICT: {
  ------------------
  |  Branch (406:9): [True: 11.9k, False: 183k]
  ------------------
  407|  11.9k|            hashtable_t *ht = (hashtable_t*)data->hashtable;
  408|       |            // PLIST_DICT hashtables must not own/free values; values are freed via node tree.
  409|  11.9k|            assert(!ht || ht->free_func == NULL);
  ------------------
  |  Branch (409:13): [True: 11.9k, False: 0]
  |  Branch (409:13): [True: 0, False: 0]
  |  Branch (409:13): [True: 11.7k, False: 235]
  |  Branch (409:13): [True: 235, False: 0]
  ------------------
  410|  11.9k|            if (ht) ht->free_func = NULL;
  ------------------
  |  Branch (410:17): [True: 235, False: 11.7k]
  ------------------
  411|  11.9k|            hash_table_destroy(ht);
  412|  11.9k|            data->hashtable = NULL;
  413|  11.9k|            break;
  414|  11.9k|        }
  415|  28.7k|        default:
  ------------------
  |  Branch (415:9): [True: 28.7k, False: 167k]
  ------------------
  416|  28.7k|            break;
  417|   195k|    }
  418|   195k|}
plist.c:plist_free_node:
  500|  9.40k|{
  501|  9.40k|    if (!root) return NODE_ERR_INVALID_ARG;
  ------------------
  |  |   37|      0|#define NODE_ERR_INVALID_ARG  -1
  ------------------
  |  Branch (501:9): [True: 0, False: 9.40k]
  ------------------
  502|       |
  503|  9.40k|    int root_index = -1;
  504|       |
  505|  9.40k|    if (root->parent) {
  ------------------
  |  Branch (505:9): [True: 0, False: 9.40k]
  ------------------
  506|      0|        root_index = node_detach(root->parent, root);
  507|      0|        if (root_index < 0) {
  ------------------
  |  Branch (507:13): [True: 0, False: 0]
  ------------------
  508|      0|            return root_index;
  509|      0|        }
  510|      0|    }
  511|       |
  512|  9.40k|    int r = plist_free_children(root);
  513|  9.40k|    if (r < 0) {
  ------------------
  |  Branch (513:9): [True: 0, False: 9.40k]
  ------------------
  514|       |        // root is already detached; caller should treat as error.
  515|      0|        return r;
  516|      0|    }
  517|       |
  518|  9.40k|    plist_data_t data = plist_get_data(root);
  519|  9.40k|    plist_free_data(data);
  520|  9.40k|    root->data = NULL;
  521|       |
  522|  9.40k|    node_destroy(root);
  523|       |
  524|  9.40k|    return root_index;
  525|  9.40k|}
plist.c:plist_free_children:
  428|  9.40k|{
  429|  9.40k|    if (!root) return NODE_ERR_INVALID_ARG;
  ------------------
  |  |   37|      0|#define NODE_ERR_INVALID_ARG  -1
  ------------------
  |  Branch (429:9): [True: 0, False: 9.40k]
  ------------------
  430|       |
  431|  9.40k|    if (!node_first_child(root)) {
  ------------------
  |  Branch (431:9): [True: 8.08k, False: 1.31k]
  ------------------
  432|  8.08k|        return NODE_ERR_SUCCESS;
  ------------------
  |  |   36|  8.08k|#define NODE_ERR_SUCCESS       0
  ------------------
  433|  8.08k|    }
  434|       |
  435|  1.31k|    size_t cap = 64, sp = 0;
  436|  1.31k|    node_t *stack = (node_t*)malloc(cap * sizeof(*stack));
  437|  1.31k|    if (!stack) return NODE_ERR_NO_MEM;
  ------------------
  |  |   38|      0|#define NODE_ERR_NO_MEM       -2
  ------------------
  |  Branch (437:9): [True: 0, False: 1.31k]
  ------------------
  438|       |
  439|       |    // Push *direct* children onto the stack, detached from root.
  440|   145k|    for (;;) {
  441|   145k|        node_t ch = node_first_child(root);
  442|   145k|        if (!ch) break;
  ------------------
  |  Branch (442:13): [True: 1.31k, False: 143k]
  ------------------
  443|       |
  444|   143k|        int di = node_detach(root, ch);
  445|   143k|        if (di < 0) {
  ------------------
  |  Branch (445:13): [True: 0, False: 143k]
  ------------------
  446|      0|            free(stack);
  447|      0|            return di;
  448|      0|        }
  449|       |
  450|   143k|        if (sp == cap) {
  ------------------
  |  Branch (450:13): [True: 1.93k, False: 141k]
  ------------------
  451|  1.93k|            cap += 64;
  452|  1.93k|            node_t *tmp = (node_t*)realloc(stack, cap * sizeof(*stack));
  453|  1.93k|            if (!tmp) {
  ------------------
  |  Branch (453:17): [True: 0, False: 1.93k]
  ------------------
  454|      0|                free(stack);
  455|      0|                return NODE_ERR_NO_MEM;
  ------------------
  |  |   38|      0|#define NODE_ERR_NO_MEM       -2
  ------------------
  456|      0|            }
  457|  1.93k|            stack = tmp;
  458|  1.93k|        }
  459|   143k|        stack[sp++] = ch;
  460|   143k|    }
  461|       |
  462|       |    // Now free the detached subtree nodes (and their descendants).
  463|   230k|    while (sp) {
  ------------------
  |  Branch (463:12): [True: 229k, False: 1.31k]
  ------------------
  464|   229k|        node_t node = stack[sp - 1];
  465|   229k|        node_t ch = node_first_child(node);
  466|   229k|        if (ch) {
  ------------------
  |  Branch (466:13): [True: 42.7k, False: 186k]
  ------------------
  467|  42.7k|            int di = node_detach(node, ch);
  468|  42.7k|            if (di < 0) {
  ------------------
  |  Branch (468:17): [True: 0, False: 42.7k]
  ------------------
  469|      0|                free(stack);
  470|      0|                return di;
  471|      0|            }
  472|       |
  473|  42.7k|            if (sp == cap) {
  ------------------
  |  Branch (473:17): [True: 349, False: 42.4k]
  ------------------
  474|    349|                cap += 64;
  475|    349|                node_t *tmp = (node_t*)realloc(stack, cap * sizeof(*stack));
  476|    349|                if (!tmp) {
  ------------------
  |  Branch (476:21): [True: 0, False: 349]
  ------------------
  477|      0|                    free(stack);
  478|      0|                    return NODE_ERR_NO_MEM;
  ------------------
  |  |   38|      0|#define NODE_ERR_NO_MEM       -2
  ------------------
  479|      0|                }
  480|    349|                stack = tmp;
  481|    349|            }
  482|  42.7k|            stack[sp++] = ch;
  483|  42.7k|            continue;
  484|  42.7k|        }
  485|       |
  486|   186k|        plist_data_t data = plist_get_data(node);
  487|   186k|        plist_free_data(data);
  488|   186k|        node->data = NULL;
  489|       |
  490|   186k|        node_destroy(node);
  491|       |
  492|   186k|        sp--;
  493|   186k|    }
  494|       |
  495|  1.31k|    free(stack);
  496|  1.31k|    return NODE_ERR_SUCCESS;
  ------------------
  |  |   36|  1.31k|#define NODE_ERR_SUCCESS       0
  ------------------
  497|  1.31k|}
plist.c:_plist_array_post_insert:
  989|  61.0k|{
  990|  61.0k|    ptrarray_t *pa = (ptrarray_t*)((plist_data_t)((node_t)node)->data)->hashtable;
  991|  61.0k|    if (pa) {
  ------------------
  |  Branch (991:9): [True: 12.0k, False: 48.9k]
  ------------------
  992|       |        /* store pointer to item in array */
  993|  12.0k|        if (ptr_array_insert(pa, item, n) < 0) {
  ------------------
  |  Branch (993:13): [True: 0, False: 12.0k]
  ------------------
  994|       |            /* lookup array would be out of sync, drop it */
  995|      0|            ptr_array_free(pa);
  996|      0|            ((plist_data_t)((node_t)node)->data)->hashtable = NULL;
  997|      0|        }
  998|  12.0k|        return;
  999|  12.0k|    }
 1000|       |
 1001|  48.9k|    if (((node_t)node)->count > 100) {
  ------------------
  |  Branch (1001:9): [True: 112, False: 48.8k]
  ------------------
 1002|       |       /* make new lookup array */
 1003|    112|       pa = ptr_array_new(128);
 1004|    112|       plist_t current = NULL;
 1005|    112|       for (current = (plist_t)node_first_child((node_t)node);
 1006|  11.4k|            pa && current;
  ------------------
  |  Branch (1006:13): [True: 11.4k, False: 0]
  |  Branch (1006:19): [True: 11.3k, False: 112]
  ------------------
 1007|  11.3k|            current = (plist_t)node_next_sibling((node_t)current))
 1008|  11.3k|       {
 1009|  11.3k|           if (ptr_array_add(pa, current) < 0) {
  ------------------
  |  Branch (1009:16): [True: 0, False: 11.3k]
  ------------------
 1010|      0|               ptr_array_free(pa);
 1011|       |               pa = NULL;
 1012|      0|           }
 1013|  11.3k|       }
 1014|    112|       ((plist_data_t)((node_t)node)->data)->hashtable = pa;
 1015|    112|    }
 1016|  48.9k|}
plist.c:plist_new_key:
  551|  62.7k|{
  552|  62.7k|    plist_data_t data = plist_new_plist_data();
  553|  62.7k|    if (!data) {
  ------------------
  |  Branch (553:9): [True: 0, False: 62.7k]
  ------------------
  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.7k|    data->type = PLIST_KEY;
  558|  62.7k|    data->strval = strdup(val);
  559|  62.7k|    if (!data->strval) {
  ------------------
  |  Branch (559:9): [True: 0, False: 62.7k]
  ------------------
  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.7k|    } else {
  564|  62.7k|        data->length = strlen(val);
  565|  62.7k|    }
  566|  62.7k|    return plist_new_node(data);
  567|  62.7k|}
plist.c:dict_key_hash:
  365|  61.3k|{
  366|  61.3k|    plist_data_t keydata = (plist_data_t)data;
  367|  61.3k|    unsigned int hash = 5381;
  368|  61.3k|    size_t i;
  369|  61.3k|    char *str = keydata->strval;
  370|   158k|    for (i = 0; i < keydata->length; str++, i++) {
  ------------------
  |  Branch (370:17): [True: 97.3k, False: 61.3k]
  ------------------
  371|  97.3k|        hash = ((hash << 5) + hash) + *str;
  372|  97.3k|    }
  373|  61.3k|    return hash;
  374|  61.3k|}
plist.c:dict_key_compare:
  377|  3.87k|{
  378|  3.87k|    plist_data_t data_a = (plist_data_t)a;
  379|  3.87k|    plist_data_t data_b = (plist_data_t)b;
  380|  3.87k|    if (data_a->strval == NULL || data_b->strval == NULL) {
  ------------------
  |  Branch (380:9): [True: 0, False: 3.87k]
  |  Branch (380:35): [True: 0, False: 3.87k]
  ------------------
  381|      0|        return FALSE;
  ------------------
  |  |   32|      0|#define FALSE 0
  ------------------
  382|      0|    }
  383|  3.87k|    if (data_a->length != data_b->length) {
  ------------------
  |  Branch (383:9): [True: 1.79k, False: 2.07k]
  ------------------
  384|  1.79k|        return FALSE;
  ------------------
  |  |   32|  1.79k|#define FALSE 0
  ------------------
  385|  1.79k|    }
  386|  2.07k|    return (strcmp(data_a->strval, data_b->strval) == 0) ? TRUE : FALSE;
  ------------------
  |  |   28|  1.42k|#define TRUE 1
  ------------------
                  return (strcmp(data_a->strval, data_b->strval) == 0) ? TRUE : FALSE;
  ------------------
  |  |   32|    653|#define FALSE 0
  ------------------
  |  Branch (386:12): [True: 1.42k, False: 653]
  ------------------
  387|  3.87k|}

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

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|}

