]> git.ipfire.org Git - thirdparty/gnulib.git/commitdiff
stdcountof-h: New module.
authorBruno Haible <bruno@clisp.org>
Mon, 2 Jun 2025 21:42:17 +0000 (23:42 +0200)
committerBruno Haible <bruno@clisp.org>
Mon, 2 Jun 2025 21:42:17 +0000 (23:42 +0200)
* lib/stdcountof.in.h: New file.
* m4/stdcountof_h.m4: New file.
* modules/stdcountof-h: New file.

ChangeLog
lib/stdcountof.in.h [new file with mode: 0644]
m4/stdcountof_h.m4 [new file with mode: 0644]
modules/stdcountof-h [new file with mode: 0644]

index a1d88c839df1bd2755d541034efe33bd50884dca..3c05726d954f89d7097259b6f4149c1ca1e8b64f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2025-06-02  Bruno Haible  <bruno@clisp.org>
+
+       stdcountof-h: New module.
+       * lib/stdcountof.in.h: New file.
+       * m4/stdcountof_h.m4: New file.
+       * modules/stdcountof-h: New file.
+
 2025-06-02  Bruno Haible  <bruno@clisp.org>
 
        stddef-h: Fix compilation errors in C++ mode (regression 2025-05-27).
diff --git a/lib/stdcountof.in.h b/lib/stdcountof.in.h
new file mode 100644 (file)
index 0000000..3bbb783
--- /dev/null
@@ -0,0 +1,95 @@
+/* Copyright 2025 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Lesser General Public License as published
+   by the Free Software Foundation; either version 2.1 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <bruno@clisp.org>, 2025.  */
+
+#ifndef _GL_STDCOUNTOF_H
+#define _GL_STDCOUNTOF_H
+
+#if defined __cplusplus
+/* Get size_t.  */
+# include <stddef.h>
+#endif
+
+/* Returns the number of elements of the array A, as a value of type size_t.
+   Example declarations of arrays:
+     extern int a[];
+     extern int a[10];
+     static int a[10][20];
+     void func () { int a[10]; ... }
+   Attempts to produce an error if A is a pointer, e.g. in
+     void func (int a[10]) { ... }
+ */
+#define countof(a) \
+  (sizeof (a) / sizeof (a[0]) + 0 * _gl_verify_is_array (a))
+
+/* Attempts to verify that A is an array.  */
+#if defined __cplusplus
+/* Borrowed from verify.h.  */
+# if !GNULIB_defined_struct__gl_verify_type
+template <int w>
+  struct _gl_verify_type {
+    unsigned int _gl_verify_error_if_negative: w;
+  };
+#  define GNULIB_defined_struct__gl_verify_type 1
+# endif
+# if __cplusplus >= 201103L
+#  if 1
+  /* Use decltype.  */
+/* Default case.  */
+template <typename T>
+  struct _gl_array_type_test { static const int is_array = -1; };
+/* Unbounded arrays.  */
+template <typename T>
+  struct _gl_array_type_test<T[]> { static const int is_array = 1; };
+/* Bounded arrays.  */
+template <typename T, size_t N>
+  struct _gl_array_type_test<T[N]> { static const int is_array = 1; };
+#   define _gl_verify_is_array(a) \
+     sizeof (_gl_verify_type<_gl_array_type_test<decltype(a)>::is_array>)
+#  else
+  /* Use template argument deduction.
+     Use sizeof to get a constant expression from an unknown type.  */
+/* Default case.  */
+template <typename T>
+  struct _gl_array_type_test { double large; };
+/* Unbounded arrays.  */
+template <typename T>
+  struct _gl_array_type_test<T[]> { char small; };
+/* Bounded arrays.  */
+template <typename T, size_t N>
+  struct _gl_array_type_test<T[N]> { char small; };
+/* The T& parameter is essential here: it prevents decay (array-to-pointer
+   conversion).  */
+template <typename T> _gl_array_type_test<T> _gl_array_type_test_helper(T&);
+#   define _gl_verify_is_array(a) \
+     sizeof (_gl_verify_type<(sizeof (_gl_array_type_test_helper(a)) < sizeof (double) ? 1 : -1)>)
+#  endif
+# else
+/* The compiler does not have the necessary functionality.  */
+#  define _gl_verify_is_array(a) 0
+# endif
+#else
+/* In C, we can use typeof and __builtin_types_compatible_p.  */
+# if _GL_GNUC_PREREQ (3, 1) || defined __clang__
+#  define _gl_verify_is_array(a) \
+    sizeof (struct { unsigned int _gl_verify_error_if_negative : __builtin_types_compatible_p (typeof (a), typeof (&*(a))) ? -1 : 1; })
+# else
+/* The compiler does not have the necessary built-ins.  */
+#  define _gl_verify_is_array(a) 0
+# endif
+#endif
+
+#endif /* _GL_STDCOUNTOF_H */
diff --git a/m4/stdcountof_h.m4 b/m4/stdcountof_h.m4
new file mode 100644 (file)
index 0000000..23b31c1
--- /dev/null
@@ -0,0 +1,24 @@
+# stdcountof_h.m4
+# serial 1
+dnl Copyright 2025 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+dnl This file is offered as-is, without any warranty.
+
+AC_DEFUN_ONCE([gl_STDCOUNTOF_H],
+[
+  AC_CHECK_HEADERS_ONCE([stdcountof.h])
+  if test $ac_cv_header_stdcountof_h = yes; then
+    HAVE_STDCOUNTOF_H=1
+  else
+    HAVE_STDCOUNTOF_H=0
+  fi
+  AC_SUBST([HAVE_STDCOUNTOF_H])
+
+  if test $HAVE_STDCOUNTOF_H = 1; then
+    GL_GENERATE_STDCOUNTOF_H=false
+  else
+    GL_GENERATE_STDCOUNTOF_H=true
+  fi
+])
diff --git a/modules/stdcountof-h b/modules/stdcountof-h
new file mode 100644 (file)
index 0000000..1408e5e
--- /dev/null
@@ -0,0 +1,39 @@
+Description:
+An <stdcountof.h> that is like C23.
+
+Files:
+lib/stdcountof.in.h
+m4/stdcountof_h.m4
+
+Depends-on:
+gen-header
+
+configure.ac:
+gl_STDCOUNTOF_H
+gl_CONDITIONAL_HEADER([stdcountof.h])
+AC_PROG_MKDIR_P
+
+Makefile.am:
+BUILT_SOURCES += $(STDCOUNTOF_H)
+
+# We need the following in order to create <stdcountof.h> when the system
+# doesn't have one that works with the given compiler.
+if GL_GENERATE_STDCOUNTOF_H
+stdcountof.h: stdcountof.in.h $(top_builddir)/config.status
+@NMD@  $(AM_V_GEN)$(MKDIR_P) '%reldir%'
+       $(gl_V_at)$(SED_HEADER_STDOUT) $(srcdir)/stdcountof.in.h > $@-t
+       $(AM_V_at)mv $@-t $@
+else
+stdcountof.h: $(top_builddir)/config.status
+       rm -f $@
+endif
+MOSTLYCLEANFILES += stdcountof.h stdcountof.h-t
+
+Include:
+<stdcountof.h>
+
+License:
+LGPLv2+
+
+Maintainer:
+Bruno Haible