Branch Coverage

TreeRBXS.xs
Criterion Covered Total %
branch 1098 1764 62.2


line true false branch
41 0 23 if (!sv) return false;
42 0 23 if (SvMAGICAL(sv))
44 0 23 if (SvIOK(sv) || SvUOK(sv))
0 0 if (SvIOK(sv) || SvUOK(sv))
46 0 0 if (SvNOK(sv) && (SvNV(sv) == (NV)(IV)SvNV(sv)))
0 0 if (SvNOK(sv) && (SvNV(sv) == (NV)(IV)SvNV(sv)))
48 0 0 if (SvPOK(sv)) {
51 0 0 if (len == 0 || !((str[0] >= '0' && str[0] <= '9') || str[0] == '-' || str[0] == '+'))
0 0 if (len == 0 || !((str[0] >= '0' && str[0] <= '9') || str[0] == '-' || str[0] == '+'))
0 0 if (len == 0 || !((str[0] >= '0' && str[0] <= '9') || str[0] == '-' || str[0] == '+'))
0 0 if (len == 0 || !((str[0] >= '0' && str[0] <= '9') || str[0] == '-' || str[0] == '+'))
0 0 if (len == 0 || !((str[0] >= '0' && str[0] <= '9') || str[0] == '-' || str[0] == '+'))
53 0 0 while (--len > 0) {
54 0 0 if (str[len] < '0' || str[len] > '9')
0 0 if (str[len] < '0' || str[len] > '9')
65 16 8 if (SvIOK(type_sv)) {
67 16 0 if (key_type < 1 || key_type > KEY_TYPE_MAX)
0 16 if (key_type < 1 || key_type > KEY_TYPE_MAX)
70 8 0 else if (SvPOK(type_sv)) {
73 2 6 if (len > 9 && foldEQ(str, "KEY_TYPE_", 9)) {
2 0 if (len > 9 && foldEQ(str, "KEY_TYPE_", 9)) {
77 7 0 key_type= (len == 3 && foldEQ(str, "ANY", 3))? KEY_TYPE_ANY
78 7 1 : (len == 5 && foldEQ(str, "CLAIM", 5))? KEY_TYPE_CLAIM
0 8 : (len == 5 && foldEQ(str, "CLAIM", 5))? KEY_TYPE_CLAIM
0 0 : (len == 5 && foldEQ(str, "CLAIM", 5))? KEY_TYPE_CLAIM
79 7 1 : (len == 3 && foldEQ(str, "INT", 3))? KEY_TYPE_INT
0 7 : (len == 3 && foldEQ(str, "INT", 3))? KEY_TYPE_INT
80 0 1 : (len == 5 && foldEQ(str, "FLOAT", 5))? KEY_TYPE_FLOAT
0 0 : (len == 5 && foldEQ(str, "FLOAT", 5))? KEY_TYPE_FLOAT
81 1 0 : (len == 4 && foldEQ(str, "BSTR", 4))? KEY_TYPE_BSTR
0 1 : (len == 4 && foldEQ(str, "BSTR", 4))? KEY_TYPE_BSTR
82 0 0 : (len == 4 && foldEQ(str, "USTR", 4))? KEY_TYPE_USTR
0 0 : (len == 4 && foldEQ(str, "USTR", 4))? KEY_TYPE_USTR
128 8 48 if (SvROK(cmp_sv) && SvTYPE(SvRV(cmp_sv)) == SVt_PVCV)
8 0 if (SvROK(cmp_sv) && SvTYPE(SvRV(cmp_sv)) == SVt_PVCV)
130 28 20 else if (SvIOK(cmp_sv)) {
132 28 0 cmp_id= (i < 1 || i > CMP_MAX || i == CMP_SUB)? -1 : (int) i;
28 0 cmp_id= (i < 1 || i > CMP_MAX || i == CMP_SUB)? -1 : (int) i;
28 0 cmp_id= (i < 1 || i > CMP_MAX || i == CMP_SUB)? -1 : (int) i;
134 20 0 else if (SvPOK(cmp_sv)) {
137 10 10 if (len > 4 && foldEQ(str, "CMP_", 4)) {
1 9 if (len > 4 && foldEQ(str, "CMP_", 4)) {
141 1 9 cmp_id= (len == 3 && foldEQ(str, "INT", 3))? CMP_INT
142 10 10 : (len == 3 && foldEQ(str, "STR", 3))? CMP_STR
0 1 : (len == 3 && foldEQ(str, "STR", 3))? CMP_STR
143 1 10 : (len == 4 && foldEQ(str, "UTF8", 4))? CMP_STR // back-compat name
0 0 : (len == 4 && foldEQ(str, "UTF8", 4))? CMP_STR // back-compat name
144 0 10 : (len == 4 && foldEQ(str, "PERL", 4))? CMP_PERL
0 0 : (len == 4 && foldEQ(str, "PERL", 4))? CMP_PERL
145 0 10 : (len == 5 && foldEQ(str, "FLOAT", 5))? CMP_FLOAT
0 1 : (len == 5 && foldEQ(str, "FLOAT", 5))? CMP_FLOAT
146 1 9 : (len == 6 && foldEQ(str, "MEMCMP", 6))? CMP_MEMCMP
0 0 : (len == 6 && foldEQ(str, "MEMCMP", 6))? CMP_MEMCMP
147 0 9 : (len == 8 && foldEQ(str, "FOLDCASE", 8))? CMP_FOLDCASE
2 5 : (len == 8 && foldEQ(str, "FOLDCASE", 8))? CMP_FOLDCASE
148 7 2 : (len == 8 && foldEQ(str, "NUMSPLIT", 8))? CMP_NUMSPLIT
0 2 : (len == 8 && foldEQ(str, "NUMSPLIT", 8))? CMP_NUMSPLIT
149 2 2 : (len ==17 && foldEQ(str, "NUMSPLIT_FOLDCASE", 17))? CMP_NUMSPLIT_FOLDCASE
2 0 : (len ==17 && foldEQ(str, "NUMSPLIT_FOLDCASE", 17))? CMP_NUMSPLIT_FOLDCASE
151 2 0 : -1;
185 61 0 if (SvIOK(mode_sv)) {
187 61 0 mode= (i < 0 || i > GET_MAX)? -1 : (int) i;
61 0 mode= (i < 0 || i > GET_MAX)? -1 : (int) i;
188 0 0 } else if (SvPOK(mode_sv)) {
191 0 0 if (len > 4 && foldEQ(mode_str, "GET_", 4)) {
0 0 if (len > 4 && foldEQ(mode_str, "GET_", 4)) {
197 0 0 case '<': mode= len == 1? GET_LT : len == 2 && mode_str[1] == '='? GET_LE : -1; break;
0 0 case '<': mode= len == 1? GET_LT : len == 2 && mode_str[1] == '='? GET_LE : -1; break;
0 0 case '<': mode= len == 1? GET_LT : len == 2 && mode_str[1] == '='? GET_LE : -1; break;
198 0 0 case '>': mode= len == 1? GET_GT : len == 2 && mode_str[1] == '='? GET_GE : -1; break;
0 0 case '>': mode= len == 1? GET_GT : len == 2 && mode_str[1] == '='? GET_GE : -1; break;
0 0 case '>': mode= len == 1? GET_GT : len == 2 && mode_str[1] == '='? GET_GE : -1; break;
199 0 0 case '=': mode= len == 2 && mode_str[1] == '='? GET_EQ : -1; break;
0 0 case '=': mode= len == 2 && mode_str[1] == '='? GET_EQ : -1; break;
200 0 0 case '-': mode= len == 2 && mode_str[1] == '-'? GET_PREV : -1; break;
0 0 case '-': mode= len == 2 && mode_str[1] == '-'? GET_PREV : -1; break;
201 0 0 case '+': mode= len == 2 && mode_str[1] == '+'? GET_NEXT : -1; break;
0 0 case '+': mode= len == 2 && mode_str[1] == '+'? GET_NEXT : -1; break;
203 0 0 mode= len == 2 && (mode_str[1] == 'q' || mode_str[1] == 'Q')? GET_EQ
0 0 mode= len == 2 && (mode_str[1] == 'q' || mode_str[1] == 'Q')? GET_EQ
204 0 0 : len == 7 && foldEQ(mode_str, "EQ_LAST", 7)? GET_EQ_LAST
0 0 : len == 7 && foldEQ(mode_str, "EQ_LAST", 7)? GET_EQ_LAST
205 0 0 : -1;
208 0 0 mode= len == 2 && (mode_str[1] == 't' || mode_str[1] == 'T')? GET_GT
0 0 mode= len == 2 && (mode_str[1] == 't' || mode_str[1] == 'T')? GET_GT
209 0 0 : len == 2 && (mode_str[1] == 'e' || mode_str[1] == 'E')? GET_GE
0 0 : len == 2 && (mode_str[1] == 'e' || mode_str[1] == 'E')? GET_GE
0 0 : len == 2 && (mode_str[1] == 'e' || mode_str[1] == 'E')? GET_GE
210 0 0 : -1;
213 0 0 mode= len == 2 && (mode_str[1] == 't' || mode_str[1] == 'T')? GET_LT
0 0 mode= len == 2 && (mode_str[1] == 't' || mode_str[1] == 'T')? GET_LT
214 0 0 : len == 2 && (mode_str[1] == 'e' || mode_str[1] == 'E')? GET_LE
0 0 : len == 2 && (mode_str[1] == 'e' || mode_str[1] == 'E')? GET_LE
0 0 : len == 2 && (mode_str[1] == 'e' || mode_str[1] == 'E')? GET_LE
215 0 0 : len == 7 && foldEQ(mode_str, "LE_LAST", 7)? GET_LE_LAST
0 0 : len == 7 && foldEQ(mode_str, "LE_LAST", 7)? GET_LE_LAST
216 0 0 : -1;
218 0 0 case 'P': case 'p': mode= foldEQ(mode_str, "PREV", 4)? GET_PREV : -1; break;
219 0 0 case 'N': case 'n': mode= foldEQ(mode_str, "NEXT", 4)? GET_NEXT : -1; break;
220 0 0 case 'o': case 'O': mode= foldEQ(mode_str, "OR_ADD", 6)? GET_OR_ADD : -1; break;
230 0 0 if (!sv)
232 0 0 else if (!SvPOK(sv))
235 0 0 if (len < size || ((intptr_t)p) & (align-1)) {
0 0 if (len < size || ((intptr_t)p) & (align-1)) {
236 0 0 SvGROW(sv, size+align-1);
0 0 SvGROW(sv, size+align-1);
239 0 0 if ((intptr_t)p & (align-1)) {
333 20213 0 if (item->orig_key_stored)
433 0 19 if (!tree) croak("tree is NULL");
434 0 19 if (!tree->owner) croak("no owner");
435 19 0 if (tree->key_type < 0 || tree->key_type > KEY_TYPE_MAX) croak("bad key_type");
0 19 if (tree->key_type < 0 || tree->key_type > KEY_TYPE_MAX) croak("bad key_type");
436 0 19 if (!tree->compare) croak("no compare function");
437 0 19 if ((err= rbtree_check_structure(&tree->root_sentinel, (int(*)(void*,void*,void*)) tree->compare, tree, -OFS_TreeRBXS_item_FIELD_rbnode)))
439 19 0 if (TreeRBXS_get_count(tree)) {
441 500010 19 while (node) {
443 0 500010 if (item->key_type != tree->key_type)
445 0 500010 if (!item->value)
447 0 500010 if (item->iter) {
449 0 0 while (iter) {
450 0 0 if (!iter->owner) croak("Iterator lacks owner reference");
451 0 0 if (iter->item != item) croak("Iterator referenced by wrong item");
458 19 0 if (!tree->recent_count) {
459 19 0 if (tree->recent.prev != &tree->recent || tree->recent.next != &tree->recent)
0 19 if (tree->recent.prev != &tree->recent || tree->recent.next != &tree->recent)
462 0 0 if (tree->recent.prev == &tree->recent || tree->recent.next == &tree->recent)
0 0 if (tree->recent.prev == &tree->recent || tree->recent.next == &tree->recent)
464 0 0 if (tree->recent_limit >= 0 && tree->recent_count > tree->recent_limit)
0 0 if (tree->recent_limit >= 0 && tree->recent_count > tree->recent_limit)
472 5 74 if (!tree->hashiter) {
495 20079 481391 if (tree->transform) {
518 0 140231 if (len > CKEYLEN_MAX)
537 44 3 if (cmp != 0) {
538 9 35 rbtree_node_t *node= cmp < 0? rbtree_node_prev(&item->rbnode) : rbtree_node_next(&item->rbnode);
540 44 0 int neighbor_cmp= neighbor? tree->compare(tree, new_value, neighbor) : 0;
541 14 30 IV new_extra= ITEM_EXTRA_BYTES_NEEDED(new_value);
0 14 IV new_extra= ITEM_EXTRA_BYTES_NEEDED(new_value);
542 14 30 if (IS_ITEM_KEY_STORED_IN_EXTRA(item)) {
0 14 if (IS_ITEM_KEY_STORED_IN_EXTRA(item)) {
543 0 30 IV cur_extra= ITEM_EXTRA_BYTES_NEEDED(item);
0 0 IV cur_extra= ITEM_EXTRA_BYTES_NEEDED(item);
544 2 28 if (new_extra > cur_extra) {
554 35 9 if ((cmp > 0 && neighbor_cmp > 0) || (cmp < 0 && neighbor_cmp < 0)
32 3 if ((cmp > 0 && neighbor_cmp > 0) || (cmp < 0 && neighbor_cmp < 0)
9 32 if ((cmp > 0 && neighbor_cmp > 0) || (cmp < 0 && neighbor_cmp < 0)
6 3 if ((cmp > 0 && neighbor_cmp > 0) || (cmp < 0 && neighbor_cmp < 0)
555 33 5 || (neighbor_cmp == 0 && !tree->allow_duplicates)
33 0 || (neighbor_cmp == 0 && !tree->allow_duplicates)
560 0 39 if (item->iter)
563 0 39 if (tree->prev_inserted_item == item) {
589 36 3 if (found_identical) {
591 30 6 if (cmp > 0)
596 36 0 if (!tree->allow_duplicates) {
600 0 36 rm_node= (rm_node == search[1])? NULL : rbtree_node_next(rm_node);
601 0 36 ASSUME(rm_item != item);
603 0 36 } while (rm_node);
606 3 0 else if (search[0])
616 0 14 if (item->key_type == KEY_TYPE_CLAIM)
638 16 31 if (item->orig_key_stored) {
642 0 16 ASSUME(new_value->orig_key_stored);
658 470907 30077 bool is_buffered_key= IS_ITEM_KEY_STORED_IN_EXTRA(src);
110025 360882 bool is_buffered_key= IS_ITEM_KEY_STORED_IN_EXTRA(src);
666 480952 20032 if (src->orig_key_stored || is_buffered_key) {
120070 360882 if (src->orig_key_stored || is_buffered_key) {
668 140102 0 strbuf_len= is_buffered_key? src->ckeylen+1 : 0;
672 20032 120070 if (keyptr_len) {
675 0 20032 kept= src->key_type == KEY_TYPE_CLAIM? SvREFCNT_inc(kept) : newSVsv(kept);
680 140102 0 if (is_buffered_key) {
729 149 26 return node? GET_TreeRBXS_FROM_root_sentinel(node) : NULL;
734 6 0 while (node && node->parent)
4 2 while (node && node->parent)
747 2 0 struct TreeRBXS *tree= root_sentinel? GET_TreeRBXS_FROM_root_sentinel(root_sentinel) : NULL;
753 2 0 if (item != orig_item) {
755 2 0 if (tree) {
756 2 0 if (item->rbnode.left->count) {
757 0 2 ASSUME(item->rbnode.left->parent == orig_rbnode);
760 2 0 if (item->rbnode.right->count) {
761 0 2 ASSUME(item->rbnode.right->parent == orig_rbnode);
764 2 0 if (item->rbnode.parent == root_sentinel) {
765 0 2 ASSUME(root_sentinel->left == orig_rbnode);
768 0 0 else if (item->rbnode.parent->left == orig_rbnode)
771 0 0 ASSUME(item->rbnode.parent->right == orig_rbnode);
775 2 0 if (item->recent.next) {
776 0 2 ASSUME(item->recent.next->prev == orig_llnode);
777 0 2 ASSUME(item->recent.prev->next == orig_llnode);
782 0 2 if (tree->prev_inserted_item == orig_item)
786 0 2 if (item->iter) {
788 0 0 for (; cur; cur= cur->next_iter) {
789 0 0 ASSUME(cur->item == orig_item);
794 2 0 if (item->owner) {
796 0 2 ASSUME(magic != NULL);
797 0 2 ASSUME(magic->mg_ptr == (char*) orig_item);
801 0 2 if (IS_ITEM_KEY_STORED_IN_EXTRA(item)) {
0 0 if (IS_ITEM_KEY_STORED_IN_EXTRA(item)) {
802 2 0 ASSUME(orig_ckey_ofs >= 0 && orig_ckey_ofs <= sizeof(void*));
0 2 ASSUME(orig_ckey_ofs >= 0 && orig_ckey_ofs <= sizeof(void*));
811 140767 360218 switch (item->key_type) {
815 20032 480953 if (item->orig_key_stored) {
819 500985 0 if (item->value)
837 25 178 if (!rbtree_node_is_in_tree(&item->rbnode))
847 16813 0 for (cur= &item->iter; *cur; cur= &((*cur)->next_iter)) {
848 1659 15154 if (*cur == iter) {
865 3 12 if (iter->recent) {
866 0 3 lnode= iter->reverse? tree->recent.prev : tree->recent.next;
867 3 0 item= (lnode == &tree->recent)? NULL : GET_TreeRBXS_item_FROM_recent(lnode);
873 2 10 : rbtree_node_left_leaf(root);
882 13 1917 if (iter->item == item)
885 1640 277 if (iter->item)
888 1692 225 if (item) {
890 106 1586 if (iter->recent && !item->recent.next)
0 106 if (iter->recent && !item->recent.next)
907 0 1667 if (!iter->tree)
910 103 1564 if (iter->recent) {
913 1 102 if (ofs < 0 && !item) {
0 1 if (ofs < 0 && !item) {
914 0 0 cur= iter->reverse? iter->tree->recent.prev : iter->tree->recent.next;
919 16 87 if (iter->reverse)
921 86 17 if (ofs > 0) {
922 88 86 while (ofs-- > 0 && cur && cur != end)
88 0 while (ofs-- > 0 && cur && cur != end)
88 0 while (ofs-- > 0 && cur && cur != end)
924 17 0 } else if (ofs < 0) {
925 17 17 while (ofs++ < 0 && cur && cur != end)
17 0 while (ofs++ < 0 && cur && cur != end)
17 0 while (ofs++ < 0 && cur && cur != end)
928 103 0 item= cur && cur != end? GET_TreeRBXS_item_FROM_recent(cur) : NULL;
88 15 item= cur && cur != end? GET_TreeRBXS_item_FROM_recent(cur) : NULL;
932 810 754 else if (ofs == 1) {
934 798 12 if (item) {
936 392 406 node= iter->reverse? rbtree_node_prev(node) : rbtree_node_next(node);
950 737 17 : !iter->reverse? rbtree_node_index(&item->rbnode)
952 387 350 : cnt - 1 - rbtree_node_index(&item->rbnode);
953 750 4 if (ofs > 0) {
954 601 149 newpos= (UV)ofs < (cnt-pos)? pos + ofs : cnt;
957 4 0 newpos= (pos < o)? 0 : pos - o;
960 360 394 if (iter->reverse) newpos= cnt - 1 - newpos;
982 70 18 for (iter= item->iter, item->iter= NULL; iter; iter= next) {
984 8 62 if (iter->recent) { // iterating insertion order?
985 3 5 if (iter->reverse) { // newest to oldest?
986 3 0 if (!prev_recent) {
988 3 0 if (lnode == NULL || lnode == &iter->tree->recent) {
1 2 if (lnode == NULL || lnode == &iter->tree->recent) {
1001 3 2 if (!next_recent) {
1003 3 0 if (lnode == NULL || lnode == &iter->tree->recent) {
0 3 if (lnode == NULL || lnode == &iter->tree->recent) {
1015 3 59 else if (flags & ONLY_ADVANCE_RECENT) {
1021 31 28 if (iter->reverse) { // iterating high to low
1022 22 9 if (!prev_item) {
1024 17 5 if (!node) {
1038 18 10 if (!next_item) {
1040 9 9 if (!node) {
1062 97 0 if (rbtree_node_is_in_tree(&item->rbnode)) {
1063 14 83 if (tree->prev_inserted_item == item) {
1068 16 81 if (item->iter)
1071 25 72 if (item->recent.next)
1078 85 12 if (!item->owner)
1088 6 500887 while (iter) {
1097 0 500887 if (rbtree_node_is_in_tree(&item->rbnode))
1100 500875 12 if (!item->owner)
1105 19 243 if (iter->item)
1107 262 0 if (iter->tree) {
1108 5 257 if (iter->tree->hashiter == iter)
1119 8 103 if (tree->compare_callback)
1121 5 106 if (tree->hashiter)
1152 369 5 if (node && cmp == 0) {
327 42 if (node && cmp == 0) {
1163 2 310 if (tree->allowed_duplicates)
1166 8 304 if (step)
1175 1 14 if (tree->allowed_duplicates)
1178 10 5 if (step)
1193 7 0 if (node && cmp > 0)
2 5 if (node && cmp > 0)
1199 7 0 if (node && cmp < 0)
6 1 if (node && cmp < 0)
1204 3 3 TREERBXS_INSERT_ITEM_AT_NODE(tree, item, node, cmp);
0 3 TREERBXS_INSERT_ITEM_AT_NODE(tree, item, node, cmp);
0 6 TREERBXS_INSERT_ITEM_AT_NODE(tree, item, node, cmp);
1220 500671 339 if (tree->prev_inserted_trend >= INSERT_TREND_TRIGGER) {
1221 470541 30130 if (tree->prev_inserted_trend > INSERT_TREND_CAP)
1225 14 500657 if (cmp == 0) {
1227 1 13 if (overwrite) {
1228 1 0 if (tree->prev_inserted_dup) {
1231 1 1 && tree->compare(tree, stack_item, GET_TreeRBXS_item_FROM_rbnode(hint->parent)) == 0)
1 0 && tree->compare(tree, stack_item, GET_TreeRBXS_item_FROM_rbnode(hint->parent)) == 0)
1237 13 0 } else if (tree->allow_duplicates)
1242 500607 50 else if (cmp > 0) {
1244 149791 350816 if (!tmpnode || tree->compare(tree, stack_item, GET_TreeRBXS_item_FROM_rbnode(tmpnode)) < 0) {
134802 14989 if (!tmpnode || tree->compare(tree, stack_item, GET_TreeRBXS_item_FROM_rbnode(tmpnode)) < 0) {
1252 47 3 if (!tmpnode || tree->compare(tree, stack_item, GET_TreeRBXS_item_FROM_rbnode(tmpnode)) > 0) {
9 38 if (!tmpnode || tree->compare(tree, stack_item, GET_TreeRBXS_item_FROM_rbnode(tmpnode)) > 0) {
1266 15271 95 if (hint && cmp == 0) {
15219 52 if (hint && cmp == 0) {
1267 25 27 if (overwrite) {
1269 23 2 if (tree->allowed_duplicates) {
1271 0 3 if (!rbtree_find_all(
1280 6 3 while (last != first) {
1291 23 3 if (oldval_out)
1297 6 20 if (item->orig_key_stored) {
1300 6 0 if (sv_cmp(orig_key, new_key)) {
1307 25 1 if (tree->track_recent || item->recent.next)
0 25 if (tree->track_recent || item->recent.next)
1310 21 6 } else if (tree->allow_duplicates) {
1316 8 26 if (tree->track_recent)
1322 3 3 if (item == tree->prev_inserted_item)
1330 95 500849 TREERBXS_INSERT_ITEM_AT_NODE(tree, item, hint, cmp);
493311 7538 TREERBXS_INSERT_ITEM_AT_NODE(tree, item, hint, cmp);
72 500872 TREERBXS_INSERT_ITEM_AT_NODE(tree, item, hint, cmp);
1334 341 500663 if (tree->prev_inserted_trend < INSERT_TREND_TRIGGER && tree->prev_inserted_item) {
242 99 if (tree->prev_inserted_trend < INSERT_TREND_TRIGGER && tree->prev_inserted_item) {
1336 234 8 if (item == tree->prev_inserted_item
1337 57 177 || item->rbnode.parent == &tree->prev_inserted_item->rbnode
1338 50 7 || item->rbnode.left == &tree->prev_inserted_item->rbnode
1339 11 39 || item->rbnode.right == &tree->prev_inserted_item->rbnode
1342 24 15 } else if (tree->prev_inserted_trend)
1354 110 1 if (item->recent.next != node_after) {
1355 6 104 if (item->recent.next) {
1368 19 91 if (tree->recent_limit >= 0 && tree->recent_count > tree->recent_limit)
14 5 if (tree->recent_limit >= 0 && tree->recent_count > tree->recent_limit)
1377 35 0 if (item->recent.next) {
1379 2 33 if (item->iter)
1394 15 0 if (lim >= 0 && tree->recent_count > lim) {
15 0 if (lim >= 0 && tree->recent_count > lim) {
1397 17 15 for (i= 0; i < n && cur && cur != &tree->recent; i++) {
17 0 for (i= 0; i < n && cur && cur != &tree->recent; i++) {
17 0 for (i= 0; i < n && cur && cur != &tree->recent; i++) {
1399 0 17 if (nodes_out)
1405 0 15 if (i != n)
1423 165671 55399 return diff < 0? -1 : diff > 0? 1 : 0; /* shrink from IV to int might lose upper bits */
1429 55330 165491 return diff < 0? -1 : diff > 0? 1 : 0;
1437 39507 632784 return cmp? cmp : alen < blen? -1 : alen > blen? 1 : 0;
35663 3844 return cmp? cmp : alen < blen? -1 : alen > blen? 1 : 0;
1448 40307 1 while (apos < alim && bpos < blim) {
40293 14 while (apos < alim && bpos < blim) {
1450 40413 4 while (apos < alim && bpos < blim && *apos == *bpos && !isdigit(*apos))
40413 0 while (apos < alim && bpos < blim && *apos == *bpos && !isdigit(*apos))
39920 493 while (apos < alim && bpos < blim && *apos == *bpos && !isdigit(*apos))
124 39796 while (apos < alim && bpos < blim && *apos == *bpos && !isdigit(*apos))
1454 40627 9 while (apos < alim && !isdigit(*apos)) apos++;
343 40284 while (apos < alim && !isdigit(*apos)) apos++;
1456 40478 9 while (bpos < blim && !isdigit(*bpos)) bpos++;
194 40284 while (bpos < blim && !isdigit(*bpos)) bpos++;
1460 40211 82 if (alen || blen) {
10 40201 if (alen || blen) {
1463 10 82 if (alen == 0) return -1;
1464 46 36 if (blen == 0) return 1;
1467 0 36 if (a_utf8 != b_utf8) {
1469 0 0 : bytes_cmp_utf8((const U8*) amark, alen, (const U8*) bmark, blen);
1470 0 0 if (cmp) return cmp;
1475 36 0 if (cmp) return cmp;
1476 0 0 if (alen < blen) return -1;
1477 0 0 if (alen > blen) return -1;
1481 40197 4 if (!(apos < alim && bpos < blim)) break;
40197 0 if (!(apos < alim && bpos < blim)) break;
1484 40387 0 while (apos < alim && *apos == '0') apos++;
190 40197 while (apos < alim && *apos == '0') apos++;
1485 40325 0 while (bpos < blim && *bpos == '0') bpos++;
128 40197 while (bpos < blim && *bpos == '0') bpos++;
1489 147627 2 while (apos < alim && bpos < blim && *apos == *bpos && isdigit(*apos))
147613 14 while (apos < alim && bpos < blim && *apos == *bpos && isdigit(*apos))
107472 40141 while (apos < alim && bpos < blim && *apos == *bpos && isdigit(*apos))
107432 40 while (apos < alim && bpos < blim && *apos == *bpos && isdigit(*apos))
1493 40195 2 if ((apos < alim && isdigit(*apos)) || (bpos < blim && isdigit(*bpos))) {
59 40136 if ((apos < alim && isdigit(*apos)) || (bpos < blim && isdigit(*bpos))) {
47 14 if ((apos < alim && isdigit(*apos)) || (bpos < blim && isdigit(*bpos))) {
6 41 if ((apos < alim && isdigit(*apos)) || (bpos < blim && isdigit(*bpos))) {
1494 1 40141 if (apos == alim) return -1;
1495 0 40141 if (bpos == blim) return 1;
1499 48642 40018 while (apos < alim && isdigit(*apos)) apos++;
48519 123 while (apos < alim && isdigit(*apos)) apos++;
1500 48606 40039 while (bpos < blim && isdigit(*bpos)) bpos++;
48504 102 while (bpos < blim && isdigit(*bpos)) bpos++;
1504 52 40089 if (alen < blen) return -1;
1505 67 40022 if (alen > blen) return 1;
1512 1 18 if (bpos < blim) return -1;
1513 14 4 if (apos < alim) return 1;
1568 0 221372 PUSHMARK(SP);
1569 0 221372 EXTEND(SP, 2);
1573 0 221372 if (call_sv(tree->compare_callback, G_SCALAR) != 1)
1580 166015 55357 return (int)(ret < 0? -1 : ret > 0? 1 : 0);
1593 0 20079 PUSHMARK(SP);
1594 0 20079 XPUSHs(orig_key);
1616 111 0 if (mg->mg_ptr) {
1626 203 0 if (mg->mg_ptr) {
1635 257 0 if (mg->mg_ptr)
1660 0 501531 if (!sv_isobject(obj)) {
1661 0 0 if (flags & OR_DIE)
1666 501420 111 if (SvMAGICAL(sv) && (magic= mg_findext(sv, PERL_MAGIC_ext, &TreeRBXS_magic_vt)))
501420 0 if (SvMAGICAL(sv) && (magic= mg_findext(sv, PERL_MAGIC_ext, &TreeRBXS_magic_vt)))
1669 111 0 if (flags & AUTOCREATE) {
1678 0 0 else if (flags & OR_DIE)
1689 34 694 if (!sv_isobject(obj)) {
1690 0 34 if (flags & OR_DIE)
1695 694 0 if (SvMAGICAL(sv) && (magic= mg_findext(sv, PERL_MAGIC_ext, &TreeRBXS_item_magic_vt)))
452 242 if (SvMAGICAL(sv) && (magic= mg_findext(sv, PERL_MAGIC_ext, &TreeRBXS_item_magic_vt)))
1698 0 242 if (flags & OR_DIE)
1710 75 221 if (!item)
1713 21 200 if (item->owner)
1729 24 902 if (!item)
1731 159 743 if (item->orig_key_stored) {
1781 0 2210 if (!sv_isobject(obj)) {
1782 0 0 if (flags & OR_DIE)
1787 2210 0 if (SvMAGICAL(sv) && (magic= mg_findext(sv, PERL_MAGIC_ext, &TreeRBXS_iter_magic_vt)))
1696 514 if (SvMAGICAL(sv) && (magic= mg_findext(sv, PERL_MAGIC_ext, &TreeRBXS_iter_magic_vt)))
1790 257 257 if (flags & AUTOCREATE) {
1799 0 257 else if (flags & OR_DIE)
1808 65 0 if (!(method_gv= gv_fetchmethod(stash, name))
1809 0 65 || !(method_cv= GvCV(method_gv)))
1816 348 0 SvUPGRADE(name, SVt_PVNV);
1830 39 0 if (array && SvTYPE(array) == SVt_PVAV)
3 36 if (array && SvTYPE(array) == SVt_PVAV)
1832 36 0 else if (array && SvROK(array) && SvTYPE(SvRV(array)) == SVt_PVAV)
36 0 else if (array && SvROK(array) && SvTYPE(SvRV(array)) == SVt_PVAV)
36 0 else if (array && SvROK(array) && SvTYPE(SvRV(array)) == SVt_PVAV)
1839 1 38 if (!vec) {
1840 0 1 if (n == 0) /* don't return a NULL for an empty array, but doesn't need to be a real pointer */
1845 0 1 Newx(vec, n, SV*);
1847 10 1 for (i= 0; i < n; i++) {
1849 10 0 vec[i]= el? *el : NULL;
1853 39 0 if (len) *len= n;
1886 138 111 for (i= out_i= 0; i < attr_list_len; i += 2) {
1891 0 138 if (i + 1 == attr_list_len)
1894 0 138 if (!SvOK(val))
1897 27 0 case 2: if (strcmp("kv", attrname) == 0) { kv_sv= val; break; }
1899 5 0 case 4: if (strcmp("keys", attrname) == 0) { keys_sv= val; break; }
1901 2 1 case 6: if (strcmp("values", attrname) == 0) { values_sv= val; break; }
1902 1 0 else if (strcmp("recent", attrname) == 0) { recent_sv= val; break; }
1904 24 0 case 8: if (strcmp("key_type", attrname) == 0) { key_type_sv= val; break; }
1905 0 0 else if (strcmp("hashiter", attrname) == 0) { hashiter_sv= val; break; }
1907 56 0 case 10: if (strcmp("compare_fn", attrname) == 0) { compare_fn_sv= val; break; }
1909 9 1 case 12: if (strcmp("track_recent", attrname) == 0) { tree->track_recent= val && SvTRUE(val); break; }
9 0 case 12: if (strcmp("track_recent", attrname) == 0) { tree->track_recent= val && SvTRUE(val); break; }
9 0 case 12: if (strcmp("track_recent", attrname) == 0) { tree->track_recent= val && SvTRUE(val); break; }
1910 1 0 else if (strcmp("recent_limit", attrname) == 0) {
1911 1 0 tree->recent_limit= val && SvOK(val) && SvIV(val) >= 0? SvIV(val) : -1;
1 0 tree->recent_limit= val && SvOK(val) && SvIV(val) >= 0? SvIV(val) : -1;
1 0 tree->recent_limit= val && SvOK(val) && SvIV(val) >= 0? SvIV(val) : -1;
1915 0 0 case 15: if (strcmp("compat_list_get", attrname) == 0) { tree->compat_list_get= val && SvTRUE(val); break; }
0 0 case 15: if (strcmp("compat_list_get", attrname) == 0) { tree->compat_list_get= val && SvTRUE(val); break; }
0 0 case 15: if (strcmp("compat_list_get", attrname) == 0) { tree->compat_list_get= val && SvTRUE(val); break; }
1917 10 0 case 16: if (strcmp("allow_duplicates", attrname) == 0) { tree->allow_duplicates= val && SvTRUE(val); break; }
10 0 case 16: if (strcmp("allow_duplicates", attrname) == 0) { tree->allow_duplicates= val && SvTRUE(val); break; }
10 0 case 16: if (strcmp("allow_duplicates", attrname) == 0) { tree->allow_duplicates= val && SvTRUE(val); break; }
1919 3 0 case 20: if (strcmp("keys_in_recent_order", attrname) == 0) { tree->keys_in_recent_order= val && SvTRUE(val); break; }
3 0 case 20: if (strcmp("keys_in_recent_order", attrname) == 0) { tree->keys_in_recent_order= val && SvTRUE(val); break; }
3 0 case 20: if (strcmp("keys_in_recent_order", attrname) == 0) { tree->keys_in_recent_order= val && SvTRUE(val); break; }
1921 0 0 case 21: if (strcmp("lookup_updates_recent", attrname) == 0) { tree->lookup_updates_recent= val && SvTRUE(val); break; }
0 0 case 21: if (strcmp("lookup_updates_recent", attrname) == 0) { tree->lookup_updates_recent= val && SvTRUE(val); break; }
0 0 case 21: if (strcmp("lookup_updates_recent", attrname) == 0) { tree->lookup_updates_recent= val && SvTRUE(val); break; }
1925 0 0 if (i > out_i) {
1934 24 87 if (key_type_sv) {
1936 0 24 if (key_type < 0)
1942 56 55 if (compare_fn_sv) {
1944 0 56 if (cmp_id < 0)
1947 21 34 } else if (key_type_sv) {
1950 10 11 : key_type == KEY_TYPE_FLOAT? CMP_FLOAT
1951 7 3 : key_type == KEY_TYPE_BSTR? CMP_MEMCMP
1952 4 3 : key_type == KEY_TYPE_USTR? CMP_STR
1953 2 2 : key_type == KEY_TYPE_ANY? CMP_PERL /* use Perl's cmp operator */
1960 8 0 if (!compare_fn_sv || !SvRV(compare_fn_sv) || SvTYPE(SvRV(compare_fn_sv)) != SVt_PVCV)
8 0 if (!compare_fn_sv || !SvRV(compare_fn_sv) || SvTYPE(SvRV(compare_fn_sv)) != SVt_PVCV)
0 8 if (!compare_fn_sv || !SvRV(compare_fn_sv) || SvTYPE(SvRV(compare_fn_sv)) != SVt_PVCV)
1964 8 0 if (key_type != KEY_TYPE_CLAIM) tree->key_type= KEY_TYPE_ANY;
1974 37 1 if (key_type != KEY_TYPE_CLAIM) tree->key_type= KEY_TYPE_ANY;
1995 4 1 if (key_type != KEY_TYPE_USTR && key_type != KEY_TYPE_ANY && key_type != KEY_TYPE_CLAIM)
1 3 if (key_type != KEY_TYPE_USTR && key_type != KEY_TYPE_ANY && key_type != KEY_TYPE_CLAIM)
1 0 if (key_type != KEY_TYPE_USTR && key_type != KEY_TYPE_ANY && key_type != KEY_TYPE_CLAIM)
2004 84 27 if (kv_sv || keys_sv || values_sv) {
79 5 if (kv_sv || keys_sv || values_sv) {
0 79 if (kv_sv || keys_sv || values_sv) {
2009 27 5 if (kv_sv) {
2010 27 0 if (keys_sv || values_sv)
0 27 if (keys_sv || values_sv)
2012 0 27 if (!(key_vec= unwrap_array(kv_sv, &num_kv)))
2014 0 27 if (num_kv & 1)
2020 5 27 if (keys_sv) {
2021 0 5 if (!(key_vec= unwrap_array(keys_sv, &num_kv)))
2025 2 30 if (values_sv) {
2027 0 2 if (!key_vec)
2029 0 2 if (!(val_vec= unwrap_array(values_sv, &nvals)))
2031 0 2 if (nvals != num_kv)
2036 1 31 if (recent_sv)
2038 154 32 for (key_lim= key_vec + num_kv * key_step; key_vec < key_lim; key_vec += key_step, val_vec += val_step) {
2039 136 18 TreeRBXS_init_tmp_item(&stack_item, tree, (*key_vec? *key_vec : &PL_sv_undef), (val_vec? *val_vec : &PL_sv_undef));
154 0 TreeRBXS_init_tmp_item(&stack_item, tree, (*key_vec? *key_vec : &PL_sv_undef), (val_vec? *val_vec : &PL_sv_undef));
2048 1 110 if (recent_sv) {
2051 0 1 if (!rvec) croak("'recent' must be an arrayref");
2052 23 1 for (i= 0; i < n; i++) {
2053 0 23 if (!looks_like_integer(rvec[i]))
2056 23 0 if (idx < 0 || idx >= nodecount)
0 23 if (idx < 0 || idx >= nodecount)
2059 0 23 if (!node) croak("BUG: access node[idx]");
2065 0 111 if (hashiter_sv) {
2068 0 0 if (!looks_like_integer(hashiter_sv))
2071 0 0 if (idx < 0 || idx >= nodecount)
0 0 if (idx < 0 || idx >= nodecount)
2074 0 0 if (!node) croak("BUG: access node[idx]");
2085 7 0 if (!version || !SvOK(version))
0 7 if (!version || !SvOK(version))
2108 0 108 if (sv_isobject(obj_or_pkg) && SvTYPE(SvRV(obj_or_pkg)) == SVt_PVHV) {
0 0 if (sv_isobject(obj_or_pkg) && SvTYPE(SvRV(obj_or_pkg)) == SVt_PVHV) {
2112 108 0 else if (SvPOK(obj_or_pkg) && (pkg= gv_stashsv(obj_or_pkg, 0))) {
108 0 else if (SvPOK(obj_or_pkg) && (pkg= gv_stashsv(obj_or_pkg, 0))) {
2113 0 108 if (!sv_derived_from(obj_or_pkg, "Tree::RB::XS"))
2121 0 0 croak("%s: first arg must be package name or blessed object", ix == 1? "_init_tree":"new");
2124 4 104 if (items == 2) {
2127 1 3 if (!SvROK(first) || SvTYPE(SvRV(first)) == SVt_PVCV) {
0 1 if (!SvROK(first) || SvTYPE(SvRV(first)) == SVt_PVCV) {
2134 1 0 else if (SvTYPE(SvRV(first)) == SVt_PVHV) {
2139 0 1 Newx(attr_list, attr_len, SV*);
2142 3 1 while ((ent= hv_iternext(attrhv)) && i < attr_len) {
3 0 while ((ent= hv_iternext(attrhv)) && i < attr_len) {
2155 0 108 if (tree->owner != (SV*) obj_hv)
2159 0 108 if (n_unknown) {
2161 0 0 if (ix == 0)
2164 0 0 if (attr_list != PL_stack_base+ax+1) {
2165 0 0 EXTEND(SP, n_unknown);
0 0 EXTEND(SP, n_unknown);
2166 0 0 for (i= 0; i < n_unknown; i++)
2170 0 108 i= ix == 0? 1 : n_unknown;
2197 0 4 while ((pos= hv_iternext(treehv))) {
2201 0 4 if (tree->recent_limit >= 0) {
2207 2 2 if (nodecount) {
2233 34 2 for (i= 0; i < nodecount && node; i++, node=rbtree_node_next(node)) {
34 0 for (i= 0; i < nodecount && node; i++, node=rbtree_node_next(node)) {
2255 0 2 if (i < nodecount) croak("BUG: too few nodes in tree");
2256 0 2 if (node) croak("BUG: too many nodes in tree");
2267 1 1 if (tree->recent_count) {
2273 23 1 for (i= tree->recent_count; i > 0 && pos != root; --i, pos= pos->next) {
23 0 for (i= tree->recent_count; i > 0 && pos != root; --i, pos= pos->next) {
2278 0 1 if (i != 0) croak("BUG: too few recent-tracked nodes");
2279 0 1 if (pos != root) croak("BUG: too many recent-tracked nodes");
2282 0 2 if (tree->hashiter && tree->hashiter->item) {
0 0 if (tree->hashiter && tree->hashiter->item) {
2286 0 0 if (pointing_at) {
2296 2 2 if (cmp_id == CMP_SUB) {
2297 0 2 if (!cloning)
2305 2 0 if (!stash || !name || !(re_gv= gv_fetchmethod(stash, name)) || GvCV(re_gv) != cv)
2 0 if (!stash || !name || !(re_gv= gv_fetchmethod(stash, name)) || GvCV(re_gv) != cv)
1 1 if (!stash || !name || !(re_gv= gv_fetchmethod(stash, name)) || GvCV(re_gv) != cv)
0 1 if (!stash || !name || !(re_gv= gv_fetchmethod(stash, name)) || GvCV(re_gv) != cv)
2306 1 0 croak("Comparison function (%s::%s) for Tree::RB::XS instance cannot be serialized unless it exists as a global package function",
1 0 croak("Comparison function (%s::%s) for Tree::RB::XS instance cannot be serialized unless it exists as a global package function",
1 0 croak("Comparison function (%s::%s) for Tree::RB::XS instance cannot be serialized unless it exists as a global package function",
1 0 croak("Comparison function (%s::%s) for Tree::RB::XS instance cannot be serialized unless it exists as a global package function",
0 1 croak("Comparison function (%s::%s) for Tree::RB::XS instance cannot be serialized unless it exists as a global package function",
0 0 croak("Comparison function (%s::%s) for Tree::RB::XS instance cannot be serialized unless it exists as a global package function",
1 0 croak("Comparison function (%s::%s) for Tree::RB::XS instance cannot be serialized unless it exists as a global package function",
0 1 croak("Comparison function (%s::%s) for Tree::RB::XS instance cannot be serialized unless it exists as a global package function",
2311 1 0 av_push(attrs, newSVpvf("%s::%s", HvNAME(stash), name));
1 0 av_push(attrs, newSVpvf("%s::%s", HvNAME(stash), name));
0 1 av_push(attrs, newSVpvf("%s::%s", HvNAME(stash), name));
0 0 av_push(attrs, newSVpvf("%s::%s", HvNAME(stash), name));
1 0 av_push(attrs, newSVpvf("%s::%s", HvNAME(stash), name));
0 1 av_push(attrs, newSVpvf("%s::%s", HvNAME(stash), name));
2315 0 3 if (version < 0 || version > 0x7FFFFFFF)
2321 3 0 if (key_type < 1 || key_type > 255)
0 3 if (key_type < 1 || key_type > 255)
2325 3 0 if (cmp_id < 1 || cmp_id > 255)
0 3 if (cmp_id < 1 || cmp_id > 255)
2330 0 3 | (tree->compat_list_get? 2 : 0)
2331 1 2 | (tree->track_recent? 4 : 0)
2332 0 3 | (tree->lookup_updates_recent? 8 : 0)
2333 0 3 | (tree->keys_in_recent_order? 0x10 : 0);
2337 0 3 EXTEND(SP, 2);
2356 3 0 if (!SvROK(objref) || SvTYPE(SvRV(objref)) != SVt_PVHV)
0 3 if (!SvROK(objref) || SvTYPE(SvRV(objref)) != SVt_PVHV)
2359 0 3 if (tree->owner != SvRV(objref))
2364 0 3 if (sb_len < 10)
2371 0 3 if (version <= 0)
2373 0 3 if (version > get_integer_version())
2383 3 0 if (key_type <= 0 || key_type > KEY_TYPE_MAX)
0 3 if (key_type <= 0 || key_type > KEY_TYPE_MAX)
2387 3 0 if (cmp_id <= 0 || cmp_id > CMP_MAX)
0 3 if (cmp_id <= 0 || cmp_id > CMP_MAX)
2391 3 0 if (cmp_id == CMP_FOLDCASE || cmp_id == CMP_NUMSPLIT_FOLDCASE)
0 3 if (cmp_id == CMP_FOLDCASE || cmp_id == CMP_NUMSPLIT_FOLDCASE)
2395 0 3 Newx(attr_list, attr_len, SV*);
2400 1 2 if (cmp_id == CMP_SUB) {
2401 0 1 if (!cloning) croak("compare_fn lookup is forbidden unless cloning");
2403 1 0 for (i= attr_len-2; i >= 0; i-= 2) {
2404 1 0 if (strcmp(SvPV_nolen(attr_list[i]), "compare_fn") == 0) {
2407 1 0 if (gv && GvCV(gv))
1 0 if (gv && GvCV(gv))
2414 0 1 if (i < 0)
2419 0 3 if (n_unknown) {
2422 0 0 for (i= 0; i < n_unknown-1; i += 2)
2423 0 0 if (!hv_store_ent(obj, attr_list[i], (tmpsv= newSVsv(attr_list[i+1])), 0))
2445 2 16 : sv_2mortal(new_enum_dualvar(aTHX_ id, newSVpv(get_cmp_name(id), 0)));
2453 4 11 if (items > 1) {
2466 0 2 if (items > 1) {
2470 0 2 ST(0)= tree->compat_list_get? &PL_sv_yes : &PL_sv_no;
2479 0 2 if (items > 1) {
2483 2 0 ST(0)= tree->track_recent? &PL_sv_yes : &PL_sv_no;
2492 1 2 if (items > 1) {
2496 0 2 ST(0)= tree->lookup_updates_recent? &PL_sv_yes : &PL_sv_no;
2505 1 0 if (items > 1) {
2509 0 0 ST(0)= tree->keys_in_recent_order? &PL_sv_yes : &PL_sv_no;
2517 0 56 RETVAL= TreeRBXS_get_count(tree);
2525 0 9 RETVAL= tree->recent_count;
2534 2 2 if (newval) {
2535 1 1 if (!SvOK(newval)) {
2537 1 0 } else if (!looks_like_number(newval) || SvIV(newval) < 0) {
0 1 } else if (!looks_like_number(newval) || SvIV(newval) < 0) {
2546 1 1 : sv_2mortal(newSViv(tree->recent_limit));
2554 0 1 EXTEND(SP, 5);
2575 0 500341 if (!SvOK(key))
2579 100132 1 ST(0)= ix == 0? sv_2mortal(newSViv(inserted? rbtree_node_index(&inserted->rbnode) : -1))
2580 100133 400208 : ix == 1? (oldval? oldval : &PL_sv_undef)
17 400185 : ix == 1? (oldval? oldval : &PL_sv_undef)
2581 400202 6 : (inserted? sv_2mortal(TreeRBXS_wrap_item(inserted)) : &PL_sv_undef);
4 2 : (inserted? sv_2mortal(TreeRBXS_wrap_item(inserted)) : &PL_sv_undef);
2596 0 4 if (items == 2 && SvROK(ST(1)) && SvTYPE(SvRV(ST(1))) == SVt_PVAV && !sv_isobject(ST(1))) {
0 0 if (items == 2 && SvROK(ST(1)) && SvTYPE(SvRV(ST(1))) == SVt_PVAV && !sv_isobject(ST(1))) {
0 0 if (items == 2 && SvROK(ST(1)) && SvTYPE(SvRV(ST(1))) == SVt_PVAV && !sv_isobject(ST(1))) {
0 0 if (items == 2 && SvROK(ST(1)) && SvTYPE(SvRV(ST(1))) == SVt_PVAV && !sv_isobject(ST(1))) {
2605 515 4 while (i < lim) {
2608 0 515 if (av) {
2610 0 0 if (!el) croak("Tree->insert_multi does not support tied or sparse arrays");
2613 0 0 if (i < lim) {
2615 0 0 if (!el) croak("Tree->insert_multi does not support tied or sparse arrays");
2621 515 0 if (++i < lim) {
2626 0 515 if (!SvOK(key))
2633 5 510 if (ix == 0? (inserted != NULL) : (oldval == NULL))
507 8 if (ix == 0? (inserted != NULL) : (oldval == NULL))
2636 0 4 RETVAL= added;
2653 4 4 for (i= 1; i < items; i++) {
2656 1 3 if (tree->allowed_duplicates) {
2671 2 1 if (node && cmp == 0)
2 0 if (node && cmp == 0)
2675 0 4 RETVAL= total;
2706 0 368 if (!SvOK(key))
2709 6 362 if (ix >> 4) {
2712 0 6 if (mode_sv)
2715 61 301 mode= mode_sv? parse_lookup_mode(mode_sv) : GET_EQ;
2716 0 362 if (mode < 0)
2721 249 119 if (ix >= 3)
2722 24 225 ix= (GIMME_V == G_SCALAR || (ix == 4 && !tree->compat_list_get))? 2 : 3;
3 21 ix= (GIMME_V == G_SCALAR || (ix == 4 && !tree->compat_list_get))? 2 : 3;
3 0 ix= (GIMME_V == G_SCALAR || (ix == 4 && !tree->compat_list_get))? 2 : 3;
2732 337 31 if (item) {
2733 1 336 if (tree->lookup_updates_recent)
2735 0 337 if (GIMME_V == G_VOID)
2737 48 289 else if (ix <= 1) {
2738 38 10 if (ix == 0) { // return node
2745 273 16 } else if (ix == 2) { // return value
2768 0 1 if (!SvOK(key))
2771 1 0 if (rbtree_find_all(
2778 0 1 EXTEND(SP, count);
2779 6 1 for (i= 0; i < count; i++) {
2782 0 6 if (tree->lookup_updates_recent)
2800 0 24 if (!SvOK(key1))
2803 0 24 if ((item= TreeRBXS_get_magic_item(key1, 0))) {
2804 0 0 if (!TreeRBXS_is_member(tree, item))
2809 21 3 if (rbtree_find_all(
2816 1 20 if (key2)
2822 2 1 if (key2) {
2830 3 21 if (key2 && first) {
3 0 if (key2 && first) {
2831 0 3 if ((item= TreeRBXS_get_magic_item(key2, 0))) {
2832 0 0 if (!TreeRBXS_is_member(tree, item))
2837 2 1 if (rbtree_find_all(
2851 3 0 if (last && rbtree_node_index(first) > rbtree_node_index(last))
1 2 if (last && rbtree_node_index(first) > rbtree_node_index(last))
2856 24 0 if (first && last) {
22 2 if (first && last) {
2859 3 22 first= (first == last)? NULL : rbtree_node_next(first);
2862 3 22 } while (first);
2864 6 18 RETVAL= i;
2881 33 23 for (i= 1; i < items; i++) {
2884 0 33 if (++i >= items)
2889 3 0 case 'a': if (strncmp(opt_name, "max", len) == 0) { max_sv= ST(i); continue; }
2890 7 0 case 'i': if (strncmp(opt_name, "min", len) == 0) { min_sv= ST(i); continue; }
2894 23 0 if (strncmp(opt_name, "offset", len) == 0) { offset_sv= ST(i); continue; }
2899 1 22 if (!TreeRBXS_get_count(tree))
2902 7 15 if (min_sv) {
2904 6 1 if (!min_item) {
2906 1 5 if (SvROK(min_sv) && (it= TreeRBXS_get_magic_iter(min_sv, 0))) {
1 0 if (SvROK(min_sv) && (it= TreeRBXS_get_magic_iter(min_sv, 0))) {
2908 0 1 if (!min_item) croak("Iterator for 'min' is not referencing a tree node");
2917 3 19 if (max_sv) {
2919 2 1 if (!max_item) {
2921 1 1 if (SvROK(max_sv) && (it= TreeRBXS_get_magic_iter(max_sv, 0))) {
1 0 if (SvROK(max_sv) && (it= TreeRBXS_get_magic_iter(max_sv, 0))) {
2923 0 1 if (!max_item) croak("Iterator for 'max' is not referencing a tree node");
2932 22 0 if (offset_sv) {
2942 18 4 if (tree->key_type == KEY_TYPE_INT) {
2945 1 17 if (SvUOK(offset_sv) && SvUV(offset_sv) > IV_MAX)
1 0 if (SvUOK(offset_sv) && SvUV(offset_sv) > IV_MAX)
2948 0 17 if (offset_iv == 0)
2953 11 6 if (positive) {
2954 3 8 IV max_key= (max_item? max_item : last_item)->keyunion.ikey;
2955 1 10 if (IV_MAX - offset_iv < max_key)
2958 3 3 IV min_key= (min_item? min_item : first_item)->keyunion.ikey;
2959 1 5 if (IV_MIN - offset_iv > min_key)
2963 2 2 else if (tree->key_type == KEY_TYPE_FLOAT) {
2965 0 2 if (offset_nv == 0.0)
2978 12 5 edge_item= positive? max_item : min_item;
2979 6 11 if (edge_item && (boundary_node= node_seek[positive](&edge_item->rbnode))) {
4 2 if (edge_item && (boundary_node= node_seek[positive](&edge_item->rbnode))) {
2984 1 0 *final_item= (positive? (min_item? min_item : first_item)
2985 1 3 : (max_item? max_item : last_item)),
0 3 : (max_item? max_item : last_item)),
2989 9 0 if (intmode) {
2991 1 8 if (positive? (newval < boundary_item->keyunion.ikey)
4 5 if (positive? (newval < boundary_item->keyunion.ikey)
2997 0 0 if (positive? (newval < boundary_item->keyunion.nkey)
0 0 if (positive? (newval < boundary_item->keyunion.nkey)
3027 5 0 if (intmode) edge_item->keyunion.ikey= stack_item.keyunion.ikey;
3029 1 4 if (found_identical) {
3033 1 0 if (!tree->allow_duplicates) {
3037 0 1 node= (node == search[1])? NULL : rbtree_node_next(node);
3038 1 0 if (item != edge_item)
3040 0 1 } while (node);
3045 3 1 else if (search[0])
3049 5 0 if (!next || edge_item == final_item)
0 5 if (!next || edge_item == final_item)
3058 1 3 *(positive? &max_item : &min_item)= edge_item;
3061 7 10 rbtree_node_t *node= min_item? &min_item->rbnode : &first_item->rbnode;
3062 3 14 rbtree_node_t *end= max_item? &max_item->rbnode : &last_item->rbnode;
3064 36 5 if (intmode)
3068 17 24 if (node == end) break;
3088 0 0 bool keep= !(GIMME_V == G_VOID || GIMME_V == G_SCALAR);
0 0 bool keep= !(GIMME_V == G_VOID || GIMME_V == G_SCALAR);
3092 0 0 if (max_count >= 0 && tree->recent_count > max_count) {
0 0 if (max_count >= 0 && tree->recent_count > max_count) {
3094 0 0 if (keep) {
3095 0 0 EXTEND(SP, n);
0 0 EXTEND(SP, n);
3102 0 0 if (GIMME_V == G_SCALAR)
3145 1 14 if (ofs < 0) ofs += TreeRBXS_get_count(tree);
3156 8 0 : GET_TreeRBXS_item_FROM_rbnode(TreeRBXS_get_root(tree));
3165 1 12 if (newval) {
3166 0 1 if (!TreeRBXS_is_member(tree, newval))
3171 9 4 : GET_TreeRBXS_item_FROM_recent(tree->recent.next);
3180 1 18 if (newval) {
3181 0 1 if (!TreeRBXS_is_member(tree, newval))
3186 15 4 : GET_TreeRBXS_item_FROM_recent(tree->recent.prev);
3200 8 72 size_t n_ret, i, node_count= tree->keys_in_recent_order? tree->recent_count : TreeRBXS_get_count(tree);
3206 0 80 if (GIMME_V == G_VOID) {
3209 0 80 else if (GIMME_V == G_SCALAR) {
3214 19 61 n_ret= want_kv? node_count*2 : node_count;
3215 0 80 EXTEND(SP, n_ret);
3216 8 72 if (tree->keys_in_recent_order) {
3217 3 5 struct dllist_node *node= reverse? tree->recent.prev : tree->recent.next;
3219 3 5 if (keys_only) {
3220 8 3 for (i= 0; i < n_ret && node != limit; i++, node= reverse? node->prev : node->next)
8 0 for (i= 0; i < n_ret && node != limit; i++, node= reverse? node->prev : node->next)
3221 3 5 ST(i)= sv_2mortal(TreeRBXS_item_wrap_key(GET_TreeRBXS_item_FROM_recent(node)));
3223 2 3 else if (values_only) {
3224 6 2 for (i= 0; i < n_ret && node != limit; i++, node= reverse? node->prev : node->next)
6 0 for (i= 0; i < n_ret && node != limit; i++, node= reverse? node->prev : node->next)
3225 3 3 ST(i)= GET_TreeRBXS_item_FROM_recent(node)->value;
3228 8 3 for (i= 0; i < n_ret && node != limit; node= reverse? node->prev : node->next) {
8 0 for (i= 0; i < n_ret && node != limit; node= reverse? node->prev : node->next) {
3232 3 5 i++;
3235 0 8 if (node != limit) i++; // for error reporting
3238 0 72 rbtree_node_t *node= (reverse? rbtree_node_right_leaf : rbtree_node_left_leaf)(TreeRBXS_get_root(tree));
3239 0 72 rbtree_node_t *(*step)(rbtree_node_t *)= reverse? rbtree_node_prev : rbtree_node_next;
3240 56 16 if (keys_only) {
3241 374 56 for (i= 0; i < n_ret && node; i++, node= step(node))
374 0 for (i= 0; i < n_ret && node; i++, node= step(node))
3244 0 16 else if (values_only) {
3245 0 0 for (i= 0; i < n_ret && node; i++, node= step(node))
0 0 for (i= 0; i < n_ret && node; i++, node= step(node))
3249 56 16 for (i= 0; i < n_ret && node; node= step(node)) {
56 0 for (i= 0; i < n_ret && node; node= step(node)) {
3256 0 72 if (node) i++; // for error reporting
3258 0 80 if (i != n_ret)
3259 0 0 croak("BUG: expected %ld nodes but found %ld",
3271 1 14 if (tree->hashiterset)
3288 2 59 if (tree->hashiterset)
3306 2 1 if (item && (TreeRBXS_item_get_tree(item) != tree))
0 2 if (item && (TreeRBXS_item_get_tree(item) != tree))
3311 1 2 if (!item) TreeRBXS_iter_rewind(iter);
3331 0 3 if (!SvOK(key))
3334 2 1 if (rbtree_find_all(
3344 0 2 first= (first == last)? NULL : rbtree_node_next(first);
3346 0 2 } while (first);
3377 66 1 RETVAL= cmp_numsplit(apos, apos+alen, a_utf8, bpos, bpos+blen, b_utf8);
3392 47 155 if (newval) {
3400 155 47 : TreeRBXS_item_wrap_key(item);
3409 0 51 if (newval)
3419 0 0 RETVAL= rbtree_node_index(&item->rbnode);
3451 1 11 if (newval) {
3452 0 1 if (!next)
3454 0 1 if (!tree) croak("Node was removed from tree");
3458 5 0 RETVAL= (!next || !tree || next == &tree->recent)? NULL
5 0 RETVAL= (!next || !tree || next == &tree->recent)? NULL
3459 5 7 : GET_TreeRBXS_item_FROM_recent(next);
3471 1 13 if (newval) {
3472 0 1 if (!prev)
3474 0 1 if (!tree) croak("Node was removed from tree");
3478 7 0 RETVAL= (!prev || !tree || prev == &tree->recent)? NULL
7 0 RETVAL= (!prev || !tree || prev == &tree->recent)? NULL
3479 7 7 : GET_TreeRBXS_item_FROM_recent(prev);
3487 0 1 RETVAL= rbtree_node_is_in_tree(&item->rbnode) && item->rbnode.parent->count?
3488 1 4 GET_TreeRBXS_item_FROM_rbnode(item->rbnode.parent) : NULL;
3498 1 14 ST(0)= tree && tree->owner? sv_2mortal(newRV_inc(tree->owner)) : &PL_sv_undef;
1 0 ST(0)= tree && tree->owner? sv_2mortal(newRV_inc(tree->owner)) : &PL_sv_undef;
3505 4 4 RETVAL= rbtree_node_is_in_tree(&item->rbnode) && item->rbnode.left->count?
3506 8 4 GET_TreeRBXS_item_FROM_rbnode(item->rbnode.left) : NULL;
3514 4 4 RETVAL= rbtree_node_is_in_tree(&item->rbnode) && item->rbnode.right->count?
3515 8 4 GET_TreeRBXS_item_FROM_rbnode(item->rbnode.right) : NULL;
3543 1 4 RETVAL= item->rbnode.color;
3551 0 5 RETVAL= item->rbnode.count;
3562 5 1 if (tree) {
3576 10 4 if (items > 1) {
3578 0 10 if (!tree) croak("Node was removed from tree");
3579 0 10 if (SvTRUE(newval))
3595 0 2 if (!tree) croak("Node was removed from tree");
3605 0 0 if (!tree) croak("Node was removed from tree");
3618 2 1 if (tree) {
3642 1 2 if (idx == -1) {
3645 1 0 if (!svec || n != 2 || !svec[0] || !svec[1])
1 0 if (!svec || n != 2 || !svec[0] || !svec[1])
1 0 if (!svec || n != 2 || !svec[0] || !svec[1])
0 1 if (!svec || n != 2 || !svec[0] || !svec[1])
3654 0 2 if (!(node= rbtree_node_child_at_index(TreeRBXS_get_root(tree), idx)))
3657 0 2 if (item->owner) {
3658 0 0 if (item->owner != SvRV(item_sv))
3690 257 0 if (iter->item || iter->tree)
0 257 if (iter->item || iter->tree)
3701 0 257 if ((iter2= TreeRBXS_get_magic_iter(target, 0))) {
3703 0 0 if (items < 2) {
3710 17 240 else if ((item= TreeRBXS_get_magic_item(target, 0))) {
3713 240 0 else if ((tree= TreeRBXS_get_magic_tree(target, 0))) {
3714 13 227 if (iter->recent) {
3715 4 9 lnode= iter->reverse? tree->recent.prev : tree->recent.next;
3717 13 0 : GET_TreeRBXS_item_FROM_recent(lnode);
3721 227 0 : iter->reverse? rbtree_node_right_leaf(TreeRBXS_get_root(tree))
3722 104 123 : rbtree_node_left_leaf(TreeRBXS_get_root(tree));
3723 227 0 if (node)
3727 0 257 if (!tree)
3729 15 242 if (iter->recent && item && !item->recent.next)
15 0 if (iter->recent && item && !item->recent.next)
0 15 if (iter->recent && item && !item->recent.next)
3732 257 0 if (tree->owner)
3751 25 10 RETVAL= iter->item? SvREFCNT_inc_simple_NN(iter->item->value) : &PL_sv_undef;
3767 0 0 RETVAL= !iter->item || !rbtree_node_is_in_tree(&iter->item->rbnode)? &PL_sv_undef
3768 0 1 : newSViv(rbtree_node_index(&iter->item->rbnode));
3776 0 0 RETVAL= iter->tree && iter->tree->owner? newRV_inc(iter->tree->owner) : &PL_sv_undef;
0 0 RETVAL= iter->tree && iter->tree->owner? newRV_inc(iter->tree->owner) : &PL_sv_undef;
3784 19 27 RETVAL= !iter->item;
3800 22 24 size_t pos, n, nret, i, max_count= iter->recent? iter->tree->recent_count : TreeRBXS_get_count(iter->tree);
3803 8 38 rbtree_node_t *(*step)(rbtree_node_t *)= iter->reverse? &rbtree_node_prev : rbtree_node_next;
3805 38 8 if (iter->item) {
3807 28 10 : ((SvPOK(count_sv) && *SvPV_nolen(count_sv) == '*')
15 13 : ((SvPOK(count_sv) && *SvPV_nolen(count_sv) == '*')
0 15 : ((SvPOK(count_sv) && *SvPV_nolen(count_sv) == '*')
3808 6 7 || (SvNOK(count_sv) && SvNV(count_sv) > (NV)PERL_INT_MAX))? max_count
0 6 || (SvNOK(count_sv) && SvNV(count_sv) > (NV)PERL_INT_MAX))? max_count
3810 1 37 if (request < 1) {
3815 1 36 else if (GIMME_V == G_VOID) {
3821 26 10 else if (request == 1 || iter->recent) { // un-optimized loop
10 16 else if (request == 1 || iter->recent) { // un-optimized loop
3822 2 18 nret= ix == 3? request<<1 : request;
3823 0 20 EXTEND(SP, nret);
3824 86 20 for (i= 0; i < nret && iter->item; ) {
86 0 for (i= 0; i < nret && iter->item; ) {
3826 6 80 : ix == 2? iter->item->value
3827 0 80 : sv_2mortal(TreeRBXS_item_wrap_key(iter->item));
3828 46 40 if (ix == 3)
3837 1 15 n= iter->reverse? 1 + pos : max_count - pos;
3838 3 13 if (n > request) n= request;
3840 6 10 nret= (ix == 3)? n<<1 : n;
3841 0 16 EXTEND(SP, nret); // EXTEND macro declares a temp 'ix' internally - GitHub #2
3842 1 15 if (ix == 0) {
3843 2 1 for (i= 0; i < nret && node; i++, node= step(node))
2 0 for (i= 0; i < nret && node; i++, node= step(node))
3846 4 11 else if (ix == 1) {
3847 16 4 for (i= 0; i < nret && node; i++, node= step(node))
16 0 for (i= 0; i < nret && node; i++, node= step(node))
3850 5 6 else if (ix == 2) {
3851 91 5 for (i= 0; i < nret && node; i++, node= step(node))
91 0 for (i= 0; i < nret && node; i++, node= step(node))
3855 70 6 for (i= 0; i < nret && node; node= step(node)) {
70 0 for (i= 0; i < nret && node; node= step(node)) {
3862 0 16 if (i != nret)
3863 0 0 croak("BUG: expected %ld nodes but found %ld", (long) n, (long) (ix == 3? i>>1 : i));
3881 1295 210 RETVAL= !!iter->item;
3889 5 0 if (iter->item) {
3911 0 0 av_push(refs, iter->item? newSViv(rbtree_node_index(&iter->item->rbnode)) : newSV(0));