This is pretty trivial. We want to keep only those subheadings that were originally defined in our package. Each CV (code value) has a pointer to the package in which it was defined. Thanks to B we can verify that:
use B (); ... if (my $coderef = $self->can($symbol)) { my $cv = B::svref_2object $coderef; push @sections, $symbol if $cv->STASH->NAME eq __PACKAGE__; }
That is, we perform introspection using svref_2object . This returns a Perl object representing the internal perl data structure.
If we look at coderef, we get a B::CV object, which is an internal CV . The STASH field in CV indicates Stash where it was defined. As you know, Stash is just a special hash (internally represented as HV ), so $cv->STASH returns a B::HV . The NAME a HV field contains the full name of the Stash package if the HV is a Stash and not a regular hash.
Now we have all the information we need, and we can compare the desired package name with the coderef wallet name.
Of course, this is simplified, and you will want to go through @ISA for general classes.
No one likes dirty namespaces. Fortunately, there are modules that remove external characters from Stash, for example. namespace::clean . This is not a problem when the CVs of all the subscribers you call are known at compile time.
source share