summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authorYves Orton <demerphq@gmail.com>2014-12-25 01:33:42 +0100
committerYves Orton <demerphq@gmail.com>2014-12-25 01:34:39 +0100
commiteaab56493bda8d2c9e499f01433ea2da9b29f6e5 (patch)
treef52f9654540bc436cf4482d0dfe54e65410158bc /ext
parentcced55d2e366f8ccb0884e747f32c32c1b538989 (diff)
downloadperl-eaab56493bda8d2c9e499f01433ea2da9b29f6e5.tar.gz
add new API function sv_get_backrefs()
This encapsulates the logic to extract the backrefs from a weak-referent. Since sv_get_backrefs() can be used for a similar purposes as hv_backreferences_p() we no longer need to export the later, and therefore this patch also reverts ad2f46a793b4ade67d45ac0086ae62f6756c2752. See perl #123473 for related discussion, and https://github.com/Sereal/Sereal/issues/73 for a practical example of why this API is required.
Diffstat (limited to 'ext')
-rw-r--r--ext/XS-APItest/APItest.xs19
-rw-r--r--ext/XS-APItest/t/weaken.t52
2 files changed, 71 insertions, 0 deletions
diff --git a/ext/XS-APItest/APItest.xs b/ext/XS-APItest/APItest.xs
index dee9f2f4a7..791063536d 100644
--- a/ext/XS-APItest/APItest.xs
+++ b/ext/XS-APItest/APItest.xs
@@ -5024,3 +5024,22 @@ test_Gconvert(SV * number, SV * num_digits)
RETVAL = newSVpv(buffer, 0);
OUTPUT:
RETVAL
+
+MODULE = XS::APItest PACKAGE = XS::APItest::Backrefs
+
+void
+weaken(SV *sv)
+ PROTOTYPE: $
+ CODE:
+ sv_rvweaken(sv);
+
+SV *
+has_backrefs(SV *sv)
+ CODE:
+ if (SvROK(sv) && sv_get_backrefs(SvRV(sv)))
+ RETVAL = &PL_sv_yes;
+ else
+ RETVAL = &PL_sv_no;
+ OUTPUT:
+ RETVAL
+
diff --git a/ext/XS-APItest/t/weaken.t b/ext/XS-APItest/t/weaken.t
new file mode 100644
index 0000000000..5396e529de
--- /dev/null
+++ b/ext/XS-APItest/t/weaken.t
@@ -0,0 +1,52 @@
+#!perl
+
+use strict;
+use warnings;
+
+use Test::More tests => 7;
+
+use_ok('XS::APItest');
+
+# test sv_rvweaken() and sv_get_backrefs()
+#
+# weaken() maps to sv_rvweaken() and is the same as the one
+# from Scalar::Utils - we recreate it in XS::APItest so
+# we can test it even if we build without Scalar::Utils
+#
+# has_backrefs() maps to sv_get_backrefs(), which would not
+# normally be useful to Perl code. (Er, maybe :-)
+
+# has_backrefs is really an internal routine
+# which would not normally have to worry about refs
+# and things like that, but to use it from perl we cant
+# have an AV/HV without having an RV wrapping it, so we
+# mandate the ref always.
+
+my $foo= "foo";
+my $bar= "bar";
+
+my $scalar_ref= \$foo;
+my $array_ref= [ qw(this is an array) ];
+my $hash_ref= { this => is => a => 'hash' };
+
+my $nrml_scalar_ref= \$bar;
+my $nrml_array_ref= [ qw( this is an array ) ];
+my $nrml_hash_ref= { this => is => a => 'hash' };
+
+# we could probably do other tests here, such as
+# verify the refcount of the referents, but maybe
+# another day.
+weaken(my $weak_scalar_ref= $scalar_ref);
+weaken(my $weak_array_ref= $array_ref);
+weaken(my $weak_hash_ref= $hash_ref);
+
+ok(has_backrefs($scalar_ref), "scalar with backrefs");
+ok(has_backrefs($array_ref), "array with backrefs");
+ok(has_backrefs($hash_ref), "hash with backrefs");
+
+ok(!has_backrefs($nrml_scalar_ref), "scalar without backrefs");
+ok(!has_backrefs($nrml_array_ref), "array without backrefs");
+ok(!has_backrefs($nrml_hash_ref), "hash without backrefs");
+
+1;
+