Clone
view release on metacpan or search on metacpan
}
sv_magic(clone,
obj,
mg->mg_type,
mg_ptr,
mg->mg_len);
}
}
/* Null the qr vtable -- avoid mg_find traversal if we already know */
if (has_qr && (mg = mg_find(clone, 'r')))
mg->mg_virtual = (MGVTBL *) NULL;
}
/* 2: HASH/ARRAY - (with 'internal' elements) */
/* For tied HV/AV (magic_ref > 0): skip direct element iteration;
* the tie magic cloned above handles the data. */
if ( !magic_ref )
{
if ( SvTYPE(ref) == SVt_PVHV )
clone = hv_clone (ref, clone, hseen, depth, rdepth, weakrefs);
else if ( SvTYPE(ref) == SVt_PVAV )
clone = av_clone (ref, clone, hseen, depth, rdepth, weakrefs);
/* 3: REFERENCE (inlined for speed) */
else if (SvROK (ref))
{
TRACEME(("clone = 0x%x(%d)\n", clone, SvREFCNT(clone)));
SvREFCNT_dec(SvRV(clone));
SvRV(clone) = sv_clone (SvRV(ref), hseen, depth, rdepth, weakrefs); /* Clone the referent */
if (SvOBJECT(SvRV(ref)))
{
sv_bless (clone, SvSTASH (SvRV (ref)));
}
if (SvWEAKREF(ref)) {
/* Defer weakening until after the entire clone graph is built.
* sv_rvweaken decrements the referent's refcount, which can
* destroy it if no other strong references exist yet.
* By deferring, we ensure all strong references are in place
* before any weakening occurs. (fixes GH #15) */
av_push(weakrefs, SvREFCNT_inc_simple_NN(clone));
}
}
}
TRACEME(("clone = 0x%x(%d)\n", clone, SvREFCNT(clone)));
return clone;
}
MODULE = Clone PACKAGE = Clone
PROTOTYPES: ENABLE
void
clone(self, depth=-1)
SV *self
int depth
PREINIT:
SV *clone = &PL_sv_undef;
HV *hseen = newHV();
AV *weakrefs = newAV();
PPCODE:
TRACEME(("ref = 0x%x\n", self));
clone = sv_clone(self, hseen, depth, 0, weakrefs);
/* Now apply deferred weakening (GH #15).
* All strong references in the clone graph are established,
* so it is safe to weaken references without destroying referents. */
{
I32 i;
I32 len = av_len(weakrefs);
for (i = 0; i <= len; i++) {
SV **svp = av_fetch(weakrefs, i, 0);
if (svp && *svp && SvROK(*svp)) {
sv_rvweaken(*svp);
}
}
}
hv_clear(hseen); /* Free HV */
SvREFCNT_dec((SV *)hseen);
SvREFCNT_dec((SV *)weakrefs);
EXTEND(SP,1);
PUSHs(sv_2mortal(clone));
( run in 3.498 seconds using v1.01-cache-2.11-cpan-71847e10f99 )