Branch Coverage

src/xs/clone.cc
Criterion Covered Total %
branch 92 138 66.6


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 15150 if (depth > CLONE_MAX_DEPTH) throw std::invalid_argument("clone: max depth (5000) reached, it looks like you passed a cycled structure");
2 0 if (depth > CLONE_MAX_DEPTH) throw std::invalid_argument("clone: max depth (5000) reached, it looks like you passed a cycled structure");
52 5051 10099 if (SvROK(source)) { // reference
56 5049 2 if (val_type == SVt_PVCV || val_type == SVt_PVIO) { // CV and IO cannot be copied - just set reference to the same SV
2 5047 if (val_type == SVt_PVCV || val_type == SVt_PVIO) { // CV and IO cannot be copied - just set reference to the same SV
57 4 0 SvSetSV_nosteal(dest, source);
4 0 SvSetSV_nosteal(dest, source);
58 2 2 if (SvWEAKREF(source)) sv_rvweaken(dest);
2 0 if (SvWEAKREF(source)) sv_rvweaken(dest);
63 25 5022 if (xdata) {
64 25 0 auto it = xdata->map.find(id);
65 5 20 if (it != xdata->map.end()) {
66 5 0 SvSetSV_nosteal(dest, it->second);
5 0 SvSetSV_nosteal(dest, it->second);
67 1 4 if (SvWEAKREF(source)) sv_rvweaken(dest);
1 0 if (SvWEAKREF(source)) sv_rvweaken(dest);
70 2 18 if (SvWEAKREF(source)) {
72 2 0 xdata->weakrefs.push_back({dest, id});
81 5010 30 if (is_object) {
82 5010 0 auto mg = mg_findext(source_val, PERL_MAGIC_ext, &clone_marker);
83 2 5008 if (mg) {
86 5008 0 else if ((cloneGV = gv_fetchmeth(SvSTASH(source_val), HOOK_METHOD, HOOK_METHLEN, 0))) {
3 5005 else if ((cloneGV = gv_fetchmeth(SvSTASH(source_val), HOOK_METHOD, HOOK_METHLEN, 0))) {
88 3 0 sv_magicext(source_val, NULL, PERL_MAGIC_ext, &clone_marker, (const char*)xdata, 0);
89 3 0 dSP; ENTER; SAVETMPS;
3 0 dSP; ENTER; SAVETMPS;
90 0 3 PUSHMARK(SP);
0 0 PUSHMARK(SP);
91 0 3 XPUSHs(source);
0 0 XPUSHs(source);
93 3 0 int count = call_sv((SV*)GvCV(cloneGV), G_SCALAR);
96 3 3 while (count--) retval = POPs;
97 3 0 if (retval) SvSetSV(dest, retval);
3 0 if (retval) SvSetSV(dest, retval);
3 0 if (retval) SvSetSV(dest, retval);
99 3 0 FREETMPS; LEAVE;
3 0 FREETMPS; LEAVE;
3 0 FREETMPS; LEAVE;
101 3 0 sv_unmagicext(source_val, PERL_MAGIC_ext, &clone_marker);
102 1 2 if (xdata) xdata->map[id] = dest;
1 0 if (xdata) xdata->map[id] = dest;
107 5037 0 SV* refval = newSV(0);
108 5037 0 sv_upgrade(dest, SVt_RV);
112 5007 30 if (is_object) sv_bless(dest, SvSTASH(source_val)); // cloning an object without any specific clone behavior
5007 0 if (is_object) sv_bless(dest, SvSTASH(source_val)); // cloning an object without any specific clone behavior
113 16 5021 if (xdata) xdata->map[id] = dest;
16 0 if (xdata) xdata->map[id] = dest;
114 35 5002 _clone(aTHX_ refval, source_val, xdata, depth+1);
130 5062 0 SvSetSV_nosteal(dest, source);
145 45 17 for (SSize_t i = 0; i <= srcfill; ++i) {
147 45 0 if (srcval != NULL) { // if not empty slot
159 0 5018 if (!hvarr) return;
161 40144 20 for (STRLEN i = 0; i <= hvmax; ++i) {
163 10032 35146 for (entry = hvarr[i]; entry; entry = HeNEXT(entry)) {
165 10032 0 SV* elem = newSV(0);
166 10032 0 hv_storehek((HV*)dest, hek, elem);
167 5034 4998 _clone(aTHX_ elem, HeVAL(entry), xdata, depth+1);
179 7 0 }
7 0 }