Branch Coverage

TreeRBXS.xs
Criterion Covered Total %
branch 1097 1764 62.1


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 481400 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 470913 30077 bool is_buffered_key= IS_ITEM_KEY_STORED_IN_EXTRA(src);
110025 360888 bool is_buffered_key= IS_ITEM_KEY_STORED_IN_EXTRA(src);
666 480958 20032 if (src->orig_key_stored || is_buffered_key) {
120070 360888 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 140773 360218 switch (item->key_type) {
815 20032 480959 if (item->orig_key_stored) {
819 500991 0 if (item->value)
837 108 0 if (!rbtree_node_is_in_tree(&item->rbnode))
847 16904 0 for (cur= &item->iter; *cur; cur= &((*cur)->next_iter)) {
848 1680 15224 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 22 1938 if (iter->item == item)
885 1661 277 if (iter->item)
888 1723 215 if (item) {
890 106 1617 if (iter->recent && !item->recent.next)
0 106 if (iter->recent && !item->recent.next)
907 0 1698 if (!iter->tree)
910 103 1595 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 825 770 else if (ofs == 1) {
934 812 13 if (item) {
936 389 423 node= iter->reverse? rbtree_node_prev(node) : rbtree_node_next(node);
950 744 26 : !iter->reverse? rbtree_node_index(&item->rbnode)
952 384 360 : cnt - 1 - rbtree_node_index(&item->rbnode);
953 766 4 if (ofs > 0) {
954 603 163 newpos= (UV)ofs < (cnt-pos)? pos + ofs : cnt;
957 4 0 newpos= (pos < o)? 0 : pos - o;
960 376 394 if (iter->reverse) newpos= cnt - 1 - newpos;
982 79 18 for (iter= item->iter, item->iter= NULL; iter; iter= next) {
984 8 71 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 68 else if (flags & ONLY_ADVANCE_RECENT) {
1021 29 39 if (iter->reverse) { // iterating high to low
1022 25 4 if (!prev_item) {
1024 20 5 if (!node) {
1038 26 13 if (!next_item) {
1040 16 10 if (!node) {
1063 98 0 if (in_tree) {
1064 14 84 if (tree->prev_inserted_item == item) {
1069 16 82 if (item->iter)
1072 25 73 if (item->recent.next)
1079 71 27 if (!item->owner)
1081 27 0 else if (in_tree)
1091 6 500892 while (iter) {
1102 500812 80 if (!item->owner)
1109 19 243 if (iter->item)
1111 262 0 if (iter->tree) {
1112 5 257 if (iter->tree->hashiter == iter)
1123 8 105 if (tree->compare_callback)
1125 5 108 if (tree->hashiter)
1156 371 5 if (node && cmp == 0) {
329 42 if (node && cmp == 0) {
1167 2 312 if (tree->allowed_duplicates)
1170 8 306 if (step)
1179 1 14 if (tree->allowed_duplicates)
1182 10 5 if (step)
1197 7 0 if (node && cmp > 0)
2 5 if (node && cmp > 0)
1203 7 0 if (node && cmp < 0)
6 1 if (node && cmp < 0)
1208 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);
1224 500671 345 if (tree->prev_inserted_trend >= INSERT_TREND_TRIGGER) {
1225 470541 30130 if (tree->prev_inserted_trend > INSERT_TREND_CAP)
1229 14 500657 if (cmp == 0) {
1231 1 13 if (overwrite) {
1232 1 0 if (tree->prev_inserted_dup) {
1235 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)
1241 13 0 } else if (tree->allow_duplicates)
1246 500607 50 else if (cmp > 0) {
1248 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) {
1256 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) {
1270 15275 97 if (hint && cmp == 0) {
15223 52 if (hint && cmp == 0) {
1271 25 27 if (overwrite) {
1273 23 2 if (tree->allowed_duplicates) {
1275 0 3 if (!rbtree_find_all(
1284 6 3 while (last != first) {
1295 23 3 if (oldval_out)
1301 6 20 if (item->orig_key_stored) {
1304 6 0 if (sv_cmp(orig_key, new_key)) {
1311 25 1 if (tree->track_recent || item->recent.next)
0 25 if (tree->track_recent || item->recent.next)
1314 21 6 } else if (tree->allow_duplicates) {
1320 8 26 if (tree->track_recent)
1326 3 3 if (item == tree->prev_inserted_item)
1334 97 500853 TREERBXS_INSERT_ITEM_AT_NODE(tree, item, hint, cmp);
493315 7538 TREERBXS_INSERT_ITEM_AT_NODE(tree, item, hint, cmp);
72 500878 TREERBXS_INSERT_ITEM_AT_NODE(tree, item, hint, cmp);
1338 347 500663 if (tree->prev_inserted_trend < INSERT_TREND_TRIGGER && tree->prev_inserted_item) {
246 101 if (tree->prev_inserted_trend < INSERT_TREND_TRIGGER && tree->prev_inserted_item) {
1340 238 8 if (item == tree->prev_inserted_item
1341 57 181 || item->rbnode.parent == &tree->prev_inserted_item->rbnode
1342 50 7 || item->rbnode.left == &tree->prev_inserted_item->rbnode
1343 11 39 || item->rbnode.right == &tree->prev_inserted_item->rbnode
1346 24 15 } else if (tree->prev_inserted_trend)
1358 110 1 if (item->recent.next != node_after) {
1359 6 104 if (item->recent.next) {
1372 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)
1381 35 0 if (item->recent.next) {
1383 2 33 if (item->iter)
1398 15 0 if (lim >= 0 && tree->recent_count > lim) {
15 0 if (lim >= 0 && tree->recent_count > lim) {
1401 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++) {
1403 0 17 if (nodes_out)
1409 0 15 if (i != n)
1427 165680 55396 return diff < 0? -1 : diff > 0? 1 : 0; /* shrink from IV to int might lose upper bits */
1433 55321 165526 return diff < 0? -1 : diff > 0? 1 : 0;
1441 39502 632795 return cmp? cmp : alen < blen? -1 : alen > blen? 1 : 0;
35662 3840 return cmp? cmp : alen < blen? -1 : alen > blen? 1 : 0;
1452 40307 1 while (apos < alim && bpos < blim) {
40293 14 while (apos < alim && bpos < blim) {
1454 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))
1458 40627 9 while (apos < alim && !isdigit(*apos)) apos++;
343 40284 while (apos < alim && !isdigit(*apos)) apos++;
1460 40478 9 while (bpos < blim && !isdigit(*bpos)) bpos++;
194 40284 while (bpos < blim && !isdigit(*bpos)) bpos++;
1464 40211 82 if (alen || blen) {
10 40201 if (alen || blen) {
1467 10 82 if (alen == 0) return -1;
1468 46 36 if (blen == 0) return 1;
1471 0 36 if (a_utf8 != b_utf8) {
1473 0 0 : bytes_cmp_utf8((const U8*) amark, alen, (const U8*) bmark, blen);
1474 0 0 if (cmp) return cmp;
1479 36 0 if (cmp) return cmp;
1480 0 0 if (alen < blen) return -1;
1481 0 0 if (alen > blen) return -1;
1485 40197 4 if (!(apos < alim && bpos < blim)) break;
40197 0 if (!(apos < alim && bpos < blim)) break;
1488 40387 0 while (apos < alim && *apos == '0') apos++;
190 40197 while (apos < alim && *apos == '0') apos++;
1489 40325 0 while (bpos < blim && *bpos == '0') bpos++;
128 40197 while (bpos < blim && *bpos == '0') bpos++;
1493 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))
1497 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))) {
1498 1 40141 if (apos == alim) return -1;
1499 0 40141 if (bpos == blim) return 1;
1503 48642 40018 while (apos < alim && isdigit(*apos)) apos++;
48519 123 while (apos < alim && isdigit(*apos)) apos++;
1504 48606 40039 while (bpos < blim && isdigit(*bpos)) bpos++;
48504 102 while (bpos < blim && isdigit(*bpos)) bpos++;
1508 52 40089 if (alen < blen) return -1;
1509 67 40022 if (alen > blen) return 1;
1516 1 18 if (bpos < blim) return -1;
1517 14 4 if (apos < alim) return 1;
1572 0 221330 PUSHMARK(SP);
1573 0 221330 EXTEND(SP, 2);
1577 0 221330 if (call_sv(tree->compare_callback, G_SCALAR) != 1)
1584 165973 55357 return (int)(ret < 0? -1 : ret > 0? 1 : 0);
1597 0 20079 PUSHMARK(SP);
1598 0 20079 XPUSHs(orig_key);
1620 113 0 if (mg->mg_ptr) {
1630 108 0 if (mg->mg_ptr) {
1639 257 0 if (mg->mg_ptr)
1664 0 501536 if (!sv_isobject(obj)) {
1665 0 0 if (flags & OR_DIE)
1670 501423 113 if (SvMAGICAL(sv) && (magic= mg_findext(sv, PERL_MAGIC_ext, &TreeRBXS_magic_vt)))
501423 0 if (SvMAGICAL(sv) && (magic= mg_findext(sv, PERL_MAGIC_ext, &TreeRBXS_magic_vt)))
1673 113 0 if (flags & AUTOCREATE) {
1682 0 0 else if (flags & OR_DIE)
1693 35 694 if (!sv_isobject(obj)) {
1694 0 35 if (flags & OR_DIE)
1699 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)))
1702 0 242 if (flags & OR_DIE)
1714 75 223 if (!item)
1717 118 105 if (item->owner)
1733 24 902 if (!item)
1735 159 743 if (item->orig_key_stored) {
1785 0 2241 if (!sv_isobject(obj)) {
1786 0 0 if (flags & OR_DIE)
1791 2241 0 if (SvMAGICAL(sv) && (magic= mg_findext(sv, PERL_MAGIC_ext, &TreeRBXS_iter_magic_vt)))
1727 514 if (SvMAGICAL(sv) && (magic= mg_findext(sv, PERL_MAGIC_ext, &TreeRBXS_iter_magic_vt)))
1794 257 257 if (flags & AUTOCREATE) {
1803 0 257 else if (flags & OR_DIE)
1812 65 0 if (!(method_gv= gv_fetchmethod(stash, name))
1813 0 65 || !(method_cv= GvCV(method_gv)))
1820 348 0 SvUPGRADE(name, SVt_PVNV);
1834 41 0 if (array && SvTYPE(array) == SVt_PVAV)
3 38 if (array && SvTYPE(array) == SVt_PVAV)
1836 38 0 else if (array && SvROK(array) && SvTYPE(SvRV(array)) == SVt_PVAV)
38 0 else if (array && SvROK(array) && SvTYPE(SvRV(array)) == SVt_PVAV)
38 0 else if (array && SvROK(array) && SvTYPE(SvRV(array)) == SVt_PVAV)
1843 1 40 if (!vec) {
1844 0 1 if (n == 0) /* don't return a NULL for an empty array, but doesn't need to be a real pointer */
1849 0 1 Newx(vec, n, SV*);
1851 10 1 for (i= 0; i < n; i++) {
1853 10 0 vec[i]= el? *el : NULL;
1857 41 0 if (len) *len= n;
1890 140 113 for (i= out_i= 0; i < attr_list_len; i += 2) {
1895 0 140 if (i + 1 == attr_list_len)
1898 0 140 if (!SvOK(val))
1901 29 0 case 2: if (strcmp("kv", attrname) == 0) { kv_sv= val; break; }
1903 5 0 case 4: if (strcmp("keys", attrname) == 0) { keys_sv= val; break; }
1905 2 1 case 6: if (strcmp("values", attrname) == 0) { values_sv= val; break; }
1906 1 0 else if (strcmp("recent", attrname) == 0) { recent_sv= val; break; }
1908 24 0 case 8: if (strcmp("key_type", attrname) == 0) { key_type_sv= val; break; }
1909 0 0 else if (strcmp("hashiter", attrname) == 0) { hashiter_sv= val; break; }
1911 56 0 case 10: if (strcmp("compare_fn", attrname) == 0) { compare_fn_sv= val; break; }
1913 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; }
1914 1 0 else if (strcmp("recent_limit", attrname) == 0) {
1915 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;
1919 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; }
1921 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; }
1923 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; }
1925 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; }
1929 0 0 if (i > out_i) {
1938 24 89 if (key_type_sv) {
1940 0 24 if (key_type < 0)
1946 56 57 if (compare_fn_sv) {
1948 0 56 if (cmp_id < 0)
1951 21 36 } else if (key_type_sv) {
1954 10 11 : key_type == KEY_TYPE_FLOAT? CMP_FLOAT
1955 7 3 : key_type == KEY_TYPE_BSTR? CMP_MEMCMP
1956 4 3 : key_type == KEY_TYPE_USTR? CMP_STR
1957 2 2 : key_type == KEY_TYPE_ANY? CMP_PERL /* use Perl's cmp operator */
1964 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)
1968 8 0 if (key_type != KEY_TYPE_CLAIM) tree->key_type= KEY_TYPE_ANY;
1978 39 1 if (key_type != KEY_TYPE_CLAIM) tree->key_type= KEY_TYPE_ANY;
1999 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)
2008 84 29 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) {
2013 29 5 if (kv_sv) {
2014 29 0 if (keys_sv || values_sv)
0 29 if (keys_sv || values_sv)
2016 0 29 if (!(key_vec= unwrap_array(kv_sv, &num_kv)))
2018 0 29 if (num_kv & 1)
2024 5 29 if (keys_sv) {
2025 0 5 if (!(key_vec= unwrap_array(keys_sv, &num_kv)))
2029 2 32 if (values_sv) {
2031 0 2 if (!key_vec)
2033 0 2 if (!(val_vec= unwrap_array(values_sv, &nvals)))
2035 0 2 if (nvals != num_kv)
2040 1 33 if (recent_sv)
2042 160 34 for (key_lim= key_vec + num_kv * key_step; key_vec < key_lim; key_vec += key_step, val_vec += val_step) {
2043 142 18 TreeRBXS_init_tmp_item(&stack_item, tree, (*key_vec? *key_vec : &PL_sv_undef), (val_vec? *val_vec : &PL_sv_undef));
160 0 TreeRBXS_init_tmp_item(&stack_item, tree, (*key_vec? *key_vec : &PL_sv_undef), (val_vec? *val_vec : &PL_sv_undef));
2052 1 112 if (recent_sv) {
2055 0 1 if (!rvec) croak("'recent' must be an arrayref");
2056 23 1 for (i= 0; i < n; i++) {
2057 0 23 if (!looks_like_integer(rvec[i]))
2060 23 0 if (idx < 0 || idx >= nodecount)
0 23 if (idx < 0 || idx >= nodecount)
2063 0 23 if (!node) croak("BUG: access node[idx]");
2069 0 113 if (hashiter_sv) {
2072 0 0 if (!looks_like_integer(hashiter_sv))
2075 0 0 if (idx < 0 || idx >= nodecount)
0 0 if (idx < 0 || idx >= nodecount)
2078 0 0 if (!node) croak("BUG: access node[idx]");
2089 7 0 if (!version || !SvOK(version))
0 7 if (!version || !SvOK(version))
2112 0 110 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) {
2116 110 0 else if (SvPOK(obj_or_pkg) && (pkg= gv_stashsv(obj_or_pkg, 0))) {
110 0 else if (SvPOK(obj_or_pkg) && (pkg= gv_stashsv(obj_or_pkg, 0))) {
2117 0 110 if (!sv_derived_from(obj_or_pkg, "Tree::RB::XS"))
2125 0 0 croak("%s: first arg must be package name or blessed object", ix == 1? "_init_tree":"new");
2128 4 106 if (items == 2) {
2131 1 3 if (!SvROK(first) || SvTYPE(SvRV(first)) == SVt_PVCV) {
0 1 if (!SvROK(first) || SvTYPE(SvRV(first)) == SVt_PVCV) {
2138 1 0 else if (SvTYPE(SvRV(first)) == SVt_PVHV) {
2143 0 1 Newx(attr_list, attr_len, SV*);
2146 3 1 while ((ent= hv_iternext(attrhv)) && i < attr_len) {
3 0 while ((ent= hv_iternext(attrhv)) && i < attr_len) {
2159 0 110 if (tree->owner != (SV*) obj_hv)
2163 0 110 if (n_unknown) {
2165 0 0 if (ix == 0)
2168 0 0 if (attr_list != PL_stack_base+ax+1) {
2169 0 0 EXTEND(SP, n_unknown);
0 0 EXTEND(SP, n_unknown);
2170 0 0 for (i= 0; i < n_unknown; i++)
2174 0 110 i= ix == 0? 1 : n_unknown;
2201 0 4 while ((pos= hv_iternext(treehv))) {
2205 0 4 if (tree->recent_limit >= 0) {
2211 2 2 if (nodecount) {
2237 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)) {
2259 0 2 if (i < nodecount) croak("BUG: too few nodes in tree");
2260 0 2 if (node) croak("BUG: too many nodes in tree");
2271 1 1 if (tree->recent_count) {
2277 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) {
2282 0 1 if (i != 0) croak("BUG: too few recent-tracked nodes");
2283 0 1 if (pos != root) croak("BUG: too many recent-tracked nodes");
2286 0 2 if (tree->hashiter && tree->hashiter->item) {
0 0 if (tree->hashiter && tree->hashiter->item) {
2290 0 0 if (pointing_at) {
2300 2 2 if (cmp_id == CMP_SUB) {
2301 0 2 if (!cloning)
2309 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)
2310 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",
2315 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));
2319 0 3 if (version < 0 || version > 0x7FFFFFFF)
2325 3 0 if (key_type < 1 || key_type > 255)
0 3 if (key_type < 1 || key_type > 255)
2329 3 0 if (cmp_id < 1 || cmp_id > 255)
0 3 if (cmp_id < 1 || cmp_id > 255)
2334 0 3 | (tree->compat_list_get? 2 : 0)
2335 1 2 | (tree->track_recent? 4 : 0)
2336 0 3 | (tree->lookup_updates_recent? 8 : 0)
2337 0 3 | (tree->keys_in_recent_order? 0x10 : 0);
2341 0 3 EXTEND(SP, 2);
2360 3 0 if (!SvROK(objref) || SvTYPE(SvRV(objref)) != SVt_PVHV)
0 3 if (!SvROK(objref) || SvTYPE(SvRV(objref)) != SVt_PVHV)
2363 0 3 if (tree->owner != SvRV(objref))
2368 0 3 if (sb_len < 10)
2375 0 3 if (version <= 0)
2377 0 3 if (version > get_integer_version())
2387 3 0 if (key_type <= 0 || key_type > KEY_TYPE_MAX)
0 3 if (key_type <= 0 || key_type > KEY_TYPE_MAX)
2391 3 0 if (cmp_id <= 0 || cmp_id > CMP_MAX)
0 3 if (cmp_id <= 0 || cmp_id > CMP_MAX)
2395 3 0 if (cmp_id == CMP_FOLDCASE || cmp_id == CMP_NUMSPLIT_FOLDCASE)
0 3 if (cmp_id == CMP_FOLDCASE || cmp_id == CMP_NUMSPLIT_FOLDCASE)
2399 0 3 Newx(attr_list, attr_len, SV*);
2404 1 2 if (cmp_id == CMP_SUB) {
2405 0 1 if (!cloning) croak("compare_fn lookup is forbidden unless cloning");
2407 1 0 for (i= attr_len-2; i >= 0; i-= 2) {
2408 1 0 if (strcmp(SvPV_nolen(attr_list[i]), "compare_fn") == 0) {
2411 1 0 if (gv && GvCV(gv))
1 0 if (gv && GvCV(gv))
2418 0 1 if (i < 0)
2423 0 3 if (n_unknown) {
2426 0 0 for (i= 0; i < n_unknown-1; i += 2)
2427 0 0 if (!hv_store_ent(obj, attr_list[i], (tmpsv= newSVsv(attr_list[i+1])), 0))
2449 2 16 : sv_2mortal(new_enum_dualvar(aTHX_ id, newSVpv(get_cmp_name(id), 0)));
2457 4 11 if (items > 1) {
2470 0 2 if (items > 1) {
2474 0 2 ST(0)= tree->compat_list_get? &PL_sv_yes : &PL_sv_no;
2483 0 2 if (items > 1) {
2487 2 0 ST(0)= tree->track_recent? &PL_sv_yes : &PL_sv_no;
2496 1 2 if (items > 1) {
2500 0 2 ST(0)= tree->lookup_updates_recent? &PL_sv_yes : &PL_sv_no;
2509 1 0 if (items > 1) {
2513 0 0 ST(0)= tree->keys_in_recent_order? &PL_sv_yes : &PL_sv_no;
2521 0 56 RETVAL= TreeRBXS_get_count(tree);
2529 0 9 RETVAL= tree->recent_count;
2538 2 2 if (newval) {
2539 1 1 if (!SvOK(newval)) {
2541 1 0 } else if (!looks_like_number(newval) || SvIV(newval) < 0) {
0 1 } else if (!looks_like_number(newval) || SvIV(newval) < 0) {
2550 1 1 : sv_2mortal(newSViv(tree->recent_limit));
2558 0 1 EXTEND(SP, 5);
2579 0 500341 if (!SvOK(key))
2583 100132 1 ST(0)= ix == 0? sv_2mortal(newSViv(inserted? rbtree_node_index(&inserted->rbnode) : -1))
2584 100133 400208 : ix == 1? (oldval? oldval : &PL_sv_undef)
17 400185 : ix == 1? (oldval? oldval : &PL_sv_undef)
2585 400202 6 : (inserted? sv_2mortal(TreeRBXS_wrap_item(inserted)) : &PL_sv_undef);
4 2 : (inserted? sv_2mortal(TreeRBXS_wrap_item(inserted)) : &PL_sv_undef);
2600 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))) {
2609 515 4 while (i < lim) {
2612 0 515 if (av) {
2614 0 0 if (!el) croak("Tree->insert_multi does not support tied or sparse arrays");
2617 0 0 if (i < lim) {
2619 0 0 if (!el) croak("Tree->insert_multi does not support tied or sparse arrays");
2625 515 0 if (++i < lim) {
2630 0 515 if (!SvOK(key))
2637 5 510 if (ix == 0? (inserted != NULL) : (oldval == NULL))
507 8 if (ix == 0? (inserted != NULL) : (oldval == NULL))
2640 0 4 RETVAL= added;
2657 4 4 for (i= 1; i < items; i++) {
2660 1 3 if (tree->allowed_duplicates) {
2675 2 1 if (node && cmp == 0)
2 0 if (node && cmp == 0)
2679 0 4 RETVAL= total;
2710 0 370 if (!SvOK(key))
2713 6 364 if (ix >> 4) {
2716 0 6 if (mode_sv)
2719 61 303 mode= mode_sv? parse_lookup_mode(mode_sv) : GET_EQ;
2720 0 364 if (mode < 0)
2725 249 121 if (ix >= 3)
2726 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;
2736 339 31 if (item) {
2737 1 338 if (tree->lookup_updates_recent)
2739 0 339 if (GIMME_V == G_VOID)
2741 50 289 else if (ix <= 1) {
2742 40 10 if (ix == 0) { // return node
2749 273 16 } else if (ix == 2) { // return value
2772 0 1 if (!SvOK(key))
2775 1 0 if (rbtree_find_all(
2782 0 1 EXTEND(SP, count);
2783 6 1 for (i= 0; i < count; i++) {
2786 0 6 if (tree->lookup_updates_recent)
2804 0 25 if (!SvOK(key1))
2807 0 25 if ((item= TreeRBXS_get_magic_item(key1, 0))) {
2808 0 0 if (!TreeRBXS_is_member(tree, item))
2813 22 3 if (rbtree_find_all(
2820 1 21 if (key2)
2826 2 1 if (key2) {
2834 3 22 if (key2 && first) {
3 0 if (key2 && first) {
2835 0 3 if ((item= TreeRBXS_get_magic_item(key2, 0))) {
2836 0 0 if (!TreeRBXS_is_member(tree, item))
2841 2 1 if (rbtree_find_all(
2855 3 0 if (last && rbtree_node_index(first) > rbtree_node_index(last))
1 2 if (last && rbtree_node_index(first) > rbtree_node_index(last))
2860 25 0 if (first && last) {
23 2 if (first && last) {
2863 3 23 first= (first == last)? NULL : rbtree_node_next(first);
2866 3 23 } while (first);
2868 6 19 RETVAL= i;
2885 33 23 for (i= 1; i < items; i++) {
2888 0 33 if (++i >= items)
2893 3 0 case 'a': if (strncmp(opt_name, "max", len) == 0) { max_sv= ST(i); continue; }
2894 7 0 case 'i': if (strncmp(opt_name, "min", len) == 0) { min_sv= ST(i); continue; }
2898 23 0 if (strncmp(opt_name, "offset", len) == 0) { offset_sv= ST(i); continue; }
2903 1 22 if (!TreeRBXS_get_count(tree))
2906 7 15 if (min_sv) {
2908 6 1 if (!min_item) {
2910 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))) {
2912 0 1 if (!min_item) croak("Iterator for 'min' is not referencing a tree node");
2921 3 19 if (max_sv) {
2923 2 1 if (!max_item) {
2925 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))) {
2927 0 1 if (!max_item) croak("Iterator for 'max' is not referencing a tree node");
2936 22 0 if (offset_sv) {
2946 18 4 if (tree->key_type == KEY_TYPE_INT) {
2949 1 17 if (SvUOK(offset_sv) && SvUV(offset_sv) > IV_MAX)
1 0 if (SvUOK(offset_sv) && SvUV(offset_sv) > IV_MAX)
2952 0 17 if (offset_iv == 0)
2957 11 6 if (positive) {
2958 3 8 IV max_key= (max_item? max_item : last_item)->keyunion.ikey;
2959 1 10 if (IV_MAX - offset_iv < max_key)
2962 3 3 IV min_key= (min_item? min_item : first_item)->keyunion.ikey;
2963 1 5 if (IV_MIN - offset_iv > min_key)
2967 2 2 else if (tree->key_type == KEY_TYPE_FLOAT) {
2969 0 2 if (offset_nv == 0.0)
2982 12 5 edge_item= positive? max_item : min_item;
2983 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))) {
2988 1 0 *final_item= (positive? (min_item? min_item : first_item)
2989 1 3 : (max_item? max_item : last_item)),
0 3 : (max_item? max_item : last_item)),
2993 9 0 if (intmode) {
2995 1 8 if (positive? (newval < boundary_item->keyunion.ikey)
4 5 if (positive? (newval < boundary_item->keyunion.ikey)
3001 0 0 if (positive? (newval < boundary_item->keyunion.nkey)
0 0 if (positive? (newval < boundary_item->keyunion.nkey)
3031 5 0 if (intmode) edge_item->keyunion.ikey= stack_item.keyunion.ikey;
3033 1 4 if (found_identical) {
3037 1 0 if (!tree->allow_duplicates) {
3041 0 1 node= (node == search[1])? NULL : rbtree_node_next(node);
3042 1 0 if (item != edge_item)
3044 0 1 } while (node);
3049 3 1 else if (search[0])
3053 5 0 if (!next || edge_item == final_item)
0 5 if (!next || edge_item == final_item)
3062 1 3 *(positive? &max_item : &min_item)= edge_item;
3065 7 10 rbtree_node_t *node= min_item? &min_item->rbnode : &first_item->rbnode;
3066 3 14 rbtree_node_t *end= max_item? &max_item->rbnode : &last_item->rbnode;
3068 36 5 if (intmode)
3072 17 24 if (node == end) break;
3092 0 0 bool keep= !(GIMME_V == G_VOID || GIMME_V == G_SCALAR);
0 0 bool keep= !(GIMME_V == G_VOID || GIMME_V == G_SCALAR);
3096 0 0 if (max_count >= 0 && tree->recent_count > max_count) {
0 0 if (max_count >= 0 && tree->recent_count > max_count) {
3098 0 0 if (keep) {
3099 0 0 EXTEND(SP, n);
0 0 EXTEND(SP, n);
3106 0 0 if (GIMME_V == G_SCALAR)
3149 1 14 if (ofs < 0) ofs += TreeRBXS_get_count(tree);
3160 8 0 : GET_TreeRBXS_item_FROM_rbnode(TreeRBXS_get_root(tree));
3169 1 12 if (newval) {
3170 0 1 if (!TreeRBXS_is_member(tree, newval))
3175 9 4 : GET_TreeRBXS_item_FROM_recent(tree->recent.next);
3184 1 18 if (newval) {
3185 0 1 if (!TreeRBXS_is_member(tree, newval))
3190 15 4 : GET_TreeRBXS_item_FROM_recent(tree->recent.prev);
3204 8 72 size_t n_ret, i, node_count= tree->keys_in_recent_order? tree->recent_count : TreeRBXS_get_count(tree);
3210 0 80 if (GIMME_V == G_VOID) {
3213 0 80 else if (GIMME_V == G_SCALAR) {
3218 19 61 n_ret= want_kv? node_count*2 : node_count;
3219 0 80 EXTEND(SP, n_ret);
3220 8 72 if (tree->keys_in_recent_order) {
3221 3 5 struct dllist_node *node= reverse? tree->recent.prev : tree->recent.next;
3223 3 5 if (keys_only) {
3224 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)
3225 3 5 ST(i)= sv_2mortal(TreeRBXS_item_wrap_key(GET_TreeRBXS_item_FROM_recent(node)));
3227 2 3 else if (values_only) {
3228 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)
3229 3 3 ST(i)= GET_TreeRBXS_item_FROM_recent(node)->value;
3232 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) {
3236 3 5 i++;
3239 0 8 if (node != limit) i++; // for error reporting
3242 0 72 rbtree_node_t *node= (reverse? rbtree_node_right_leaf : rbtree_node_left_leaf)(TreeRBXS_get_root(tree));
3243 0 72 rbtree_node_t *(*step)(rbtree_node_t *)= reverse? rbtree_node_prev : rbtree_node_next;
3244 56 16 if (keys_only) {
3245 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))
3248 0 16 else if (values_only) {
3249 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))
3253 56 16 for (i= 0; i < n_ret && node; node= step(node)) {
56 0 for (i= 0; i < n_ret && node; node= step(node)) {
3260 0 72 if (node) i++; // for error reporting
3262 0 80 if (i != n_ret)
3263 0 0 croak("BUG: expected %ld nodes but found %ld",
3275 1 14 if (tree->hashiterset)
3292 2 59 if (tree->hashiterset)
3310 2 1 if (item && (TreeRBXS_item_get_tree(item) != tree))
0 2 if (item && (TreeRBXS_item_get_tree(item) != tree))
3315 1 2 if (!item) TreeRBXS_iter_rewind(iter);
3335 0 3 if (!SvOK(key))
3338 2 1 if (rbtree_find_all(
3348 0 2 first= (first == last)? NULL : rbtree_node_next(first);
3350 0 2 } while (first);
3381 66 1 RETVAL= cmp_numsplit(apos, apos+alen, a_utf8, bpos, bpos+blen, b_utf8);
3396 47 155 if (newval) {
3404 155 47 : TreeRBXS_item_wrap_key(item);
3413 0 51 if (newval)
3423 0 0 RETVAL= rbtree_node_index(&item->rbnode);
3455 1 11 if (newval) {
3456 0 1 if (!next)
3458 0 1 if (!tree) croak("Node was removed from tree");
3462 5 0 RETVAL= (!next || !tree || next == &tree->recent)? NULL
5 0 RETVAL= (!next || !tree || next == &tree->recent)? NULL
3463 5 7 : GET_TreeRBXS_item_FROM_recent(next);
3475 1 13 if (newval) {
3476 0 1 if (!prev)
3478 0 1 if (!tree) croak("Node was removed from tree");
3482 7 0 RETVAL= (!prev || !tree || prev == &tree->recent)? NULL
7 0 RETVAL= (!prev || !tree || prev == &tree->recent)? NULL
3483 7 7 : GET_TreeRBXS_item_FROM_recent(prev);
3491 0 1 RETVAL= rbtree_node_is_in_tree(&item->rbnode) && item->rbnode.parent->count?
3492 1 4 GET_TreeRBXS_item_FROM_rbnode(item->rbnode.parent) : NULL;
3502 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;
3509 4 4 RETVAL= rbtree_node_is_in_tree(&item->rbnode) && item->rbnode.left->count?
3510 8 4 GET_TreeRBXS_item_FROM_rbnode(item->rbnode.left) : NULL;
3518 4 4 RETVAL= rbtree_node_is_in_tree(&item->rbnode) && item->rbnode.right->count?
3519 8 4 GET_TreeRBXS_item_FROM_rbnode(item->rbnode.right) : NULL;
3547 1 4 RETVAL= item->rbnode.color;
3555 0 5 RETVAL= item->rbnode.count;
3566 5 1 if (tree) {
3580 10 4 if (items > 1) {
3582 0 10 if (!tree) croak("Node was removed from tree");
3583 0 10 if (SvTRUE(newval))
3599 0 2 if (!tree) croak("Node was removed from tree");
3609 0 0 if (!tree) croak("Node was removed from tree");
3622 2 1 if (tree) {
3646 1 2 if (idx == -1) {
3649 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])
3659 0 2 if (!(node= rbtree_node_child_at_index(TreeRBXS_get_root(tree), idx)))
3662 0 2 if (item->owner) {
3663 0 0 if (item->owner != SvRV(item_sv))
3698 257 0 if (iter->item || iter->tree)
0 257 if (iter->item || iter->tree)
3709 0 257 if ((iter2= TreeRBXS_get_magic_iter(target, 0))) {
3711 0 0 if (items < 2) {
3718 17 240 else if ((item= TreeRBXS_get_magic_item(target, 0))) {
3721 240 0 else if ((tree= TreeRBXS_get_magic_tree(target, 0))) {
3722 13 227 if (iter->recent) {
3723 4 9 lnode= iter->reverse? tree->recent.prev : tree->recent.next;
3725 13 0 : GET_TreeRBXS_item_FROM_recent(lnode);
3729 227 0 : iter->reverse? rbtree_node_right_leaf(TreeRBXS_get_root(tree))
3730 104 123 : rbtree_node_left_leaf(TreeRBXS_get_root(tree));
3731 227 0 if (node)
3735 0 257 if (!tree)
3737 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)
3740 257 0 if (tree->owner)
3759 25 10 RETVAL= iter->item? SvREFCNT_inc_simple_NN(iter->item->value) : &PL_sv_undef;
3775 0 0 RETVAL= !iter->item || !rbtree_node_is_in_tree(&iter->item->rbnode)? &PL_sv_undef
3776 0 1 : newSViv(rbtree_node_index(&iter->item->rbnode));
3784 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;
3792 19 27 RETVAL= !iter->item;
3808 22 24 size_t pos, n, nret, i, max_count= iter->recent? iter->tree->recent_count : TreeRBXS_get_count(iter->tree);
3811 8 38 rbtree_node_t *(*step)(rbtree_node_t *)= iter->reverse? &rbtree_node_prev : rbtree_node_next;
3813 38 8 if (iter->item) {
3815 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) == '*')
3816 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
3818 1 37 if (request < 1) {
3823 1 36 else if (GIMME_V == G_VOID) {
3829 26 10 else if (request == 1 || iter->recent) { // un-optimized loop
10 16 else if (request == 1 || iter->recent) { // un-optimized loop
3830 2 18 nret= ix == 3? request<<1 : request;
3831 0 20 EXTEND(SP, nret);
3832 86 20 for (i= 0; i < nret && iter->item; ) {
86 0 for (i= 0; i < nret && iter->item; ) {
3834 6 80 : ix == 2? iter->item->value
3835 0 80 : sv_2mortal(TreeRBXS_item_wrap_key(iter->item));
3836 46 40 if (ix == 3)
3845 1 15 n= iter->reverse? 1 + pos : max_count - pos;
3846 3 13 if (n > request) n= request;
3848 6 10 nret= (ix == 3)? n<<1 : n;
3849 0 16 EXTEND(SP, nret); // EXTEND macro declares a temp 'ix' internally - GitHub #2
3850 1 15 if (ix == 0) {
3851 2 1 for (i= 0; i < nret && node; i++, node= step(node))
2 0 for (i= 0; i < nret && node; i++, node= step(node))
3854 4 11 else if (ix == 1) {
3855 16 4 for (i= 0; i < nret && node; i++, node= step(node))
16 0 for (i= 0; i < nret && node; i++, node= step(node))
3858 5 6 else if (ix == 2) {
3859 91 5 for (i= 0; i < nret && node; i++, node= step(node))
91 0 for (i= 0; i < nret && node; i++, node= step(node))
3863 70 6 for (i= 0; i < nret && node; node= step(node)) {
70 0 for (i= 0; i < nret && node; node= step(node)) {
3870 0 16 if (i != nret)
3871 0 0 croak("BUG: expected %ld nodes but found %ld", (long) n, (long) (ix == 3? i>>1 : i));
3889 1326 210 RETVAL= !!iter->item;
3897 5 0 if (iter->item) {
3919 0 0 av_push(refs, iter->item? newSViv(rbtree_node_index(&iter->item->rbnode)) : newSV(0));