Skip to content

Commit

Permalink
gh-89653: PEP 670: Convert PyBytes macros to functions (#91990)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
vstinner authored May 3, 2022
1 parent 4159443 commit 2eca5da
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 14 deletions.
4 changes: 2 additions & 2 deletions Doc/c-api/bytearray.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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.
4 changes: 2 additions & 2 deletions Doc/c-api/bytes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down
30 changes: 24 additions & 6 deletions Include/cpython/bytearrayobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
23 changes: 19 additions & 4 deletions Include/cpython/bytesobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down

0 comments on commit 2eca5da

Please sign in to comment.