Data-Structure-Util
view release on metacpan or search on metacpan
if ( AValue ) {
found = _has_circular_ref( *AValue, parents, seen );
if ( SvOK( found ) )
return found;
}
}
break;
}
case SVt_PVHV:{ /* Hash */
dsWARN( "Hash" );
myHash = ( HV * ) sv;
hv_iterinit( myHash );
while (( HEntry = hv_iternext( myHash ) )) {
#if dsDEBUG
STRLEN len2;
char *HKey = HePV( HEntry, len2 );
sprintf( errmsg, "NEXT KEY is %s\n", HKey );
warn( errmsg );
#endif
found =
_has_circular_ref( HeVAL( HEntry ), parents, seen );
if ( SvOK( found ) )
return found;
}
break;
}
default: ;
}
return &PL_sv_undef;
}
/*
Weaken any circular reference found
*/
SV *
_circular_off( SV * sv, HV * parents, HV * seen, SV * counter ) {
U32 len;
I32 i;
SV **AValue;
HV *myHash;
HE *HEntry;
char addr[PTRLEN];
#if dsDEBUG
char errmsg[100];
#endif
if ( SvROK( sv ) ) { /* Reference */
sprintf( addr, "%p", SvRV( sv ) );
len = strlen( addr );
if ( hv_exists( parents, addr, len ) ) {
if ( SvWEAKREF( sv ) ) {
dsWARN( "found a weak reference" );
}
else {
dsWARN( "found a circular reference!!!" );
sv_rvweaken( sv );
sv_inc( counter );
}
}
else {
if ( hv_exists( seen, addr, len ) ) {
dsWARN( "circular reference on weak ref" );
return &PL_sv_undef;
}
(void) hv_store( parents, addr, len, NULL, 0 );
(void) hv_store( seen, addr, len, NULL, 0 );
#ifdef SvWEAKREF
if ( SvWEAKREF( sv ) ) {
dsWARN( "found a weak reference 2" );
_circular_off( SvRV( sv ), newHV( ), seen, counter );
}
else {
#endif
_circular_off( SvRV( sv ), parents, seen, counter );
#ifdef SvWEAKREF
}
#endif
(void) hv_delete( seen, addr, ( U32 ) len, 0 );
(void) hv_delete( parents, addr, ( U32 ) len, 0 );
}
}
else {
/* Not a reference */
switch ( SvTYPE( sv ) ) {
case SVt_PVAV:{ /* Array */
dsWARN( "Array" );
for ( i = 0; i <= av_len( ( AV * ) sv ); i++ ) {
#if dsDEBUG
sprintf( errmsg, "next elem %i\n", i );
warn( errmsg );
#endif
AValue = av_fetch( ( AV * ) sv, i, 0 );
if ( AValue ) {
_circular_off( *AValue, parents, seen, counter );
if ( SvTYPE( sv ) != SVt_PVAV ) {
/* In some circumstances, weakening a reference screw things up */
croak
( "Array that we were weakening suddenly turned into a scalar of type type %d",
SvTYPE( sv ) );
}
}
}
break;
}
case SVt_PVHV:{ /* Hash */
dsWARN( "Hash" );
myHash = ( HV * ) sv;
hv_iterinit( myHash );
while (( HEntry = hv_iternext( myHash ) )) {
#if dsDEBUG
STRLEN len2;
char *HKey = HePV( HEntry, len2 );
sprintf( errmsg, "NEXT KEY is %s\n", HKey );
warn( errmsg );
#endif
_circular_off( HeVAL( HEntry ), parents, seen,
counter );
if ( SvTYPE( sv ) != SVt_PVHV ) {
/* In some circumstances, weakening a reference screw things up */
croak
( "Hash that we were weakening suddenly turned into a scalar of type type %d",
SvTYPE( sv ) );
}
}
break;
}
default: ;
}
}
return counter;
}
#if dsDEBUG
/*
Dump any data structure
*/
SV *
_dump_any( SV * re, HV * seen, int depth ) {
testvar:
if ( SvROK( re ) ) {
if ( has_seen( re, seen ) )
return re;
printf( "a reference " );
if ( sv_isobject( re ) )
printf( " blessed " );
printf( "to " );
re = SvRV( re );
goto testvar;
}
else {
switch ( SvTYPE( re ) ) {
case SVt_NULL:
printf( "an undef value\n" );
break;
case SVt_IV:
printf( "an integer (IV): %d\n", SvIV( re ) );
break;
case SVt_NV:
printf( "a double (NV): %f\n", SvNV( re ) );
break;
case SVt_RV:
printf( "a RV\n" );
break;
case SVt_PV:
printf( "a string (PV): %s\n", SvPV_nolen( re ) );
printf( "UTF8 %s\n", SvUTF8( re ) ? "on" : "off" );
break;
case SVt_PVIV:
printf( "an integer (PVIV): %d\n", SvIV( re ) );
break;
case SVt_PVNV:
printf( "a string (PVNV): %s\n", SvPV_nolen( re ) );
( run in 0.745 second using v1.01-cache-2.11-cpan-39bf76dae61 )