summaryrefslogtreecommitdiff
path: root/av.c
diff options
context:
space:
mode:
authorYves Orton <demerphq@gmail.com>2020-01-31 15:34:48 +0100
committerYves Orton <demerphq@gmail.com>2020-01-31 15:37:45 +0100
commit2b301921ff7682e54ab74ad30dbf2ce1c9fc24b1 (patch)
treebe847e310a47167a95628f59deaf59c0d27639e8 /av.c
parent3eb35b099f783db0ec40f0ca9f20fd1666c54cdb (diff)
downloadperl-2b301921ff7682e54ab74ad30dbf2ce1c9fc24b1.tar.gz
pp_sort.c: fix fencepost error in call to av_extend()
In [rt.cpan.org #39196] issue #17496 there is a report that Tie::File produced spurious blank lines in the file after @tied= sort @tied; it turns out that this is because Tie::File treats EXTEND similarly to STORESIZE (which is arguably not entirely correct, but also not that weird) coupled with an off by one error in the calls to av_extend() in pp_sort. This patch fixes the fencepost error, adds some comments to av_extend() to make it clear what it is doing, and adds a test that EXTEND is called by this code with correct argument.
Diffstat (limited to 'av.c')
-rw-r--r--av.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/av.c b/av.c
index 918844c376..27b2f12032 100644
--- a/av.c
+++ b/av.c
@@ -55,8 +55,13 @@ Perl_av_reify(pTHX_ AV *av)
/*
=for apidoc av_extend
-Pre-extend an array. The C<key> is the index to which the array should be
-extended.
+Pre-extend an array so that it is capable of storing values at indexes
+C<0..key>. Thus C<av_extend(av,99)> guarantees that the array can store 100
+elements, i.e. that C<av_store(av, 0, sv)> through C<av_store(av, 99, sv)>
+on a plain array will work without any further memory allocation.
+
+If the av argument is a tied array then will call the C<EXTEND> tied
+array method with an argument of C<(key+1)>.
=cut
*/
@@ -72,6 +77,15 @@ Perl_av_extend(pTHX_ AV *av, SSize_t key)
mg = SvTIED_mg((const SV *)av, PERL_MAGIC_tied);
if (mg) {
SV *arg1 = sv_newmortal();
+ /* NOTE: the API for av_extend() is NOT the same as the tie method EXTEND.
+ *
+ * The C function takes an *index* (assumes 0 indexed arrays) and ensures
+ * that the array is at least as large as the index provided.
+ *
+ * The tied array method EXTEND takes a *count* and ensures that the array
+ * is at least that many elements large. Thus we have to +1 the key when
+ * we call the tied method.
+ */
sv_setiv(arg1, (IV)(key + 1));
Perl_magic_methcall(aTHX_ MUTABLE_SV(av), mg, SV_CONST(EXTEND), G_DISCARD, 1,
arg1);