Branch Coverage

src/xs/clone.cc
Criterion Covered Total %
branch 96 146 65.7


line true false branch
29 38 0 Sv ret = Sv::create();
32 10 28 if (flags & CloneFlags::TRACK_REFS) {
35 10 0 _clone(aTHX_ ret, source, crossdata, 0);
37 2 10 for (const auto& row : data.weakrefs) { // post process weak refs that appeared before their strong refs
38 2 0 auto it = data.map.find(row.key);
39 1 1 if (it == end) continue;
40 1 0 SvSetSV_nosteal(row.dest, it->second);
1 0 SvSetSV_nosteal(row.dest, it->second);
41 1 0 sv_rvweaken(row.dest);
44 26 2 else _clone(aTHX_ ret, source, crossdata, 0);
50 2 2152 if (depth > CLONE_MAX_DEPTH) throw std::invalid_argument(
51 2 0 std::string("clone: max depth (") + std::to_string(CLONE_MAX_DEPTH) + ") reached, it looks like you passed a cycled structure"
2 0 std::string("clone: max depth (") + std::to_string(CLONE_MAX_DEPTH) + ") reached, it looks like you passed a cycled structure"
2 0 std::string("clone: max depth (") + std::to_string(CLONE_MAX_DEPTH) + ") reached, it looks like you passed a cycled structure"
2 0 std::string("clone: max depth (") + std::to_string(CLONE_MAX_DEPTH) + ") reached, it looks like you passed a cycled structure"
52 2 0 );
54 1051 1101 if (SvROK(source)) { // reference
58 1049 2 if (val_type == SVt_PVCV || val_type == SVt_PVIO) { // CV and IO cannot be copied - just set reference to the same SV
2 1047 if (val_type == SVt_PVCV || val_type == SVt_PVIO) { // CV and IO cannot be copied - just set reference to the same SV
59 4 0 SvSetSV_nosteal(dest, source);
4 0 SvSetSV_nosteal(dest, source);
60 2 2 if (SvWEAKREF(source)) sv_rvweaken(dest);
2 0 if (SvWEAKREF(source)) sv_rvweaken(dest);
65 25 1022 if (xdata) {
66 25 0 auto it = xdata->map.find(id);
67 5 20 if (it != xdata->map.end()) {
68 5 0 SvSetSV_nosteal(dest, it->second);
5 0 SvSetSV_nosteal(dest, it->second);
69 1 4 if (SvWEAKREF(source)) sv_rvweaken(dest);
1 0 if (SvWEAKREF(source)) sv_rvweaken(dest);
72 2 18 if (SvWEAKREF(source)) {
74 2 0 xdata->weakrefs.push_back({dest, id});
83 1010 30 if (is_object) {
84 1010 0 auto mg = mg_findext(source_val, PERL_MAGIC_ext, &clone_marker);
85 2 1008 if (mg) {
88 1008 0 else if ((cloneGV = gv_fetchmeth(SvSTASH(source_val), HOOK_METHOD, HOOK_METHLEN, 0))) {
3 1005 else if ((cloneGV = gv_fetchmeth(SvSTASH(source_val), HOOK_METHOD, HOOK_METHLEN, 0))) {
90 3 0 sv_magicext(source_val, NULL, PERL_MAGIC_ext, &clone_marker, (const char*)xdata, 0);
91 3 0 dSP; ENTER; SAVETMPS;
3 0 dSP; ENTER; SAVETMPS;
92 0 3 PUSHMARK(SP);
0 0 PUSHMARK(SP);
93 0 3 XPUSHs(source);
0 0 XPUSHs(source);
95 3 0 int count = call_sv((SV*)GvCV(cloneGV), G_SCALAR);
98 3 3 while (count--) retval = POPs;
99 3 0 if (retval) SvSetSV(dest, retval);
3 0 if (retval) SvSetSV(dest, retval);
3 0 if (retval) SvSetSV(dest, retval);
101 3 0 FREETMPS; LEAVE;
3 0 FREETMPS; LEAVE;
3 0 FREETMPS; LEAVE;
103 3 0 sv_unmagicext(source_val, PERL_MAGIC_ext, &clone_marker);
104 1 2 if (xdata) xdata->map[id] = dest;
1 0 if (xdata) xdata->map[id] = dest;
109 1037 0 SV* refval = newSV(0);
110 1037 0 sv_upgrade(dest, SVt_RV);
114 1007 30 if (is_object) sv_bless(dest, SvSTASH(source_val)); // cloning an object without any specific clone behavior
1007 0 if (is_object) sv_bless(dest, SvSTASH(source_val)); // cloning an object without any specific clone behavior
115 16 1021 if (xdata) xdata->map[id] = dest;
16 0 if (xdata) xdata->map[id] = dest;
116 35 1002 _clone(aTHX_ refval, source_val, xdata, depth+1);
132 64 0 SvSetSV_nosteal(dest, source);
147 45 17 for (SSize_t i = 0; i <= srcfill; ++i) {
149 45 0 if (srcval != NULL) { // if not empty slot
161 0 1018 if (!hvarr) return;
163 3154 20 for (STRLEN i = 0; i <= hvmax; ++i) {
165 1034 2156 for (entry = hvarr[i]; entry; entry = HeNEXT(entry)) {
167 1034 0 SV* elem = newSV(0);
168 1034 0 hv_storehek((HV*)dest, hek, elem);
169 36 998 _clone(aTHX_ elem, HeVAL(entry), xdata, depth+1);
181 7 0 }
7 0 }