Blob Blame History Raw
From bafffe7f2ca587960177ed03216e2d5692fe6143 Mon Sep 17 00:00:00 2001
From: Karl Williamson <khw@cpan.org>
Date: Wed, 19 Aug 2020 11:57:17 -0600
Subject: [PATCH] Add av_count()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This returns the number of elements in an array in a clearly named
function.

av_top_index(), av_tindex() are clearly named, but are less than ideal,
and came about because no one back then thought of this one, until now
Paul Evans did.

Petr Písař: Port 87306e0674dfe3af29804b4641347cd5ac9b0521 to 5.32.0.

Signed-off-by: Petr Písař <ppisar@redhat.com>
---
 av.c      | 17 ++++++++++++++---
 av.h      |  3 ++-
 embed.fnc |  3 ++-
 embed.h   |  2 +-
 inline.h  | 16 ++++++++++++----
 proto.h   | 11 ++++++++---
 6 files changed, 39 insertions(+), 13 deletions(-)

diff --git a/av.c b/av.c
index 27b2f12..b5ddaca 100644
--- a/av.c
+++ b/av.c
@@ -814,9 +814,10 @@ The Perl equivalent for this is C<$#myarray>.
 =for apidoc av_len
 
 Same as L</av_top_index>.  Note that, unlike what the name implies, it returns
-the highest index in the array, so to get the size of the array you need to use
-S<C<av_len(av) + 1>>.  This is unlike L</sv_len>, which returns what you would
-expect.
+the highest index in the array.  This is unlike L</sv_len>, which returns what
+you would expect.
+
+B<To get the true number of elements in the array, instead use C<L</av_count>>>.
 
 =cut
 */
@@ -1089,6 +1090,16 @@ Perl_av_nonelem(pTHX_ AV *av, SSize_t ix) {
     return sv;
 }
 
+SSize_t
+Perl_av_top_index(pTHX_ AV *av)
+{
+    PERL_ARGS_ASSERT_AV_TOP_INDEX;
+    assert(SvTYPE(av) == SVt_PVAV);
+
+    return AvFILL(av);
+}
+
+
 /*
  * ex: set ts=8 sts=4 sw=4 et:
  */
diff --git a/av.h b/av.h
index 5e39c42..90ebfff 100644
--- a/av.h
+++ b/av.h
@@ -81,7 +81,8 @@ Same as C<av_top_index()>.
                                           
 #define AvFILL(av)	((SvRMAGICAL((const SV *) (av))) \
 			 ? mg_size(MUTABLE_SV(av)) : AvFILLp(av))
-#define av_tindex(av)   av_top_index(av)
+#define av_top_index(av) AvFILL(av)
+#define av_tindex(av)    av_top_index(av)
 
 /* Note that it doesn't make sense to do this:
  *      SvGETMAGIC(av); IV x = av_tindex_nomg(av);
diff --git a/embed.fnc b/embed.fnc
index 589ab1a..789cd3c 100644
--- a/embed.fnc
+++ b/embed.fnc
@@ -541,7 +541,8 @@ Apd	|void	|av_push	|NN AV *av|NN SV *val
 EXp	|void	|av_reify	|NN AV *av
 ApdR	|SV*	|av_shift	|NN AV *av
 Apd	|SV**	|av_store	|NN AV *av|SSize_t key|NULLOK SV *val
-AidRp	|SSize_t|av_top_index	|NN AV *av
+AMdRp	|SSize_t|av_top_index	|NN AV *av
+AidRp	|Size_t	|av_count	|NN AV *av
 AmdR	|SSize_t|av_tindex	|NN AV *av
 Apd	|void	|av_undef	|NN AV *av
 Apdoex	|SV**	|av_create_and_unshift_one|NN AV **const avp|NN SV *const val
diff --git a/embed.h b/embed.h
index 182b12a..329ac40 100644
--- a/embed.h
+++ b/embed.h
@@ -48,6 +48,7 @@
 #define atfork_lock		Perl_atfork_lock
 #define atfork_unlock		Perl_atfork_unlock
 #define av_clear(a)		Perl_av_clear(aTHX_ a)
+#define av_count(a)		Perl_av_count(aTHX_ a)
 #define av_delete(a,b,c)	Perl_av_delete(aTHX_ a,b,c)
 #define av_exists(a,b)		Perl_av_exists(aTHX_ a,b)
 #define av_extend(a,b)		Perl_av_extend(aTHX_ a,b)
@@ -59,7 +60,6 @@
 #define av_push(a,b)		Perl_av_push(aTHX_ a,b)
 #define av_shift(a)		Perl_av_shift(aTHX_ a)
 #define av_store(a,b,c)		Perl_av_store(aTHX_ a,b,c)
-#define av_top_index(a)		Perl_av_top_index(aTHX_ a)
 #define av_undef(a)		Perl_av_undef(aTHX_ a)
 #define av_unshift(a,b)		Perl_av_unshift(aTHX_ a,b)
 #define block_end(a,b)		Perl_block_end(aTHX_ a,b)
diff --git a/inline.h b/inline.h
index 27005d2..35af18a 100644
--- a/inline.h
+++ b/inline.h
@@ -39,13 +39,21 @@ SOFTWARE.
 
 /* ------------------------------- av.h ------------------------------- */
 
-PERL_STATIC_INLINE SSize_t
-Perl_av_top_index(pTHX_ AV *av)
+/*
+=for apidoc av_count
+Returns the number of elements in the array C<av>.  This is the true length of
+the array, including any undefined elements.  It is always the same as
+S<C<av_top_index(av) + 1>>.
+
+=cut
+*/
+PERL_STATIC_INLINE Size_t
+Perl_av_count(pTHX_ AV *av)
 {
-    PERL_ARGS_ASSERT_AV_TOP_INDEX;
+    PERL_ARGS_ASSERT_AV_COUNT;
     assert(SvTYPE(av) == SVt_PVAV);
 
-    return AvFILL(av);
+    return AvFILL(av) + 1;
 }
 
 /* ------------------------------- cv.h ------------------------------- */
diff --git a/proto.h b/proto.h
index 02ef4ed..83ba098 100644
--- a/proto.h
+++ b/proto.h
@@ -219,6 +219,13 @@ PERL_CALLCONV SV**	Perl_av_arylen_p(pTHX_ AV *av);
 PERL_CALLCONV void	Perl_av_clear(pTHX_ AV *av);
 #define PERL_ARGS_ASSERT_AV_CLEAR	\
 	assert(av)
+#ifndef PERL_NO_INLINE_FUNCTIONS
+PERL_STATIC_INLINE Size_t	Perl_av_count(pTHX_ AV *av)
+			__attribute__warn_unused_result__;
+#define PERL_ARGS_ASSERT_AV_COUNT	\
+	assert(av)
+#endif
+
 PERL_CALLCONV void	Perl_av_create_and_push(pTHX_ AV **const avp, SV *const val);
 #define PERL_ARGS_ASSERT_AV_CREATE_AND_PUSH	\
 	assert(avp); assert(val)
@@ -284,12 +291,10 @@ PERL_CALLCONV SV**	Perl_av_store(pTHX_ AV *av, SSize_t key, SV *val);
 			__attribute__warn_unused_result__; */
 #define PERL_ARGS_ASSERT_AV_TINDEX
 
-#ifndef PERL_NO_INLINE_FUNCTIONS
-PERL_STATIC_INLINE SSize_t	Perl_av_top_index(pTHX_ AV *av)
+PERL_CALLCONV SSize_t	Perl_av_top_index(pTHX_ AV *av)
 			__attribute__warn_unused_result__;
 #define PERL_ARGS_ASSERT_AV_TOP_INDEX	\
 	assert(av)
-#endif
 
 PERL_CALLCONV void	Perl_av_undef(pTHX_ AV *av);
 #define PERL_ARGS_ASSERT_AV_UNDEF	\
-- 
2.25.4