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

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

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

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

plist_json_init:
   57|      2|{
   58|       |    /* init JSON stuff */
   59|      2|#ifdef DEBUG
   60|      2|    char *env_debug = getenv("PLIST_JSON_DEBUG");
   61|      2|    if (env_debug && !strcmp(env_debug, "1")) {
  ------------------
  |  Branch (61:9): [True: 0, False: 2]
  |  Branch (61:22): [True: 0, False: 0]
  ------------------
   62|      0|        plist_json_debug = 1;
   63|      0|    }
   64|      2|#endif
   65|      2|}
plist_from_json:
  955|  2.31k|{
  956|  2.31k|    if (!plist) {
  ------------------
  |  Branch (956:9): [True: 0, False: 2.31k]
  ------------------
  957|      0|        return PLIST_ERR_INVALID_ARG;
  958|      0|    }
  959|  2.31k|    *plist = NULL;
  960|  2.31k|    if (!json || (length == 0)) {
  ------------------
  |  Branch (960:9): [True: 0, False: 2.31k]
  |  Branch (960:18): [True: 0, False: 2.31k]
  ------------------
  961|      0|        return PLIST_ERR_INVALID_ARG;
  962|      0|    }
  963|       |
  964|  2.31k|    jsmn_parser parser;
  965|  2.31k|    jsmn_init(&parser);
  966|  2.31k|    unsigned int maxtoks = 256;
  967|  2.31k|    unsigned int curtoks = 0;
  968|  2.31k|    int r = 0;
  969|  2.31k|    jsmntok_t *tokens = NULL;
  970|       |
  971|  12.3k|    do {
  972|  12.3k|        jsmntok_t* newtokens = (jsmntok_t*)realloc(tokens, sizeof(jsmntok_t)*maxtoks);
  973|  12.3k|        if (!newtokens) {
  ------------------
  |  Branch (973:13): [True: 0, False: 12.3k]
  ------------------
  974|      0|            free(tokens);
  975|      0|            PLIST_JSON_ERR("%s: Out of memory\n", __func__);
  ------------------
  |  |   49|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  976|      0|            return PLIST_ERR_NO_MEM;
  977|      0|        }
  978|  12.3k|        memset((unsigned char*)newtokens + sizeof(jsmntok_t)*curtoks, '\0', sizeof(jsmntok_t)*(maxtoks-curtoks));
  979|  12.3k|        tokens = newtokens;
  980|  12.3k|        curtoks = maxtoks;
  981|       |
  982|  12.3k|        r = jsmn_parse(&parser, json, length, tokens, maxtoks);
  983|  12.3k|        if (r == JSMN_ERROR_NOMEM) {
  ------------------
  |  Branch (983:13): [True: 10.0k, False: 2.31k]
  ------------------
  984|  10.0k|            if (maxtoks > (unsigned int)INT_MAX - 16) {
  ------------------
  |  Branch (984:17): [True: 0, False: 10.0k]
  ------------------
  985|      0|                free(tokens);
  986|      0|                return PLIST_ERR_NO_MEM;
  987|      0|            }
  988|  10.0k|            maxtoks+=16;
  989|  10.0k|            continue;
  990|  10.0k|        } else if (r < 0) {
  ------------------
  |  Branch (990:20): [True: 375, False: 1.94k]
  ------------------
  991|    375|            break;
  992|    375|        }
  993|  12.3k|    } while (r == JSMN_ERROR_NOMEM);
  ------------------
  |  Branch (993:14): [True: 10.0k, False: 1.94k]
  ------------------
  994|       |
  995|  2.31k|    switch(r) {
  996|      0|        case JSMN_ERROR_NOMEM:
  ------------------
  |  Branch (996:9): [True: 0, False: 2.31k]
  ------------------
  997|      0|            PLIST_JSON_ERR("%s: Out of memory...\n", __func__);
  ------------------
  |  |   49|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  998|      0|            free(tokens);
  999|      0|            return PLIST_ERR_NO_MEM;
 1000|     70|        case JSMN_ERROR_INVAL:
  ------------------
  |  Branch (1000:9): [True: 70, False: 2.24k]
  ------------------
 1001|     70|            PLIST_JSON_ERR("%s: Invalid character inside JSON string\n", __func__);
  ------------------
  |  |   49|     70|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 70]
  |  |  ------------------
  ------------------
 1002|     70|            free(tokens);
 1003|     70|            return PLIST_ERR_PARSE;
 1004|    305|        case JSMN_ERROR_PART:
  ------------------
  |  Branch (1004:9): [True: 305, False: 2.01k]
  ------------------
 1005|    305|            PLIST_JSON_ERR("%s: Incomplete JSON, more bytes expected\n", __func__);
  ------------------
  |  |   49|    305|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 305]
  |  |  ------------------
  ------------------
 1006|    305|            free(tokens);
 1007|    305|            return PLIST_ERR_PARSE;
 1008|      0|        case JSMN_ERROR_LIMIT:
  ------------------
  |  Branch (1008:9): [True: 0, False: 2.31k]
  ------------------
 1009|      0|            PLIST_JSON_ERR("%s: Input data too large\n", __func__);
  ------------------
  |  |   49|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1010|      0|            free(tokens);
 1011|      0|            return PLIST_ERR_PARSE;
 1012|  1.94k|        default:
  ------------------
  |  Branch (1012:9): [True: 1.94k, False: 375]
  ------------------
 1013|  1.94k|            break;
 1014|  2.31k|    }
 1015|       |
 1016|  1.94k|    int startindex = 0;
 1017|  1.94k|    jsmntok_info_t ti = { tokens, parser.toknext, PLIST_ERR_SUCCESS };
 1018|  1.94k|    switch (tokens[startindex].type) {
 1019|    708|        case JSMN_PRIMITIVE:
  ------------------
  |  Branch (1019:9): [True: 708, False: 1.23k]
  ------------------
 1020|    708|            *plist = parse_primitive(json, &ti, &startindex);
 1021|    708|            break;
 1022|    188|        case JSMN_STRING:
  ------------------
  |  Branch (1022:9): [True: 188, False: 1.75k]
  ------------------
 1023|    188|            *plist = parse_string(json, &ti, &startindex);
 1024|    188|            break;
 1025|    445|        case JSMN_ARRAY:
  ------------------
  |  Branch (1025:9): [True: 445, False: 1.49k]
  ------------------
 1026|    445|            *plist = parse_array(json, &ti, &startindex, 0);
 1027|    445|            break;
 1028|    600|        case JSMN_OBJECT:
  ------------------
  |  Branch (1028:9): [True: 600, False: 1.34k]
  ------------------
 1029|    600|            *plist = parse_object(json, &ti, &startindex, 0);
 1030|    600|            break;
 1031|      0|        default:
  ------------------
  |  Branch (1031:9): [True: 0, False: 1.94k]
  ------------------
 1032|      0|            break;
 1033|  1.94k|    }
 1034|  1.94k|    free(tokens);
 1035|  1.94k|    if (!*plist) {
  ------------------
  |  Branch (1035:9): [True: 472, False: 1.46k]
  ------------------
 1036|    472|        return (ti.err != PLIST_ERR_SUCCESS) ? ti.err : PLIST_ERR_PARSE;
  ------------------
  |  Branch (1036:16): [True: 141, False: 331]
  ------------------
 1037|    472|    }
 1038|  1.46k|    return PLIST_ERR_SUCCESS;
 1039|  1.94k|}
jplist.c:parse_primitive:
  603|  27.0k|{
  604|  27.0k|    if (ti->tokens[*index].type != JSMN_PRIMITIVE) {
  ------------------
  |  Branch (604:9): [True: 0, False: 27.0k]
  ------------------
  605|      0|        PLIST_JSON_ERR("%s: token type != JSMN_PRIMITIVE\n", __func__);
  ------------------
  |  |   49|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  606|      0|        return NULL;
  607|      0|    }
  608|  27.0k|    plist_t val = NULL;
  609|  27.0k|    const char* str_val = js + ti->tokens[*index].start;
  610|  27.0k|    const char* str_end = js + ti->tokens[*index].end;
  611|  27.0k|    size_t str_len = ti->tokens[*index].end - ti->tokens[*index].start;
  612|  27.0k|    if (!strncmp("false", str_val, str_len)) {
  ------------------
  |  Branch (612:9): [True: 3.79k, False: 23.2k]
  ------------------
  613|  3.79k|        val = plist_new_bool(0);
  614|  23.2k|    } else if (!strncmp("true", str_val, str_len)) {
  ------------------
  |  Branch (614:16): [True: 2.92k, False: 20.3k]
  ------------------
  615|  2.92k|        val = plist_new_bool(1);
  616|  20.3k|    } else if (!strncmp("null", str_val, str_len)) {
  ------------------
  |  Branch (616:16): [True: 13.9k, False: 6.39k]
  ------------------
  617|  13.9k|        plist_data_t data = plist_new_plist_data();
  618|  13.9k|        if (!data) {
  ------------------
  |  Branch (618:13): [True: 0, False: 13.9k]
  ------------------
  619|      0|            PLIST_JSON_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |   49|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  620|      0|            return NULL;
  621|      0|        }
  622|  13.9k|        data->type = PLIST_NULL;
  623|  13.9k|        val = plist_new_node(data);
  624|  13.9k|    } else if (isdigit(str_val[0]) || (str_val[0] == '-' && str_val+1 < str_end && isdigit(str_val[1]))) {
  ------------------
  |  Branch (624:16): [True: 5.49k, False: 903]
  |  Branch (624:40): [True: 737, False: 166]
  |  Branch (624:61): [True: 728, False: 9]
  |  Branch (624:84): [True: 723, False: 5]
  ------------------
  625|  6.21k|        char* endp = (char*)str_val;
  626|  6.21k|        int is_neg = (str_val[0] == '-');
  627|  6.21k|        int64_t intpart = parse_decimal(str_val, str_end, &endp);
  628|  6.21k|        if (endp >= str_end) {
  ------------------
  |  Branch (628:13): [True: 3.96k, False: 2.25k]
  ------------------
  629|       |            /* integer */
  630|  3.96k|            if (is_neg || intpart <= INT64_MAX) {
  ------------------
  |  Branch (630:17): [True: 483, False: 3.48k]
  |  Branch (630:27): [True: 3.48k, False: 0]
  ------------------
  631|  3.96k|                val = plist_new_int(intpart);
  632|  3.96k|            } else {
  633|      0|                val = plist_new_uint((uint64_t)intpart);
  634|      0|            }
  635|  3.96k|        } 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 (635:21): [True: 474, False: 1.77k]
  |  Branch (635:37): [True: 473, False: 1]
  |  Branch (635:57): [True: 471, False: 2]
  |  Branch (635:82): [True: 1.33k, False: 446]
  |  Branch (635:98): [True: 423, False: 23]
  |  Branch (635:115): [True: 1.74k, False: 15]
  |  Branch (635:136): [True: 684, False: 1.05k]
  |  Branch (635:160): [True: 781, False: 278]
  |  Branch (635:182): [True: 266, False: 12]
  |  Branch (635:205): [True: 1.03k, False: 14]
  |  Branch (635:225): [True: 1.03k, False: 2]
  ------------------
  636|       |            /* floating point */
  637|  2.18k|            double dval = (double)intpart;
  638|  2.18k|            char* fendp = endp;
  639|  2.18k|            int err = 0;
  640|  2.18k|            do {
  641|  2.18k|                if (*endp == '.') {
  ------------------
  |  Branch (641:21): [True: 471, False: 1.71k]
  ------------------
  642|    471|                    fendp++;
  643|    471|                    double frac = 0;
  644|    471|                    double p = 0.1;
  645|  1.37k|                    while (fendp < str_end && isdigit(*fendp)) {
  ------------------
  |  Branch (645:28): [True: 928, False: 444]
  |  Branch (645:47): [True: 901, False: 27]
  ------------------
  646|    901|                        frac = frac + (*fendp - '0') * p;
  647|    901|                        p *= 0.1;
  648|    901|                        fendp++;
  649|    901|                    }
  650|    471|                    if (is_neg) {
  ------------------
  |  Branch (650:25): [True: 240, False: 231]
  ------------------
  651|    240|                        dval -= frac;
  652|    240|                    } else {
  653|    231|                        dval += frac;
  654|    231|                    }
  655|    471|                }
  656|  2.18k|                if (fendp >= str_end) {
  ------------------
  |  Branch (656:21): [True: 444, False: 1.74k]
  ------------------
  657|    444|                    break;
  658|    444|                }
  659|  1.74k|                if (fendp+1 < str_end && (*fendp == 'e' || *fendp == 'E') && (isdigit(*(fendp+1)) || (((*(fendp+1) == '-') || (*(fendp+1) == '+')) && fendp+2 < str_end && isdigit(*(fendp+2))))) {
  ------------------
  |  Branch (659:21): [True: 1.74k, False: 2]
  |  Branch (659:43): [True: 1.32k, False: 420]
  |  Branch (659:60): [True: 406, False: 14]
  |  Branch (659:79): [True: 684, False: 1.04k]
  |  Branch (659:104): [True: 773, False: 269]
  |  Branch (659:127): [True: 260, False: 9]
  |  Branch (659:151): [True: 1.03k, False: 1]
  |  Branch (659:172): [True: 1.03k, False: 1]
  ------------------
  660|  1.71k|                    int64_t exp = parse_decimal(fendp+1, str_end, &fendp);
  661|  1.71k|                    dval = dval * pow(10, (double)exp);
  662|  1.71k|                } else {
  663|     27|                    PLIST_JSON_ERR("%s: invalid character at offset %d when parsing floating point value\n", __func__, (int)(fendp - js));
  ------------------
  |  |   49|     27|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 27]
  |  |  ------------------
  ------------------
  664|     27|                    err++;
  665|     27|                }
  666|  1.74k|            } while (0);
  ------------------
  |  Branch (666:22): [Folded, False: 1.74k]
  ------------------
  667|  2.18k|            if (!err) {
  ------------------
  |  Branch (667:17): [True: 2.15k, False: 27]
  ------------------
  668|  2.15k|                if (isinf(dval) || isnan(dval)) {
  ------------------
  |  Branch (668:21): [True: 113, False: 2.04k]
  |  Branch (668:36): [True: 43, False: 2.00k]
  ------------------
  669|    156|                   PLIST_JSON_ERR("%s: unrepresentable floating point value at offset %d when parsing numerical value\n", __func__, (int)(str_val - js));
  ------------------
  |  |   49|    156|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 156]
  |  |  ------------------
  ------------------
  670|  2.00k|                } else {
  671|  2.00k|                    val = plist_new_real(dval);
  672|  2.00k|                }
  673|  2.15k|            }
  674|  2.18k|        } else {
  675|     66|            PLIST_JSON_ERR("%s: invalid character at offset %d when parsing numerical value\n", __func__, (int)(endp - js));
  ------------------
  |  |   49|     66|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 66]
  |  |  ------------------
  ------------------
  676|     66|        }
  677|  6.21k|    } else {
  678|    180|        PLIST_JSON_ERR("%s: invalid primitive value '%.*s' encountered\n", __func__, (int)str_len, str_val);
  ------------------
  |  |   49|    180|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 180]
  |  |  ------------------
  ------------------
  679|    180|    }
  680|  27.0k|    if (!val) {
  ------------------
  |  Branch (680:9): [True: 429, False: 26.6k]
  ------------------
  681|    429|        PLIST_JSON_ERR("%s: failed to create node\n", __func__);
  ------------------
  |  |   49|    429|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 429]
  |  |  ------------------
  ------------------
  682|    429|        return NULL;
  683|    429|    }
  684|  26.6k|    (*index)++;
  685|  26.6k|    return val;
  686|  27.0k|}
jplist.c:parse_decimal:
  558|  7.93k|{
  559|  7.93k|    uint64_t MAX = INT64_MAX;
  560|  7.93k|    uint64_t x = 0;
  561|  7.93k|    int is_neg = 0;
  562|  7.93k|    *endp = (char*)str;
  563|       |
  564|  7.93k|    if (str[0] == '-') {
  ------------------
  |  Branch (564:9): [True: 1.49k, False: 6.43k]
  ------------------
  565|  1.49k|        is_neg = 1;
  566|  1.49k|        (*endp)++;
  567|  6.43k|    } else if (str[0] == '+') {
  ------------------
  |  Branch (567:16): [True: 258, False: 6.17k]
  ------------------
  568|    258|        (*endp)++;
  569|    258|    }
  570|  7.93k|    if (is_neg) {
  ------------------
  |  Branch (570:9): [True: 1.49k, False: 6.43k]
  ------------------
  571|  1.49k|        MAX++;
  572|  1.49k|    }
  573|  38.9k|    while (*endp < str_end && isdigit(**endp)) {
  ------------------
  |  Branch (573:12): [True: 34.3k, False: 4.60k]
  |  Branch (573:31): [True: 32.1k, False: 2.26k]
  ------------------
  574|  32.1k|        if (x > PO10i_LIMIT) {
  ------------------
  |  |  328|  32.1k|#define PO10i_LIMIT (INT64_MAX/10)
  ------------------
  |  Branch (574:13): [True: 653, False: 31.4k]
  ------------------
  575|    653|            x = MAX;
  576|    653|            break;
  577|    653|        }
  578|  31.4k|        x = x * 10;
  579|  31.4k|        unsigned int add = (**endp - '0');
  580|  31.4k|        if (x + add > MAX) {
  ------------------
  |  Branch (580:13): [True: 409, False: 31.0k]
  ------------------
  581|    409|            x = MAX;
  582|    409|            break;
  583|    409|        }
  584|  31.0k|        x += add;
  585|  31.0k|        (*endp)++;
  586|  31.0k|    }
  587|       |
  588|       |    // swallow the rest of the digits in case we dropped out early
  589|  9.62k|    while (*endp < str_end && isdigit(**endp)) (*endp)++;
  ------------------
  |  Branch (589:12): [True: 3.96k, False: 5.66k]
  |  Branch (589:31): [True: 1.69k, False: 2.27k]
  ------------------
  590|       |
  591|  7.93k|    int64_t result = x;
  592|  7.93k|    if (is_neg) {
  ------------------
  |  Branch (592:9): [True: 1.49k, False: 6.43k]
  ------------------
  593|  1.49k|        if (x == MAX) {
  ------------------
  |  Branch (593:13): [True: 636, False: 860]
  ------------------
  594|    636|            result = INT64_MIN;
  595|    860|        } else {
  596|    860|            result = -(int64_t)x;
  597|    860|        }
  598|  1.49k|    }
  599|  7.93k|    return result;
  600|  7.93k|}
jplist.c:parse_string:
  768|  33.5k|{
  769|  33.5k|    if (ti->tokens[*index].type != JSMN_STRING) {
  ------------------
  |  Branch (769:9): [True: 0, False: 33.5k]
  ------------------
  770|      0|        PLIST_JSON_ERR("%s: token type != JSMN_STRING\n", __func__);
  ------------------
  |  |   49|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  771|      0|        return NULL;
  772|      0|    }
  773|       |
  774|  33.5k|    size_t str_len = 0; ;
  775|  33.5k|    char* strval = unescape_string(js + ti->tokens[*index].start, ti->tokens[*index].end - ti->tokens[*index].start, &str_len);
  776|  33.5k|    if (!strval) {
  ------------------
  |  Branch (776:9): [True: 17, False: 33.5k]
  ------------------
  777|     17|        return NULL;
  778|     17|    }
  779|  33.5k|    plist_t node;
  780|       |
  781|  33.5k|    plist_data_t data = plist_new_plist_data();
  782|  33.5k|    if (!data) {
  ------------------
  |  Branch (782:9): [True: 0, False: 33.5k]
  ------------------
  783|      0|        free(strval);
  784|      0|        PLIST_JSON_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |   49|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  785|      0|        return NULL;
  786|      0|    }
  787|  33.5k|    data->type = PLIST_STRING;
  788|  33.5k|    data->strval = strval;
  789|  33.5k|    data->length = str_len;
  790|  33.5k|    node = plist_new_node(data);
  791|  33.5k|    if (!node) {
  ------------------
  |  Branch (791:9): [True: 0, False: 33.5k]
  ------------------
  792|      0|        plist_free_data(data);
  793|      0|        PLIST_JSON_ERR("%s: failed to create node\n", __func__);
  ------------------
  |  |   49|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  794|      0|        return NULL;
  795|      0|    }
  796|       |
  797|  33.5k|    (*index)++;
  798|  33.5k|    return node;
  799|  33.5k|}
jplist.c:unescape_string:
  689|  98.3k|{
  690|  98.3k|    char* strval = strndup(str_val, str_len);
  691|  98.3k|    if (!strval) return NULL;
  ------------------
  |  Branch (691:9): [True: 0, False: 98.3k]
  ------------------
  692|  98.3k|    size_t i = 0;
  693|   235k|    while (i < str_len) {
  ------------------
  |  Branch (693:12): [True: 136k, False: 98.3k]
  ------------------
  694|   136k|        if (strval[i] == '\\' && i < str_len-1) {
  ------------------
  |  Branch (694:13): [True: 5.04k, False: 131k]
  |  Branch (694:34): [True: 5.04k, False: 0]
  ------------------
  695|  5.04k|            switch (strval[i+1]) {
  696|  1.82k|                case '\"': case '/' : case '\\' : case 'b' :
  ------------------
  |  Branch (696:17): [True: 383, False: 4.66k]
  |  Branch (696:28): [True: 739, False: 4.30k]
  |  Branch (696:39): [True: 310, False: 4.73k]
  |  Branch (696:51): [True: 397, False: 4.64k]
  ------------------
  697|  3.99k|                case 'f' : case 'r' : case 'n'  : case 't' :
  ------------------
  |  Branch (697:17): [True: 879, False: 4.16k]
  |  Branch (697:28): [True: 230, False: 4.81k]
  |  Branch (697:39): [True: 592, False: 4.45k]
  |  Branch (697:51): [True: 460, False: 4.58k]
  ------------------
  698|  3.99k|                    memmove(strval+i, strval+i+1, str_len - (i+1));
  699|  3.99k|                    str_len--;
  700|  3.99k|                    switch (strval[i]) {
  701|    397|                        case 'b':
  ------------------
  |  Branch (701:25): [True: 397, False: 3.59k]
  ------------------
  702|    397|                            strval[i] = '\b';
  703|    397|                            break;
  704|    879|                        case 'f':
  ------------------
  |  Branch (704:25): [True: 879, False: 3.11k]
  ------------------
  705|    879|                            strval[i] = '\f';
  706|    879|                            break;
  707|    230|                        case 'r':
  ------------------
  |  Branch (707:25): [True: 230, False: 3.76k]
  ------------------
  708|    230|                            strval[i] = '\r';
  709|    230|                            break;
  710|    592|                        case 'n':
  ------------------
  |  Branch (710:25): [True: 592, False: 3.39k]
  ------------------
  711|    592|                            strval[i] = '\n';
  712|    592|                            break;
  713|    460|                        case 't':
  ------------------
  |  Branch (713:25): [True: 460, False: 3.53k]
  ------------------
  714|    460|                            strval[i] = '\t';
  715|    460|                            break;
  716|  1.43k|                        default:
  ------------------
  |  Branch (716:25): [True: 1.43k, False: 2.55k]
  ------------------
  717|  1.43k|                            break;
  718|  3.99k|                    }
  719|  3.99k|                    break;
  720|  3.99k|                case 'u': {
  ------------------
  |  Branch (720:17): [True: 1.05k, False: 3.99k]
  ------------------
  721|  1.05k|                    unsigned int val = 0;
  722|  1.05k|                    if (str_len-(i+2) < 4) {
  ------------------
  |  Branch (722:25): [True: 5, False: 1.04k]
  ------------------
  723|      5|                        PLIST_JSON_ERR("%s: invalid escape sequence '%s' (too short)\n", __func__, strval+i);
  ------------------
  |  |   49|      5|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 5]
  |  |  ------------------
  ------------------
  724|      5|                        free(strval);
  725|      5|                        return NULL;
  726|      5|                    }
  727|  1.04k|                    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 (727:27): [True: 1.04k, False: 4]
  |  Branch (727:52): [True: 1.04k, False: 2]
  |  Branch (727:77): [True: 1.03k, False: 5]
  |  Branch (727:102): [True: 1.03k, False: 2]
  |  Branch (727:128): [True: 0, False: 1.03k]
  ------------------
  728|     13|                        PLIST_JSON_ERR("%s: invalid escape sequence '%.*s'\n", __func__, 6, strval+i);
  ------------------
  |  |   49|     13|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 13]
  |  |  ------------------
  ------------------
  729|     13|                        free(strval);
  730|     13|                        return NULL;
  731|     13|                    }
  732|  1.03k|                    int bytelen = 0;
  733|  1.03k|                    if (val >= 0x800) {
  ------------------
  |  Branch (733:25): [True: 393, False: 643]
  ------------------
  734|       |                        /* three bytes */
  735|    393|                        strval[i]   = (char)(0xE0 + ((val >> 12) & 0xF));
  736|    393|                        strval[i+1] = (char)(0x80 + ((val >> 6) & 0x3F));
  737|    393|                        strval[i+2] = (char)(0x80 + (val & 0x3F));
  738|    393|                        bytelen = 3;
  739|    643|                    } else if (val >= 0x80) {
  ------------------
  |  Branch (739:32): [True: 400, False: 243]
  ------------------
  740|       |                        /* two bytes */
  741|    400|                        strval[i]   = (char)(0xC0 + ((val >> 6) & 0x1F));
  742|    400|                        strval[i+1] = (char)(0x80 + (val & 0x3F));
  743|    400|                        bytelen = 2;
  744|    400|                    } else {
  745|       |                        /* one byte */
  746|    243|                        strval[i] = (char)(val & 0x7F);
  747|    243|                        bytelen = 1;
  748|    243|                    }
  749|  1.03k|                    memmove(strval+i+bytelen, strval+i+6, str_len - (i+5));
  750|  1.03k|                    str_len -= (6-bytelen);
  751|  1.03k|                }   break;
  752|      0|                default:
  ------------------
  |  Branch (752:17): [True: 0, False: 5.04k]
  ------------------
  753|      0|                    PLIST_JSON_ERR("%s: invalid escape sequence '%.*s'\n", __func__, 2, strval+i);
  ------------------
  |  |   49|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  754|      0|                    free(strval);
  755|      0|                    return NULL;
  756|  5.04k|            }
  757|  5.04k|        }
  758|   136k|        i++;
  759|   136k|    }
  760|  98.3k|    strval[str_len] = '\0';
  761|  98.3k|    if (new_len) {
  ------------------
  |  Branch (761:9): [True: 33.5k, False: 64.8k]
  ------------------
  762|  33.5k|        *new_len = str_len;
  763|  33.5k|    }
  764|  98.3k|    return strval;
  765|  98.3k|}
jplist.c:parse_array:
  804|  53.8k|{
  805|  53.8k|    if (ti->tokens[*index].type != JSMN_ARRAY) {
  ------------------
  |  Branch (805:9): [True: 0, False: 53.8k]
  ------------------
  806|      0|        PLIST_JSON_ERR("%s: token type != JSMN_ARRAY\n", __func__);
  ------------------
  |  |   49|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  807|      0|        ti->err = PLIST_ERR_PARSE;
  808|      0|        return NULL;
  809|      0|    }
  810|  53.8k|    if (depth > PLIST_MAX_NESTING_DEPTH) {
  ------------------
  |  |   56|  53.8k|#define PLIST_MAX_NESTING_DEPTH NODE_MAX_DEPTH
  |  |  ------------------
  |  |  |  |   33|  53.8k|#define NODE_MAX_DEPTH 512
  |  |  ------------------
  ------------------
  |  Branch (810:9): [True: 1, False: 53.8k]
  ------------------
  811|      1|        PLIST_JSON_ERR("%s: maximum nesting depth (%u) exceeded\n", __func__, (unsigned)PLIST_MAX_NESTING_DEPTH);
  ------------------
  |  |   49|      1|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 1]
  |  |  ------------------
  ------------------
  812|      1|        ti->err = PLIST_ERR_MAX_NESTING;
  813|      1|        return NULL;
  814|      1|    }
  815|  53.8k|    plist_t arr = plist_new_array();
  816|  53.8k|    if (!arr) {
  ------------------
  |  Branch (816:9): [True: 0, False: 53.8k]
  ------------------
  817|      0|        PLIST_JSON_ERR("%s: failed to create array node\n", __func__);
  ------------------
  |  |   49|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  818|      0|        ti->err = PLIST_ERR_NO_MEM;
  819|      0|        return NULL;
  820|      0|    }
  821|  53.8k|    size_t num_tokens = ti->tokens[*index].size;
  822|  53.8k|    size_t num;
  823|  53.8k|    int j = (*index)+1;
  824|   106k|    for (num = 0; num < num_tokens; num++) {
  ------------------
  |  Branch (824:19): [True: 59.7k, False: 46.4k]
  ------------------
  825|  59.7k|        if (j >= ti->count) {
  ------------------
  |  Branch (825:13): [True: 0, False: 59.7k]
  ------------------
  826|      0|            PLIST_JSON_ERR("%s: token index out of valid range\n", __func__);
  ------------------
  |  |   49|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  827|      0|            plist_free(arr);
  828|      0|            ti->err = PLIST_ERR_PARSE;
  829|      0|            return NULL;
  830|      0|        }
  831|  59.7k|        plist_t val = NULL;
  832|  59.7k|        switch (ti->tokens[j].type) {
  833|    583|            case JSMN_OBJECT:
  ------------------
  |  Branch (833:13): [True: 583, False: 59.1k]
  ------------------
  834|    583|                val = parse_object(js, ti, &j, depth+1);
  835|    583|                break;
  836|  33.5k|            case JSMN_ARRAY:
  ------------------
  |  Branch (836:13): [True: 33.5k, False: 26.2k]
  ------------------
  837|  33.5k|                val = parse_array(js, ti, &j, depth+1);
  838|  33.5k|                break;
  839|  1.45k|            case JSMN_STRING:
  ------------------
  |  Branch (839:13): [True: 1.45k, False: 58.3k]
  ------------------
  840|  1.45k|                val = parse_string(js, ti, &j);
  841|  1.45k|                break;
  842|  24.1k|            case JSMN_PRIMITIVE:
  ------------------
  |  Branch (842:13): [True: 24.1k, False: 35.5k]
  ------------------
  843|  24.1k|                val = parse_primitive(js, ti, &j);
  844|  24.1k|                break;
  845|      0|            default:
  ------------------
  |  Branch (845:13): [True: 0, False: 59.7k]
  ------------------
  846|      0|                break;
  847|  59.7k|        }
  848|  59.7k|        if (val) {
  ------------------
  |  Branch (848:13): [True: 52.4k, False: 7.34k]
  ------------------
  849|  52.4k|            plist_array_append_item(arr, val);
  850|       |            // if append failed, val still has no parent, free it and abort
  851|  52.4k|            if (((node_t)val)->parent == NULL) {
  ------------------
  |  Branch (851:17): [True: 2, False: 52.4k]
  ------------------
  852|      2|                plist_free(val);
  853|      2|                plist_free(arr);
  854|      2|                ti->err = PLIST_ERR_NO_MEM;
  855|      2|                return NULL;
  856|      2|            }
  857|  52.4k|        } else {
  858|  7.34k|            plist_free(arr);
  859|  7.34k|            ti->err = PLIST_ERR_PARSE;
  860|  7.34k|            return NULL;
  861|  7.34k|        }
  862|  59.7k|    }
  863|  46.4k|    *(index) = j;
  864|  46.4k|    return arr;
  865|  53.8k|}
jplist.c:parse_object:
  868|  12.1k|{
  869|  12.1k|    if (ti->tokens[*index].type != JSMN_OBJECT) {
  ------------------
  |  Branch (869:9): [True: 0, False: 12.1k]
  ------------------
  870|      0|        PLIST_JSON_ERR("%s: token type != JSMN_OBJECT\n", __func__);
  ------------------
  |  |   49|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  871|      0|        ti->err = PLIST_ERR_PARSE;
  872|      0|        return NULL;
  873|      0|    }
  874|  12.1k|    if (depth > PLIST_MAX_NESTING_DEPTH) {
  ------------------
  |  |   56|  12.1k|#define PLIST_MAX_NESTING_DEPTH NODE_MAX_DEPTH
  |  |  ------------------
  |  |  |  |   33|  12.1k|#define NODE_MAX_DEPTH 512
  |  |  ------------------
  ------------------
  |  Branch (874:9): [True: 1, False: 12.1k]
  ------------------
  875|      1|        PLIST_JSON_ERR("%s: maximum nesting depth (%u) exceeded\n", __func__, (unsigned)PLIST_MAX_NESTING_DEPTH);
  ------------------
  |  |   49|      1|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 1]
  |  |  ------------------
  ------------------
  876|      1|        ti->err = PLIST_ERR_MAX_NESTING;
  877|      1|        return NULL;
  878|      1|    }
  879|  12.1k|    size_t num_tokens = ti->tokens[*index].size;
  880|  12.1k|    size_t num;
  881|  12.1k|    int j = (*index)+1;
  882|  12.1k|    if (num_tokens % 2 != 0) {
  ------------------
  |  Branch (882:9): [True: 11, False: 12.1k]
  ------------------
  883|     11|        PLIST_JSON_ERR("%s: number of children must be even\n", __func__);
  ------------------
  |  |   49|     11|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 11]
  |  |  ------------------
  ------------------
  884|     11|        ti->err = PLIST_ERR_PARSE;
  885|     11|        return NULL;
  886|     11|    }
  887|  12.1k|    plist_t obj = plist_new_dict();
  888|  12.1k|    if (!obj) {
  ------------------
  |  Branch (888:9): [True: 0, False: 12.1k]
  ------------------
  889|      0|        PLIST_JSON_ERR("%s: failed to create dict node\n", __func__);
  ------------------
  |  |   49|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  890|      0|        ti->err = PLIST_ERR_NO_MEM;
  891|      0|        return NULL;
  892|      0|    }
  893|  76.7k|    for (num = 0; num < num_tokens; num++) {
  ------------------
  |  Branch (893:19): [True: 64.8k, False: 11.9k]
  ------------------
  894|  64.8k|        if (j+1 >= ti->count) {
  ------------------
  |  Branch (894:13): [True: 0, False: 64.8k]
  ------------------
  895|      0|            PLIST_JSON_ERR("%s: token index out of valid range\n", __func__);
  ------------------
  |  |   49|      0|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  896|      0|            plist_free(obj);
  897|      0|            ti->err = PLIST_ERR_PARSE;
  898|      0|            return NULL;
  899|      0|        }
  900|  64.8k|        if (ti->tokens[j].type == JSMN_STRING) {
  ------------------
  |  Branch (900:13): [True: 64.8k, False: 5]
  ------------------
  901|  64.8k|            char* key = unescape_string(js + ti->tokens[j].start, ti->tokens[j].end - ti->tokens[j].start, NULL);
  902|  64.8k|            if (!key) {
  ------------------
  |  Branch (902:17): [True: 1, False: 64.8k]
  ------------------
  903|      1|                plist_free(obj);
  904|      1|                ti->err = PLIST_ERR_PARSE;
  905|      1|                return NULL;
  906|      1|            }
  907|  64.8k|            plist_t val = NULL;
  908|  64.8k|            j++;
  909|  64.8k|            num++;
  910|  64.8k|            switch (ti->tokens[j].type) {
  911|  10.9k|                case JSMN_OBJECT:
  ------------------
  |  Branch (911:17): [True: 10.9k, False: 53.8k]
  ------------------
  912|  10.9k|                    val = parse_object(js, ti, &j, depth+1);
  913|  10.9k|                    break;
  914|  19.8k|                case JSMN_ARRAY:
  ------------------
  |  Branch (914:17): [True: 19.8k, False: 44.9k]
  ------------------
  915|  19.8k|                    val = parse_array(js, ti, &j, depth+1);
  916|  19.8k|                    break;
  917|  31.8k|                case JSMN_STRING:
  ------------------
  |  Branch (917:17): [True: 31.8k, False: 32.9k]
  ------------------
  918|  31.8k|                    val = parse_string(js, ti, &j);
  919|  31.8k|                    break;
  920|  2.14k|                case JSMN_PRIMITIVE:
  ------------------
  |  Branch (920:17): [True: 2.14k, False: 62.6k]
  ------------------
  921|  2.14k|                    val = parse_primitive(js, ti, &j);
  922|  2.14k|                    break;
  923|      0|                default:
  ------------------
  |  Branch (923:17): [True: 0, False: 64.8k]
  ------------------
  924|      0|                    break;
  925|  64.8k|            }
  926|  64.8k|            if (val) {
  ------------------
  |  Branch (926:17): [True: 64.6k, False: 204]
  ------------------
  927|  64.6k|                plist_dict_set_item(obj, key, val);
  928|       |                // if set failed, val still has no parent, free it and abort
  929|  64.6k|                if (((node_t)val)->parent == NULL) {
  ------------------
  |  Branch (929:21): [True: 5, False: 64.6k]
  ------------------
  930|      5|                    plist_free(val);
  931|      5|                    free(key);
  932|      5|                    plist_free(obj);
  933|      5|                    ti->err = PLIST_ERR_NO_MEM;
  934|      5|                    return NULL;
  935|      5|                }
  936|  64.6k|            } else {
  937|    204|                free(key);
  938|    204|                plist_free(obj);
  939|    204|                ti->err = PLIST_ERR_PARSE;
  940|    204|                return NULL;
  941|    204|            }
  942|  64.6k|            free(key);
  943|  64.6k|        } else {
  944|      5|            PLIST_JSON_ERR("%s: keys must be of type STRING\n", __func__);
  ------------------
  |  |   49|      5|#define PLIST_JSON_ERR(...) if (plist_json_debug) { fprintf(stderr, "libplist[jsonparser] ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (49:33): [True: 0, False: 5]
  |  |  ------------------
  ------------------
  945|      5|            plist_free(obj);
  946|      5|            ti->err = PLIST_ERR_PARSE;
  947|      5|            return NULL;
  948|      5|        }
  949|  64.8k|    }
  950|  11.9k|    (*index) = j;
  951|  11.9k|    return obj;
  952|  12.1k|}

jsmn_parse:
  173|  12.3k|		unsigned int num_tokens) {
  174|  12.3k|	jsmnerr_t r;
  175|  12.3k|	int i;
  176|  12.3k|	jsmntok_t *token;
  177|       |
  178|  12.3k|	parser->end = length;
  179|       |
  180|  12.3k|	if (num_tokens >= INT_MAX) {
  ------------------
  |  Branch (180:6): [True: 0, False: 12.3k]
  ------------------
  181|      0|		return JSMN_ERROR_LIMIT;
  182|      0|	}
  183|  12.3k|	if (length > SIZE_MAX / 2) {
  ------------------
  |  Branch (183:6): [True: 0, False: 12.3k]
  ------------------
  184|      0|		return JSMN_ERROR_LIMIT;
  185|      0|	}
  186|       |
  187|   410k|	for (; (parser->end > 0 && parser->pos < parser->end) && js[parser->pos] != '\0'; parser->pos++) {
  ------------------
  |  Branch (187:10): [True: 410k, False: 0]
  |  Branch (187:29): [True: 408k, False: 2.11k]
  |  Branch (187:59): [True: 408k, False: 6]
  ------------------
  188|   408k|		char c;
  189|   408k|		jsmntype_t type;
  190|       |
  191|   408k|		c = js[parser->pos];
  192|   408k|		switch (c) {
  193|   160k|			case '{': case '[':
  ------------------
  |  Branch (193:4): [True: 55.7k, False: 352k]
  |  Branch (193:14): [True: 104k, False: 303k]
  ------------------
  194|   160k|				token = jsmn_alloc_token(parser, tokens, num_tokens);
  195|   160k|				if (token == NULL)
  ------------------
  |  Branch (195:9): [True: 6.42k, False: 153k]
  ------------------
  196|  6.42k|					return JSMN_ERROR_NOMEM;
  197|   153k|				if (parser->toksuper != -1) {
  ------------------
  |  Branch (197:9): [True: 147k, False: 6.28k]
  ------------------
  198|   147k|					tokens[parser->toksuper].size++;
  199|       |#ifdef JSMN_PARENT_LINKS
  200|       |					token->parent = parser->toksuper;
  201|       |#endif
  202|   147k|				}
  203|   153k|				token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
  ------------------
  |  Branch (203:20): [True: 52.6k, False: 100k]
  ------------------
  204|   153k|				token->start = parser->pos;
  205|   153k|				parser->toksuper = parser->toknext - 1;
  206|   153k|				break;
  207|  73.8k|			case '}': case ']':
  ------------------
  |  Branch (207:4): [True: 17.6k, False: 390k]
  |  Branch (207:14): [True: 56.1k, False: 351k]
  ------------------
  208|  73.8k|				type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
  ------------------
  |  Branch (208:13): [True: 17.6k, False: 56.1k]
  ------------------
  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.16M|				for (i = parser->toknext - 1; i >= 0; i--) {
  ------------------
  |  Branch (232:35): [True: 6.16M, False: 39]
  ------------------
  233|  6.16M|					token = &tokens[i];
  234|  6.16M|					if (token->start != JSMN_POS_INVALID && token->end == JSMN_POS_INVALID) {
  ------------------
  |  |   35|  12.3M|#define JSMN_POS_INVALID ((size_t)SIZE_MAX)
  ------------------
              					if (token->start != JSMN_POS_INVALID && token->end == JSMN_POS_INVALID) {
  ------------------
  |  |   35|  6.16M|#define JSMN_POS_INVALID ((size_t)SIZE_MAX)
  ------------------
  |  Branch (234:10): [True: 6.16M, False: 0]
  |  Branch (234:46): [True: 73.7k, False: 6.09M]
  ------------------
  235|  73.7k|						if (token->type != type) {
  ------------------
  |  Branch (235:11): [True: 6, False: 73.7k]
  ------------------
  236|      6|							return JSMN_ERROR_INVAL;
  237|      6|						}
  238|  73.7k|						parser->toksuper = -1;
  239|  73.7k|						token->end = parser->pos + 1;
  240|  73.7k|						break;
  241|  73.7k|					}
  242|  6.16M|				}
  243|       |				/* Error if unmatched closing bracket */
  244|  73.8k|				if (i == -1) return JSMN_ERROR_INVAL;
  ------------------
  |  Branch (244:9): [True: 39, False: 73.7k]
  ------------------
  245|  26.7M|				for (; i >= 0; i--) {
  ------------------
  |  Branch (245:12): [True: 26.7M, False: 6.07k]
  ------------------
  246|  26.7M|					token = &tokens[i];
  247|  26.7M|					if (token->start != JSMN_POS_INVALID && token->end == JSMN_POS_INVALID) {
  ------------------
  |  |   35|  53.4M|#define JSMN_POS_INVALID ((size_t)SIZE_MAX)
  ------------------
              					if (token->start != JSMN_POS_INVALID && token->end == JSMN_POS_INVALID) {
  ------------------
  |  |   35|  26.7M|#define JSMN_POS_INVALID ((size_t)SIZE_MAX)
  ------------------
  |  Branch (247:10): [True: 26.7M, False: 0]
  |  Branch (247:46): [True: 67.6k, False: 26.6M]
  ------------------
  248|  67.6k|						parser->toksuper = i;
  249|  67.6k|						break;
  250|  67.6k|					}
  251|  26.7M|				}
  252|  73.7k|#endif
  253|  73.7k|				break;
  254|   109k|			case '\"':
  ------------------
  |  Branch (254:4): [True: 109k, False: 298k]
  ------------------
  255|   109k|				r = jsmn_parse_string(parser, js, tokens, num_tokens);
  256|   109k|				if (r < 0) return r;
  ------------------
  |  Branch (256:9): [True: 2.69k, False: 107k]
  ------------------
  257|   107k|				if (parser->toksuper != -1)
  ------------------
  |  Branch (257:9): [True: 106k, False: 402]
  ------------------
  258|   106k|					tokens[parser->toksuper].size++;
  259|   107k|				break;
  260|  32.2k|			case '\t' : case '\r' : case '\n' : case ':' : case ',': case ' ':
  ------------------
  |  Branch (260:4): [True: 1.29k, False: 406k]
  |  Branch (260:16): [True: 1.36k, False: 406k]
  |  Branch (260:28): [True: 12.4k, False: 395k]
  |  Branch (260:40): [True: 12.2k, False: 395k]
  |  Branch (260:51): [True: 4.27k, False: 403k]
  |  Branch (260:61): [True: 655, False: 407k]
  ------------------
  261|  32.2k|				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|  32.3k|			default:
  ------------------
  |  Branch (269:4): [True: 32.3k, False: 375k]
  ------------------
  270|  32.3k|#endif
  271|  32.3k|				r = jsmn_parse_primitive(parser, js, tokens, num_tokens);
  272|  32.3k|				if (r < 0) return r;
  ------------------
  |  Branch (272:9): [True: 1.05k, False: 31.2k]
  ------------------
  273|  31.2k|				if (parser->toksuper != -1)
  ------------------
  |  Branch (273:9): [True: 29.2k, False: 2.05k]
  ------------------
  274|  29.2k|					tokens[parser->toksuper].size++;
  275|  31.2k|				break;
  276|       |
  277|       |#ifdef JSMN_STRICT
  278|       |			/* Unexpected char in strict mode */
  279|       |			default:
  280|       |				return JSMN_ERROR_INVAL;
  281|       |#endif
  282|       |
  283|   408k|		}
  284|   408k|	}
  285|       |
  286|   208k|	for (i = parser->toknext - 1; i >= 0; i--) {
  ------------------
  |  Branch (286:32): [True: 206k, False: 1.94k]
  ------------------
  287|       |		/* Unmatched opened object or array */
  288|   206k|		if (tokens[i].start != JSMN_POS_INVALID && tokens[i].end == JSMN_POS_INVALID) {
  ------------------
  |  |   35|   412k|#define JSMN_POS_INVALID ((size_t)SIZE_MAX)
  ------------------
              		if (tokens[i].start != JSMN_POS_INVALID && tokens[i].end == JSMN_POS_INVALID) {
  ------------------
  |  |   35|   206k|#define JSMN_POS_INVALID ((size_t)SIZE_MAX)
  ------------------
  |  Branch (288:7): [True: 206k, False: 0]
  |  Branch (288:46): [True: 178, False: 206k]
  ------------------
  289|    178|			return JSMN_ERROR_PART;
  290|    178|		}
  291|   206k|	}
  292|       |
  293|  1.94k|	return JSMN_SUCCESS;
  294|  2.11k|}
jsmn_init:
  300|  2.31k|void jsmn_init(jsmn_parser *parser) {
  301|  2.31k|	parser->pos = 0;
  302|  2.31k|	parser->end = 0;
  303|  2.31k|	parser->toknext = 0;
  304|  2.31k|	parser->toksuper = -1;
  305|  2.31k|}
jsmn.c:jsmn_alloc_token:
   41|   301k|		jsmntok_t *tokens, unsigned int num_tokens) {
   42|   301k|	jsmntok_t *tok;
   43|   301k|	if ((unsigned int)parser->toknext >= num_tokens) {
  ------------------
  |  Branch (43:6): [True: 10.0k, False: 291k]
  ------------------
   44|  10.0k|		return NULL;
   45|  10.0k|	}
   46|   291k|	tok = &tokens[parser->toknext++];
   47|   291k|	tok->start = tok->end = JSMN_POS_INVALID;
  ------------------
  |  |   35|   291k|#define JSMN_POS_INVALID ((size_t)SIZE_MAX)
  ------------------
   48|   291k|	tok->size = 0;
   49|       |#ifdef JSMN_PARENT_LINKS
   50|       |	tok->parent = -1;
   51|       |#endif
   52|   291k|	return tok;
   53|   301k|}
jsmn.c:jsmn_parse_string:
  117|   109k|		jsmntok_t *tokens, unsigned int num_tokens) {
  118|   109k|	jsmntok_t *token;
  119|       |
  120|   109k|	size_t start = parser->pos;
  121|       |
  122|   109k|	parser->pos++;
  123|       |
  124|       |	/* Skip starting quote */
  125|   305k|	for (; (parser->end > 0 && parser->pos < parser->end) && js[parser->pos] != '\0'; parser->pos++) {
  ------------------
  |  Branch (125:10): [True: 305k, False: 0]
  |  Branch (125:29): [True: 304k, False: 126]
  |  Branch (125:59): [True: 304k, False: 1]
  ------------------
  126|   304k|		char c = js[parser->pos];
  127|       |
  128|       |		/* Quote: end of string */
  129|   304k|		if (c == '\"') {
  ------------------
  |  Branch (129:7): [True: 109k, False: 195k]
  ------------------
  130|   109k|			token = jsmn_alloc_token(parser, tokens, num_tokens);
  131|   109k|			if (token == NULL) {
  ------------------
  |  Branch (131:8): [True: 2.56k, False: 107k]
  ------------------
  132|  2.56k|				parser->pos = start;
  133|  2.56k|				return JSMN_ERROR_NOMEM;
  134|  2.56k|			}
  135|   107k|			jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
  136|       |#ifdef JSMN_PARENT_LINKS
  137|       |			token->parent = parser->toksuper;
  138|       |#endif
  139|   107k|			return JSMN_SUCCESS;
  140|   109k|		}
  141|       |
  142|       |		/* Backslash: Quoted symbol expected */
  143|   195k|		if (c == '\\') {
  ------------------
  |  Branch (143:7): [True: 26.0k, False: 169k]
  ------------------
  144|  26.0k|			parser->pos++;
  145|  26.0k|			if (parser->end > 0 && parser->pos >= parser->end) {
  ------------------
  |  Branch (145:8): [True: 26.0k, False: 0]
  |  Branch (145:27): [True: 5, False: 26.0k]
  ------------------
  146|      5|				parser->pos = start;
  147|      5|				return JSMN_ERROR_INVAL;
  148|      5|			}
  149|  26.0k|			switch (js[parser->pos]) {
  150|       |				/* Allowed escaped symbols */
  151|  7.92k|				case '\"': case '/' : case '\\' : case 'b' :
  ------------------
  |  Branch (151:5): [True: 786, False: 25.3k]
  |  Branch (151:16): [True: 1.50k, False: 24.5k]
  |  Branch (151:27): [True: 4.92k, False: 21.1k]
  |  Branch (151:39): [True: 711, False: 25.3k]
  ------------------
  152|  24.3k|				case 'f' : case 'r' : case 'n'  : case 't' :
  ------------------
  |  Branch (152:5): [True: 1.10k, False: 24.9k]
  |  Branch (152:16): [True: 544, False: 25.5k]
  |  Branch (152:27): [True: 14.0k, False: 12.0k]
  |  Branch (152:39): [True: 773, False: 25.3k]
  ------------------
  153|  24.3k|					break;
  154|       |				/* Allows escaped symbol \uXXXX */
  155|  1.72k|				case 'u':
  ------------------
  |  Branch (155:5): [True: 1.72k, False: 24.3k]
  ------------------
  156|       |					/* TODO */
  157|  1.72k|					break;
  158|       |				/* Unexpected symbol */
  159|      2|				default:
  ------------------
  |  Branch (159:5): [True: 2, False: 26.0k]
  ------------------
  160|      2|					parser->pos = start;
  161|      2|					return JSMN_ERROR_INVAL;
  162|  26.0k|			}
  163|  26.0k|		}
  164|   195k|	}
  165|    127|	parser->pos = start;
  166|    127|	return JSMN_ERROR_PART;
  167|   109k|}
jsmn.c:jsmn_fill_token:
   59|   138k|                            size_t start, size_t end) {
   60|   138k|	token->type = type;
   61|   138k|	token->start = start;
   62|   138k|	token->end = end;
   63|   138k|	token->size = 0;
   64|   138k|}
jsmn.c:jsmn_parse_primitive:
   70|  32.3k|		jsmntok_t *tokens, unsigned int num_tokens) {
   71|  32.3k|	jsmntok_t *token;
   72|  32.3k|	size_t start;
   73|       |
   74|  32.3k|	start = parser->pos;
   75|       |
   76|   101k|	for (; (parser->end > 0 && parser->pos < parser->end) && js[parser->pos] != '\0'; parser->pos++) {
  ------------------
  |  Branch (76:10): [True: 101k, False: 0]
  |  Branch (76:29): [True: 100k, False: 670]
  |  Branch (76:59): [True: 100k, False: 1]
  ------------------
   77|   100k|		switch (js[parser->pos]) {
   78|      0|#ifndef JSMN_STRICT
   79|       |			/* In strict mode primitive must be followed by "," or "}" or "]" */
   80|  5.92k|			case ':':
  ------------------
  |  Branch (80:4): [True: 5.92k, False: 94.9k]
  ------------------
   81|  5.92k|#endif
   82|  20.7k|			case '\t' : case '\r' : case '\n' : case ' ' :
  ------------------
  |  Branch (82:4): [True: 709, False: 100k]
  |  Branch (82:16): [True: 1.02k, False: 99.8k]
  |  Branch (82:28): [True: 12.6k, False: 88.2k]
  |  Branch (82:40): [True: 460, False: 100k]
  ------------------
   83|  31.6k|			case ','  : case ']'  : case '}' :
  ------------------
  |  Branch (83:4): [True: 4.06k, False: 96.7k]
  |  Branch (83:16): [True: 5.61k, False: 95.2k]
  |  Branch (83:28): [True: 1.20k, False: 99.6k]
  ------------------
   84|  31.6k|				goto found;
   85|  69.2k|			default:
  ------------------
  |  Branch (85:4): [True: 69.2k, False: 31.6k]
  ------------------
   86|  69.2k|				break;
   87|   100k|		}
   88|  69.2k|		if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
  ------------------
  |  Branch (88:7): [True: 17, False: 69.1k]
  |  Branch (88:31): [True: 1, False: 69.1k]
  ------------------
   89|     18|			parser->pos = start;
   90|     18|			return JSMN_ERROR_INVAL;
   91|     18|		}
   92|  69.2k|	}
   93|       |#ifdef JSMN_STRICT
   94|       |	/* In strict mode primitive must be followed by a comma/object/array */
   95|       |	parser->pos = start;
   96|       |	return JSMN_ERROR_PART;
   97|       |#endif
   98|       |
   99|  32.2k|found:
  100|  32.2k|	token = jsmn_alloc_token(parser, tokens, num_tokens);
  101|  32.2k|	if (token == NULL) {
  ------------------
  |  Branch (101:6): [True: 1.03k, False: 31.2k]
  ------------------
  102|  1.03k|		parser->pos = start;
  103|  1.03k|		return JSMN_ERROR_NOMEM;
  104|  1.03k|	}
  105|  31.2k|	jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
  106|       |#ifdef JSMN_PARENT_LINKS
  107|       |	token->parent = parser->toksuper;
  108|       |#endif
  109|  31.2k|	parser->pos--;
  110|  31.2k|	return JSMN_SUCCESS;
  111|  32.2k|}

plist_ostep_init:
   55|      2|{
   56|       |    /* init OpenStep stuff */
   57|      2|#ifdef DEBUG
   58|      2|    char *env_debug = getenv("PLIST_OSTEP_DEBUG");
   59|      2|    if (env_debug && !strcmp(env_debug, "1")) {
  ------------------
  |  Branch (59:9): [True: 0, False: 2]
  |  Branch (59:22): [True: 0, False: 0]
  ------------------
   60|      0|        plist_ostep_debug = 1;
   61|      0|    }
   62|      2|#endif
   63|      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|   186k|{
  349|       |    return (plist_t) node_create(NULL, data);
  350|   186k|}
plist_get_data:
  353|  22.2M|{
  354|  22.2M|    if (!node)
  ------------------
  |  Branch (354:9): [True: 0, False: 22.2M]
  ------------------
  355|      0|        return NULL;
  356|  22.2M|    return (plist_data_t)((node_t)node)->data;
  357|  22.2M|}
plist_new_plist_data:
  360|   186k|{
  361|   186k|    return (plist_data_t) calloc(1, sizeof(struct plist_data_s));
  362|   186k|}
plist_free_data:
  421|   186k|{
  422|   186k|    if (!data) return;
  ------------------
  |  Branch (422:9): [True: 0, False: 186k]
  ------------------
  423|   186k|    _plist_free_data(data);
  424|   186k|    free(data);
  425|   186k|}
plist_new_dict:
  528|  12.1k|{
  529|  12.1k|    plist_data_t data = plist_new_plist_data();
  530|  12.1k|    if (!data) {
  ------------------
  |  Branch (530:9): [True: 0, False: 12.1k]
  ------------------
  531|      0|        PLIST_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  532|      0|        return NULL;
  533|      0|    }
  534|  12.1k|    data->type = PLIST_DICT;
  535|  12.1k|    return plist_new_node(data);
  536|  12.1k|}
plist_new_array:
  539|  53.8k|{
  540|  53.8k|    plist_data_t data = plist_new_plist_data();
  541|  53.8k|    if (!data) {
  ------------------
  |  Branch (541:9): [True: 0, False: 53.8k]
  ------------------
  542|      0|        PLIST_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  543|      0|        return NULL;
  544|      0|    }
  545|  53.8k|    data->type = PLIST_ARRAY;
  546|  53.8k|    return plist_new_node(data);
  547|  53.8k|}
plist_new_bool:
  589|  6.71k|{
  590|  6.71k|    plist_data_t data = plist_new_plist_data();
  591|  6.71k|    if (!data) {
  ------------------
  |  Branch (591:9): [True: 0, False: 6.71k]
  ------------------
  592|      0|        PLIST_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  593|      0|        return NULL;
  594|      0|    }
  595|  6.71k|    data->type = PLIST_BOOLEAN;
  596|  6.71k|    data->boolval = val;
  597|  6.71k|    data->length = sizeof(uint8_t);
  598|  6.71k|    return plist_new_node(data);
  599|  6.71k|}
plist_new_int:
  615|  3.96k|{
  616|  3.96k|    plist_data_t data = plist_new_plist_data();
  617|  3.96k|    if (!data) {
  ------------------
  |  Branch (617:9): [True: 0, False: 3.96k]
  ------------------
  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.96k|    data->type = PLIST_INT;
  622|  3.96k|    data->intval = val;
  623|  3.96k|    data->length = sizeof(uint64_t);
  624|  3.96k|    return plist_new_node(data);
  625|  3.96k|}
plist_new_real:
  641|  2.00k|{
  642|  2.00k|    plist_data_t data = plist_new_plist_data();
  643|  2.00k|    if (!data) {
  ------------------
  |  Branch (643:9): [True: 0, False: 2.00k]
  ------------------
  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.00k|    data->type = PLIST_REAL;
  648|  2.00k|    data->realval = val;
  649|  2.00k|    data->length = sizeof(double);
  650|  2.00k|    return plist_new_node(data);
  651|  2.00k|}
plist_free:
  713|  9.88k|{
  714|  9.88k|    if (plist)
  ------------------
  |  Branch (714:9): [True: 9.03k, False: 847]
  ------------------
  715|  9.03k|    {
  716|  9.03k|        plist_free_node((node_t)plist);
  717|  9.03k|    }
  718|  9.88k|}
plist_array_append_item:
 1080|  52.4k|{
 1081|  52.4k|    if (!PLIST_IS_ARRAY(node) || !item) {
  ------------------
  |  | 1195|  52.4k|    #define PLIST_IS_ARRAY(__plist)   _PLIST_IS_TYPE(__plist, ARRAY)
  |  |  ------------------
  |  |  |  | 1183|   104k|    #define _PLIST_IS_TYPE(__plist, __plist_type) (__plist && (plist_get_node_type(__plist) == PLIST_##__plist_type))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1183:52): [True: 52.4k, False: 0]
  |  |  |  |  |  Branch (1183:63): [True: 52.4k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1081:34): [True: 0, False: 52.4k]
  ------------------
 1082|      0|        PLIST_ERR("invalid argument passed to %s (node=%p, item=%p)\n", __func__, node, item);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1083|      0|        return;
 1084|      0|    }
 1085|  52.4k|    node_t it = (node_t)item;
 1086|  52.4k|    if (it->parent != NULL) {
  ------------------
  |  Branch (1086:9): [True: 0, False: 52.4k]
  ------------------
 1087|      0|        assert(it->parent == NULL && "item already has a parent; use plist_copy() or detach first");
  ------------------
  |  Branch (1087:9): [True: 0, False: 0]
  |  Branch (1087:9): [True: 0, False: 0]
  |  Branch (1087:9): [True: 0, False: 0]
  |  Branch (1087:9): [True: 0, False: 0]
  ------------------
 1088|      0|        PLIST_ERR("%s: item already has a parent; use plist_copy() or detach first\n", __func__);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
 1089|      0|        return;
 1090|      0|    }
 1091|       |
 1092|  52.4k|    int r = node_attach((node_t)node, (node_t)item);
 1093|  52.4k|    if (r != NODE_ERR_SUCCESS) {
  ------------------
  |  |   36|  52.4k|#define NODE_ERR_SUCCESS       0
  ------------------
  |  Branch (1093:9): [True: 2, False: 52.4k]
  ------------------
 1094|      2|        PLIST_ERR("%s: failed to append item (err=%d)\n", __func__, r);
  ------------------
  |  |   57|      2|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 2]
  |  |  ------------------
  ------------------
 1095|      2|        return;
 1096|      2|    }
 1097|  52.4k|    _plist_array_post_insert(node, item, -1);
 1098|  52.4k|}
plist_dict_get_item:
 1275|  64.6k|{
 1276|  64.6k|    plist_t ret = NULL;
 1277|  64.6k|    if (!PLIST_IS_DICT(node) || !key) {
  ------------------
  |  | 1197|  64.6k|    #define PLIST_IS_DICT(__plist)    _PLIST_IS_TYPE(__plist, DICT)
  |  |  ------------------
  |  |  |  | 1183|   129k|    #define _PLIST_IS_TYPE(__plist, __plist_type) (__plist && (plist_get_node_type(__plist) == PLIST_##__plist_type))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1183:52): [True: 64.6k, False: 0]
  |  |  |  |  |  Branch (1183:63): [True: 64.6k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1277:33): [True: 0, False: 64.6k]
  ------------------
 1278|      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]
  |  |  ------------------
  ------------------
 1279|      0|        return NULL;
 1280|      0|    }
 1281|  64.6k|    plist_data_t data = plist_get_data(node);
 1282|  64.6k|    if (!data) {
  ------------------
  |  Branch (1282:9): [True: 0, False: 64.6k]
  ------------------
 1283|      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]
  |  |  ------------------
  ------------------
 1284|      0|        return NULL;
 1285|      0|    }
 1286|  64.6k|    size_t keylen = strlen(key);
 1287|  64.6k|    hashtable_t *ht = (hashtable_t*)data->hashtable;
 1288|  64.6k|    if (ht) {
  ------------------
  |  Branch (1288:9): [True: 953, False: 63.6k]
  ------------------
 1289|    953|        struct plist_data_s sdata = { 0 };
 1290|    953|        sdata.strval = (char*)key;
 1291|    953|        sdata.length = keylen;
 1292|    953|        return (plist_t)hash_table_lookup(ht, &sdata);
 1293|  63.6k|    } else {
 1294|  63.6k|        plist_t k = NULL;
 1295|  7.32M|        for (k = (plist_t)node_first_child((node_t)node); k; ) {
  ------------------
  |  Branch (1295:59): [True: 7.26M, False: 60.2k]
  ------------------
 1296|  7.26M|            plist_t v = (plist_t)node_next_sibling(k);
 1297|  7.26M|            if (!v) break;
  ------------------
  |  Branch (1297:17): [True: 0, False: 7.26M]
  ------------------
 1298|  7.26M|            data = plist_get_data(k);
 1299|  7.26M|            assert(PLIST_IS_KEY(k));
  ------------------
  |  Branch (1299:13): [True: 0, False: 7.26M]
  |  Branch (1299:13): [True: 0, False: 0]
  |  Branch (1299:13): [True: 7.26M, False: 0]
  |  Branch (1299:13): [True: 7.26M, False: 0]
  ------------------
 1300|  7.26M|            if (!PLIST_IS_KEY(k) || !data || !data->strval) {
  ------------------
  |  | 1203|  7.26M|    #define PLIST_IS_KEY(__plist)     _PLIST_IS_TYPE(__plist, KEY)
  |  |  ------------------
  |  |  |  | 1183|  14.5M|    #define _PLIST_IS_TYPE(__plist, __plist_type) (__plist && (plist_get_node_type(__plist) == PLIST_##__plist_type))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1183:52): [True: 7.26M, False: 0]
  |  |  |  |  |  Branch (1183:63): [True: 7.26M, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1300:37): [True: 0, False: 7.26M]
  |  Branch (1300:46): [True: 0, False: 7.26M]
  ------------------
 1301|      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]
  |  |  ------------------
  ------------------
 1302|      0|                break;
 1303|      0|            }
 1304|  7.26M|            if (data->length == keylen && !memcmp(key, data->strval, keylen+1)) {
  ------------------
  |  Branch (1304:17): [True: 3.81M, False: 3.44M]
  |  Branch (1304:43): [True: 3.46k, False: 3.81M]
  ------------------
 1305|  3.46k|                ret = v;
 1306|  3.46k|                break;
 1307|  3.46k|            }
 1308|  7.25M|            k = node_next_sibling(v);
 1309|  7.25M|        }
 1310|  63.6k|    }
 1311|  63.6k|    return ret;
 1312|  64.6k|}
plist_dict_set_item:
 1315|  64.6k|{
 1316|  64.6k|    if (!PLIST_IS_DICT(node) || !key || !item) {
  ------------------
  |  | 1197|  64.6k|    #define PLIST_IS_DICT(__plist)    _PLIST_IS_TYPE(__plist, DICT)
  |  |  ------------------
  |  |  |  | 1183|   129k|    #define _PLIST_IS_TYPE(__plist, __plist_type) (__plist && (plist_get_node_type(__plist) == PLIST_##__plist_type))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1183:52): [True: 64.6k, False: 0]
  |  |  |  |  |  Branch (1183:63): [True: 64.6k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
  |  Branch (1316:33): [True: 0, False: 64.6k]
  |  Branch (1316:41): [True: 0, False: 64.6k]
  ------------------
 1317|      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]
  |  |  ------------------
  ------------------
 1318|      0|        return;
 1319|      0|    }
 1320|  64.6k|    node_t it = (node_t)item;
 1321|  64.6k|    if (it->parent != NULL) {
  ------------------
  |  Branch (1321:9): [True: 0, False: 64.6k]
  ------------------
 1322|      0|        assert(it->parent == NULL && "item already has a parent");
  ------------------
  |  Branch (1322:9): [True: 0, False: 0]
  |  Branch (1322:9): [True: 0, False: 0]
  |  Branch (1322:9): [True: 0, False: 0]
  |  Branch (1322:9): [True: 0, False: 0]
  ------------------
 1323|      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]
  |  |  ------------------
  ------------------
 1324|      0|        return;
 1325|      0|    }
 1326|       |
 1327|  64.6k|    hashtable_t *ht = (hashtable_t*)((plist_data_t)((node_t)node)->data)->hashtable;
 1328|       |
 1329|  64.6k|    plist_t old_item = plist_dict_get_item(node, key);
 1330|  64.6k|    plist_t key_node = NULL;
 1331|       |
 1332|  64.6k|    if (old_item) {
  ------------------
  |  Branch (1332:9): [True: 4.02k, False: 60.6k]
  ------------------
 1333|       |        // --- REPLACE EXISTING VALUE ---
 1334|  4.02k|        node_t old_val = (node_t)old_item;
 1335|  4.02k|        node_t old_key = node_prev_sibling(old_val);
 1336|  4.02k|        if (!old_key) {
  ------------------
  |  Branch (1336:13): [True: 0, False: 4.02k]
  ------------------
 1337|      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]
  |  |  ------------------
  ------------------
 1338|      0|            return;
 1339|      0|        }
 1340|  4.02k|        if (!PLIST_IS_KEY((plist_t)old_key)) {
  ------------------
  |  | 1203|  4.02k|    #define PLIST_IS_KEY(__plist)     _PLIST_IS_TYPE(__plist, KEY)
  |  |  ------------------
  |  |  |  | 1183|  4.02k|    #define _PLIST_IS_TYPE(__plist, __plist_type) (__plist && (plist_get_node_type(__plist) == PLIST_##__plist_type))
  |  |  |  |  ------------------
  |  |  |  |  |  Branch (1183:52): [True: 4.02k, False: 0]
  |  |  |  |  |  Branch (1183:63): [True: 4.02k, False: 0]
  |  |  |  |  ------------------
  |  |  ------------------
  ------------------
 1341|      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]
  |  |  ------------------
  ------------------
 1342|      0|            return;
 1343|      0|        }
 1344|       |
 1345|       |        // detach old value (do NOT free yet)
 1346|  4.02k|        int idx = node_detach((node_t)node, old_val);
 1347|  4.02k|        if (idx < 0) {
  ------------------
  |  Branch (1347:13): [True: 0, False: 4.02k]
  ------------------
 1348|      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]
  |  |  ------------------
  ------------------
 1349|      0|            return;
 1350|      0|        }
 1351|       |
 1352|       |        // insert new value at same position
 1353|  4.02k|        int r = node_insert((node_t)node, (unsigned)idx, (node_t)item);
 1354|  4.02k|        if (r != NODE_ERR_SUCCESS) {
  ------------------
  |  |   36|  4.02k|#define NODE_ERR_SUCCESS       0
  ------------------
  |  Branch (1354:13): [True: 2, False: 4.01k]
  ------------------
 1355|       |            // rollback: reinsert old value
 1356|      2|            int rb = node_insert((node_t)node, (unsigned)idx, old_val);
 1357|      2|            if (rb == NODE_ERR_SUCCESS && ht) {
  ------------------
  |  |   36|      4|#define NODE_ERR_SUCCESS       0
  ------------------
  |  Branch (1357:17): [True: 2, False: 0]
  |  Branch (1357:43): [True: 1, False: 1]
  ------------------
 1358|      1|                hash_table_insert(ht, ((node_t)old_key)->data, old_item);
 1359|      1|            }
 1360|      2|            PLIST_ERR("%s: failed to replace 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]
  |  |  ------------------
  ------------------
 1361|      2|            return;
 1362|      2|        }
 1363|  4.01k|        key_node = old_key;
 1364|       |
 1365|       |        // update hash table
 1366|  4.01k|        if (ht) {
  ------------------
  |  Branch (1366:13): [True: 559, False: 3.46k]
  ------------------
 1367|    559|            hash_table_insert(ht, (plist_data_t)((node_t)key_node)->data, item);
 1368|    559|        }
 1369|       |
 1370|       |        // now it’s safe to free old value
 1371|  4.01k|        plist_free_node(old_val);
 1372|  60.6k|    } else {
 1373|       |        // --- INSERT NEW KEY/VALUE PAIR ---
 1374|  60.6k|        key_node = plist_new_key(key);
 1375|  60.6k|        if (!key_node) return;
  ------------------
  |  Branch (1375:13): [True: 0, False: 60.6k]
  ------------------
 1376|       |
 1377|  60.6k|        int r = node_attach((node_t)node, (node_t)key_node);
 1378|  60.6k|        if (r != NODE_ERR_SUCCESS) {
  ------------------
  |  |   36|  60.6k|#define NODE_ERR_SUCCESS       0
  ------------------
  |  Branch (1378:13): [True: 0, False: 60.6k]
  ------------------
 1379|      0|            plist_free_node((node_t)key_node);
 1380|      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]
  |  |  ------------------
  ------------------
 1381|      0|            return;
 1382|      0|        }
 1383|  60.6k|        r = node_attach((node_t)node, (node_t)item);
 1384|  60.6k|        if (r != NODE_ERR_SUCCESS) {
  ------------------
  |  |   36|  60.6k|#define NODE_ERR_SUCCESS       0
  ------------------
  |  Branch (1384:13): [True: 3, False: 60.6k]
  ------------------
 1385|       |            // rollback key insertion
 1386|      3|            node_detach((node_t)node, (node_t)key_node);
 1387|      3|            plist_free_node((node_t)key_node);
 1388|      3|            PLIST_ERR("%s: failed to attach 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]
  |  |  ------------------
  ------------------
 1389|      3|            return;
 1390|      3|        }
 1391|       |
 1392|  60.6k|        if (ht) {
  ------------------
  |  Branch (1392:13): [True: 392, False: 60.2k]
  ------------------
 1393|       |            // store pointer to item in hash table
 1394|    392|            hash_table_insert(ht, (plist_data_t)((node_t)key_node)->data, item);
 1395|  60.2k|        } else if (((node_t)node)->count > 500) {
  ------------------
  |  Branch (1395:20): [True: 224, False: 59.9k]
  ------------------
 1396|       |            // make new hash table
 1397|    224|            ht = hash_table_new(dict_key_hash, dict_key_compare, NULL);
 1398|       |            // calculate the hashes for all entries we have so far
 1399|    224|            plist_t current = NULL;
 1400|    224|            for (current = (plist_t)node_first_child((node_t)node);
 1401|  56.4k|                 ht && current;
  ------------------
  |  Branch (1401:18): [True: 56.4k, False: 0]
  |  Branch (1401:24): [True: 56.2k, False: 224]
  ------------------
 1402|  56.2k|                 current = (plist_t)node_next_sibling(node_next_sibling((node_t)current)))
 1403|  56.2k|            {
 1404|  56.2k|                hash_table_insert(ht, ((node_t)current)->data, node_next_sibling((node_t)current));
 1405|  56.2k|            }
 1406|    224|            ((plist_data_t)((node_t)node)->data)->hashtable = ht;
 1407|    224|        }
 1408|  60.6k|    }
 1409|  64.6k|}
plist_get_node_type:
 1732|  14.7M|{
 1733|  14.7M|    if (node)
  ------------------
  |  Branch (1733:9): [True: 14.7M, False: 0]
  ------------------
 1734|  14.7M|    {
 1735|  14.7M|        plist_data_t data = plist_get_data(node);
 1736|  14.7M|        if (data)
  ------------------
  |  Branch (1736:13): [True: 14.7M, False: 0]
  ------------------
 1737|  14.7M|            return data->type;
 1738|  14.7M|    }
 1739|      0|    return PLIST_NONE;
 1740|  14.7M|}
plist.c:_plist_free_data:
  390|   186k|{
  391|   186k|    if (!data) return;
  ------------------
  |  Branch (391:9): [True: 0, False: 186k]
  ------------------
  392|   186k|    switch (data->type) {
  393|  60.6k|        case PLIST_KEY:
  ------------------
  |  Branch (393:9): [True: 60.6k, False: 126k]
  ------------------
  394|  94.1k|        case PLIST_STRING:
  ------------------
  |  Branch (394:9): [True: 33.5k, False: 153k]
  ------------------
  395|  94.1k|            free(data->strval);
  396|  94.1k|            data->strval = NULL;
  397|  94.1k|            break;
  398|      0|        case PLIST_DATA:
  ------------------
  |  Branch (398:9): [True: 0, False: 186k]
  ------------------
  399|      0|            free(data->buff);
  400|      0|            data->buff = NULL;
  401|      0|            break;
  402|  53.8k|        case PLIST_ARRAY:
  ------------------
  |  Branch (402:9): [True: 53.8k, False: 132k]
  ------------------
  403|  53.8k|            ptr_array_free((ptrarray_t*)data->hashtable);
  404|  53.8k|            data->hashtable = NULL;
  405|  53.8k|            break;
  406|  12.1k|        case PLIST_DICT: {
  ------------------
  |  Branch (406:9): [True: 12.1k, False: 174k]
  ------------------
  407|  12.1k|            hashtable_t *ht = (hashtable_t*)data->hashtable;
  408|       |            // PLIST_DICT hashtables must not own/free values; values are freed via node tree.
  409|  12.1k|            assert(!ht || ht->free_func == NULL);
  ------------------
  |  Branch (409:13): [True: 12.1k, False: 0]
  |  Branch (409:13): [True: 0, False: 0]
  |  Branch (409:13): [True: 11.9k, False: 224]
  |  Branch (409:13): [True: 224, False: 0]
  ------------------
  410|  12.1k|            if (ht) ht->free_func = NULL;
  ------------------
  |  Branch (410:17): [True: 224, False: 11.9k]
  ------------------
  411|  12.1k|            hash_table_destroy(ht);
  412|  12.1k|            data->hashtable = NULL;
  413|  12.1k|            break;
  414|  12.1k|        }
  415|  26.6k|        default:
  ------------------
  |  Branch (415:9): [True: 26.6k, False: 160k]
  ------------------
  416|  26.6k|            break;
  417|   186k|    }
  418|   186k|}
plist.c:plist_free_node:
  500|  13.0k|{
  501|  13.0k|    if (!root) return NODE_ERR_INVALID_ARG;
  ------------------
  |  |   37|      0|#define NODE_ERR_INVALID_ARG  -1
  ------------------
  |  Branch (501:9): [True: 0, False: 13.0k]
  ------------------
  502|       |
  503|  13.0k|    int root_index = -1;
  504|       |
  505|  13.0k|    if (root->parent) {
  ------------------
  |  Branch (505:9): [True: 0, False: 13.0k]
  ------------------
  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|  13.0k|    int r = plist_free_children(root);
  513|  13.0k|    if (r < 0) {
  ------------------
  |  Branch (513:9): [True: 0, False: 13.0k]
  ------------------
  514|       |        // root is already detached; caller should treat as error.
  515|      0|        return r;
  516|      0|    }
  517|       |
  518|  13.0k|    plist_data_t data = plist_get_data(root);
  519|  13.0k|    plist_free_data(data);
  520|  13.0k|    root->data = NULL;
  521|       |
  522|  13.0k|    node_destroy(root);
  523|       |
  524|  13.0k|    return root_index;
  525|  13.0k|}
plist.c:plist_free_children:
  428|  13.0k|{
  429|  13.0k|    if (!root) return NODE_ERR_INVALID_ARG;
  ------------------
  |  |   37|      0|#define NODE_ERR_INVALID_ARG  -1
  ------------------
  |  Branch (429:9): [True: 0, False: 13.0k]
  ------------------
  430|       |
  431|  13.0k|    if (!node_first_child(root)) {
  ------------------
  |  Branch (431:9): [True: 11.7k, False: 1.28k]
  ------------------
  432|  11.7k|        return NODE_ERR_SUCCESS;
  ------------------
  |  |   36|  11.7k|#define NODE_ERR_SUCCESS       0
  ------------------
  433|  11.7k|    }
  434|       |
  435|  1.28k|    size_t cap = 64, sp = 0;
  436|  1.28k|    node_t *stack = (node_t*)malloc(cap * sizeof(*stack));
  437|  1.28k|    if (!stack) return NODE_ERR_NO_MEM;
  ------------------
  |  |   38|      0|#define NODE_ERR_NO_MEM       -2
  ------------------
  |  Branch (437:9): [True: 0, False: 1.28k]
  ------------------
  438|       |
  439|       |    // Push *direct* children onto the stack, detached from root.
  440|   138k|    for (;;) {
  441|   138k|        node_t ch = node_first_child(root);
  442|   138k|        if (!ch) break;
  ------------------
  |  Branch (442:13): [True: 1.28k, False: 137k]
  ------------------
  443|       |
  444|   137k|        int di = node_detach(root, ch);
  445|   137k|        if (di < 0) {
  ------------------
  |  Branch (445:13): [True: 0, False: 137k]
  ------------------
  446|      0|            free(stack);
  447|      0|            return di;
  448|      0|        }
  449|       |
  450|   137k|        if (sp == cap) {
  ------------------
  |  Branch (450:13): [True: 1.83k, False: 135k]
  ------------------
  451|  1.83k|            cap += 64;
  452|  1.83k|            node_t *tmp = (node_t*)realloc(stack, cap * sizeof(*stack));
  453|  1.83k|            if (!tmp) {
  ------------------
  |  Branch (453:17): [True: 0, False: 1.83k]
  ------------------
  454|      0|                free(stack);
  455|      0|                return NODE_ERR_NO_MEM;
  ------------------
  |  |   38|      0|#define NODE_ERR_NO_MEM       -2
  ------------------
  456|      0|            }
  457|  1.83k|            stack = tmp;
  458|  1.83k|        }
  459|   137k|        stack[sp++] = ch;
  460|   137k|    }
  461|       |
  462|       |    // Now free the detached subtree nodes (and their descendants).
  463|   211k|    while (sp) {
  ------------------
  |  Branch (463:12): [True: 210k, False: 1.28k]
  ------------------
  464|   210k|        node_t node = stack[sp - 1];
  465|   210k|        node_t ch = node_first_child(node);
  466|   210k|        if (ch) {
  ------------------
  |  Branch (466:13): [True: 36.5k, False: 173k]
  ------------------
  467|  36.5k|            int di = node_detach(node, ch);
  468|  36.5k|            if (di < 0) {
  ------------------
  |  Branch (468:17): [True: 0, False: 36.5k]
  ------------------
  469|      0|                free(stack);
  470|      0|                return di;
  471|      0|            }
  472|       |
  473|  36.5k|            if (sp == cap) {
  ------------------
  |  Branch (473:17): [True: 252, False: 36.2k]
  ------------------
  474|    252|                cap += 64;
  475|    252|                node_t *tmp = (node_t*)realloc(stack, cap * sizeof(*stack));
  476|    252|                if (!tmp) {
  ------------------
  |  Branch (476:21): [True: 0, False: 252]
  ------------------
  477|      0|                    free(stack);
  478|      0|                    return NODE_ERR_NO_MEM;
  ------------------
  |  |   38|      0|#define NODE_ERR_NO_MEM       -2
  ------------------
  479|      0|                }
  480|    252|                stack = tmp;
  481|    252|            }
  482|  36.5k|            stack[sp++] = ch;
  483|  36.5k|            continue;
  484|  36.5k|        }
  485|       |
  486|   173k|        plist_data_t data = plist_get_data(node);
  487|   173k|        plist_free_data(data);
  488|   173k|        node->data = NULL;
  489|       |
  490|   173k|        node_destroy(node);
  491|       |
  492|   173k|        sp--;
  493|   173k|    }
  494|       |
  495|  1.28k|    free(stack);
  496|  1.28k|    return NODE_ERR_SUCCESS;
  ------------------
  |  |   36|  1.28k|#define NODE_ERR_SUCCESS       0
  ------------------
  497|  1.28k|}
plist.c:_plist_array_post_insert:
  989|  52.4k|{
  990|  52.4k|    ptrarray_t *pa = (ptrarray_t*)((plist_data_t)((node_t)node)->data)->hashtable;
  991|  52.4k|    if (pa) {
  ------------------
  |  Branch (991:9): [True: 10.7k, False: 41.7k]
  ------------------
  992|       |        /* store pointer to item in array */
  993|  10.7k|        ptr_array_insert(pa, item, n);
  994|  10.7k|        return;
  995|  10.7k|    }
  996|       |
  997|  41.7k|    if (((node_t)node)->count > 100) {
  ------------------
  |  Branch (997:9): [True: 117, False: 41.6k]
  ------------------
  998|       |       /* make new lookup array */
  999|    117|       pa = ptr_array_new(128);
 1000|    117|       plist_t current = NULL;
 1001|    117|       for (current = (plist_t)node_first_child((node_t)node);
 1002|  11.9k|            pa && current;
  ------------------
  |  Branch (1002:13): [True: 11.9k, False: 0]
  |  Branch (1002:19): [True: 11.8k, False: 117]
  ------------------
 1003|  11.8k|            current = (plist_t)node_next_sibling((node_t)current))
 1004|  11.8k|       {
 1005|  11.8k|           ptr_array_add(pa, current);
 1006|  11.8k|       }
 1007|    117|       ((plist_data_t)((node_t)node)->data)->hashtable = pa;
 1008|    117|    }
 1009|  41.7k|}
plist.c:plist_new_key:
  551|  60.6k|{
  552|  60.6k|    plist_data_t data = plist_new_plist_data();
  553|  60.6k|    if (!data) {
  ------------------
  |  Branch (553:9): [True: 0, False: 60.6k]
  ------------------
  554|      0|        PLIST_ERR("%s: failed to allocate plist data\n", __func__);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  555|      0|        return NULL;
  556|      0|    }
  557|  60.6k|    data->type = PLIST_KEY;
  558|  60.6k|    data->strval = strdup(val);
  559|  60.6k|    if (!data->strval) {
  ------------------
  |  Branch (559:9): [True: 0, False: 60.6k]
  ------------------
  560|      0|        plist_free_data(data);
  561|      0|        PLIST_ERR("%s: strdup failed\n", __func__);
  ------------------
  |  |   57|      0|#define PLIST_ERR(...) if (plist_debug > 0) { fprintf(stderr, "libplist ERROR: " __VA_ARGS__); }
  |  |  ------------------
  |  |  |  Branch (57:28): [True: 0, False: 0]
  |  |  ------------------
  ------------------
  562|      0|        return NULL;
  563|  60.6k|    } else {
  564|  60.6k|        data->length = strlen(val);
  565|  60.6k|    }
  566|  60.6k|    return plist_new_node(data);
  567|  60.6k|}
plist.c:dict_key_hash:
  365|  58.1k|{
  366|  58.1k|    plist_data_t keydata = (plist_data_t)data;
  367|  58.1k|    unsigned int hash = 5381;
  368|  58.1k|    size_t i;
  369|  58.1k|    char *str = keydata->strval;
  370|   156k|    for (i = 0; i < keydata->length; str++, i++) {
  ------------------
  |  Branch (370:17): [True: 98.7k, False: 58.1k]
  ------------------
  371|  98.7k|        hash = ((hash << 5) + hash) + *str;
  372|  98.7k|    }
  373|  58.1k|    return hash;
  374|  58.1k|}
plist.c:dict_key_compare:
  377|  3.44k|{
  378|  3.44k|    plist_data_t data_a = (plist_data_t)a;
  379|  3.44k|    plist_data_t data_b = (plist_data_t)b;
  380|  3.44k|    if (data_a->strval == NULL || data_b->strval == NULL) {
  ------------------
  |  Branch (380:9): [True: 0, False: 3.44k]
  |  Branch (380:35): [True: 0, False: 3.44k]
  ------------------
  381|      0|        return FALSE;
  ------------------
  |  |   32|      0|#define FALSE 0
  ------------------
  382|      0|    }
  383|  3.44k|    if (data_a->length != data_b->length) {
  ------------------
  |  Branch (383:9): [True: 1.68k, False: 1.75k]
  ------------------
  384|  1.68k|        return FALSE;
  ------------------
  |  |   32|  1.68k|#define FALSE 0
  ------------------
  385|  1.68k|    }
  386|  1.75k|    return (strcmp(data_a->strval, data_b->strval) == 0) ? TRUE : FALSE;
  ------------------
  |  |   28|  1.12k|#define TRUE 1
  ------------------
                  return (strcmp(data_a->strval, data_b->strval) == 0) ? TRUE : FALSE;
  ------------------
  |  |   32|    636|#define FALSE 0
  ------------------
  |  Branch (386:12): [True: 1.12k, False: 636]
  ------------------
  387|  3.44k|}

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

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

