[Python-checkins] gh-89653: PEP 670: Convert PyBytes macros to functions (#91990)

vstinner webhook-mailer at python.org
Tue May 3 14:15:07 EDT 2022


https://github.com/python/cpython/commit/2eca5dad0a783153318e91e3e25f16a38a632bfd
commit: 2eca5dad0a783153318e91e3e25f16a38a632bfd
branch: main
author: Victor Stinner <vstinner at python.org>
committer: vstinner <vstinner at python.org>
date: 2022-05-03T20:14:58+02:00
summary:

gh-89653: PEP 670: Convert PyBytes macros to functions (#91990)

Convert the following macros to static inline functions:

* PyByteArray_AS_STRING()
* PyByteArray_GET_SIZE()
* PyBytes_AS_STRING()
* PyBytes_GET_SIZE()

Limited C API version 3.11 no longer casts arguments.

Add _PyBytes_CAST() and _PyByteArray_CAST() macros.

files:
M Doc/c-api/bytearray.rst
M Doc/c-api/bytes.rst
M Include/cpython/bytearrayobject.h
M Include/cpython/bytesobject.h

diff --git a/Doc/c-api/bytearray.rst b/Doc/c-api/bytearray.rst
index 85a7d1373c2a8..4bf3cfe100cd0 100644
--- a/Doc/c-api/bytearray.rst
+++ b/Doc/c-api/bytearray.rst
@@ -77,9 +77,9 @@ These macros trade safety for speed and they don't check pointers.
 
 .. c:function:: char* PyByteArray_AS_STRING(PyObject *bytearray)
 
-   Macro version of :c:func:`PyByteArray_AsString`.
+   Similar to :c:func:`PyByteArray_AsString`, but without error checking.
 
 
 .. c:function:: Py_ssize_t PyByteArray_GET_SIZE(PyObject *bytearray)
 
-   Macro version of :c:func:`PyByteArray_Size`.
+   Similar to :c:func:`PyByteArray_Size`, but without error checking.
diff --git a/Doc/c-api/bytes.rst b/Doc/c-api/bytes.rst
index 32c7b80dc7ac6..d47f0422e6100 100644
--- a/Doc/c-api/bytes.rst
+++ b/Doc/c-api/bytes.rst
@@ -134,7 +134,7 @@ called with a non-bytes parameter.
 
 .. c:function:: Py_ssize_t PyBytes_GET_SIZE(PyObject *o)
 
-   Macro form of :c:func:`PyBytes_Size` but without error checking.
+   Similar to :c:func:`PyBytes_Size`, but without error checking.
 
 
 .. c:function:: char* PyBytes_AsString(PyObject *o)
@@ -151,7 +151,7 @@ called with a non-bytes parameter.
 
 .. c:function:: char* PyBytes_AS_STRING(PyObject *string)
 
-   Macro form of :c:func:`PyBytes_AsString` but without error checking.
+   Similar to :c:func:`PyBytes_AsString`, but without error checking.
 
 
 .. c:function:: int PyBytes_AsStringAndSize(PyObject *obj, char **buffer, Py_ssize_t *length)
diff --git a/Include/cpython/bytearrayobject.h b/Include/cpython/bytearrayobject.h
index 569b0cd036986..5114169c28091 100644
--- a/Include/cpython/bytearrayobject.h
+++ b/Include/cpython/bytearrayobject.h
@@ -11,10 +11,28 @@ typedef struct {
     Py_ssize_t ob_exports; /* How many buffer exports */
 } PyByteArrayObject;
 
-/* Macros, trading safety for speed */
-#define PyByteArray_AS_STRING(self) \
-    (assert(PyByteArray_Check(self)), \
-     Py_SIZE(self) ? ((PyByteArrayObject *)(self))->ob_start : _PyByteArray_empty_string)
-#define PyByteArray_GET_SIZE(self) (assert(PyByteArray_Check(self)), Py_SIZE(self))
-
 PyAPI_DATA(char) _PyByteArray_empty_string[];
+
+/* Macros and static inline functions, trading safety for speed */
+#define _PyByteArray_CAST(op) \
+    (assert(PyByteArray_Check(op)), _Py_CAST(PyByteArrayObject*, op))
+
+static inline char* PyByteArray_AS_STRING(PyObject *op)
+{
+    PyByteArrayObject *self = _PyByteArray_CAST(op);
+    if (Py_SIZE(self)) {
+        return self->ob_start;
+    }
+    return _PyByteArray_empty_string;
+}
+#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
+#  define PyByteArray_AS_STRING(self) PyByteArray_AS_STRING(_PyObject_CAST(self))
+#endif
+
+static inline Py_ssize_t PyByteArray_GET_SIZE(PyObject *op) {
+    PyByteArrayObject *self = _PyByteArray_CAST(op);
+    return Py_SIZE(self);
+}
+#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
+#  define PyByteArray_GET_SIZE(self) PyByteArray_GET_SIZE(_PyObject_CAST(self))
+#endif
diff --git a/Include/cpython/bytesobject.h b/Include/cpython/bytesobject.h
index 2c6d631f0b21e..53343661f0ec4 100644
--- a/Include/cpython/bytesobject.h
+++ b/Include/cpython/bytesobject.h
@@ -28,10 +28,25 @@ PyAPI_FUNC(PyObject*) _PyBytes_FromHex(
 PyAPI_FUNC(PyObject *) _PyBytes_DecodeEscape(const char *, Py_ssize_t,
                                              const char *, const char **);
 
-/* Macro, trading safety for speed */
-#define PyBytes_AS_STRING(op) (assert(PyBytes_Check(op)), \
-                                (((PyBytesObject *)(op))->ob_sval))
-#define PyBytes_GET_SIZE(op)  (assert(PyBytes_Check(op)),Py_SIZE(op))
+/* Macros and static inline functions, trading safety for speed */
+#define _PyBytes_CAST(op) \
+    (assert(PyBytes_Check(op)), _Py_CAST(PyBytesObject*, op))
+
+static inline char* PyBytes_AS_STRING(PyObject *op)
+{
+    return _PyBytes_CAST(op)->ob_sval;
+}
+#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
+#  define PyBytes_AS_STRING(op) PyBytes_AS_STRING(_PyObject_CAST(op))
+#endif
+
+static inline Py_ssize_t PyBytes_GET_SIZE(PyObject *op) {
+    PyBytesObject *self = _PyBytes_CAST(op);
+    return Py_SIZE(self);
+}
+#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 < 0x030b0000
+#  define PyBytes_GET_SIZE(self) PyBytes_GET_SIZE(_PyObject_CAST(self))
+#endif
 
 /* _PyBytes_Join(sep, x) is like sep.join(x).  sep must be PyBytesObject*,
    x must be an iterable object. */



More information about the Python-checkins mailing list