gh-132639: Adds PyLong_AsNativeBytes, PyLong_FromNativeBytes and PyLong_FromUnsignedNativeBytes to the limited API (GH-132640)

This commit is contained in:
Steve Dower 2025-04-21 15:59:03 +01:00 committed by GitHub
parent 70b322d313
commit 09b624b80f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 83 additions and 51 deletions

View file

@ -362,6 +362,7 @@ func,PyLong_AsLong,3.2,,
func,PyLong_AsLongAndOverflow,3.2,,
func,PyLong_AsLongLong,3.2,,
func,PyLong_AsLongLongAndOverflow,3.2,,
func,PyLong_AsNativeBytes,3.14,,
func,PyLong_AsSize_t,3.2,,
func,PyLong_AsSsize_t,3.2,,
func,PyLong_AsUInt32,3.14,,
@ -376,6 +377,7 @@ func,PyLong_FromInt32,3.14,,
func,PyLong_FromInt64,3.14,,
func,PyLong_FromLong,3.2,,
func,PyLong_FromLongLong,3.2,,
func,PyLong_FromNativeBytes,3.14,,
func,PyLong_FromSize_t,3.2,,
func,PyLong_FromSsize_t,3.2,,
func,PyLong_FromString,3.2,,
@ -383,6 +385,7 @@ func,PyLong_FromUInt32,3.14,,
func,PyLong_FromUInt64,3.14,,
func,PyLong_FromUnsignedLong,3.2,,
func,PyLong_FromUnsignedLongLong,3.2,,
func,PyLong_FromUnsignedNativeBytes,3.14,,
func,PyLong_FromVoidPtr,3.2,,
func,PyLong_GetInfo,3.2,,
data,PyLong_Type,3.2,,

View file

@ -7,57 +7,6 @@
PyAPI_FUNC(PyObject*) PyLong_FromUnicodeObject(PyObject *u, int base);
#define Py_ASNATIVEBYTES_DEFAULTS -1
#define Py_ASNATIVEBYTES_BIG_ENDIAN 0
#define Py_ASNATIVEBYTES_LITTLE_ENDIAN 1
#define Py_ASNATIVEBYTES_NATIVE_ENDIAN 3
#define Py_ASNATIVEBYTES_UNSIGNED_BUFFER 4
#define Py_ASNATIVEBYTES_REJECT_NEGATIVE 8
#define Py_ASNATIVEBYTES_ALLOW_INDEX 16
/* PyLong_AsNativeBytes: Copy the integer value to a native variable.
buffer points to the first byte of the variable.
n_bytes is the number of bytes available in the buffer. Pass 0 to request
the required size for the value.
flags is a bitfield of the following flags:
* 1 - little endian
* 2 - native endian
* 4 - unsigned destination (e.g. don't reject copying 255 into one byte)
* 8 - raise an exception for negative inputs
* 16 - call __index__ on non-int types
If flags is -1 (all bits set), native endian is used, value truncation
behaves most like C (allows negative inputs and allow MSB set), and non-int
objects will raise a TypeError.
Big endian mode will write the most significant byte into the address
directly referenced by buffer; little endian will write the least significant
byte into that address.
If an exception is raised, returns a negative value.
Otherwise, returns the number of bytes that are required to store the value.
To check that the full value is represented, ensure that the return value is
equal or less than n_bytes.
All n_bytes are guaranteed to be written (unless an exception occurs), and
so ignoring a positive return value is the equivalent of a downcast in C.
In cases where the full value could not be represented, the returned value
may be larger than necessary - this function is not an accurate way to
calculate the bit length of an integer object.
*/
PyAPI_FUNC(Py_ssize_t) PyLong_AsNativeBytes(PyObject* v, void* buffer,
Py_ssize_t n_bytes, int flags);
/* PyLong_FromNativeBytes: Create an int value from a native integer
n_bytes is the number of bytes to read from the buffer. Passing 0 will
always produce the zero int.
PyLong_FromUnsignedNativeBytes always produces a non-negative int.
flags is the same as for PyLong_AsNativeBytes, but only supports selecting
the endianness or forcing an unsigned buffer.
Returns the int object, or NULL with an exception set. */
PyAPI_FUNC(PyObject*) PyLong_FromNativeBytes(const void* buffer, size_t n_bytes,
int flags);
PyAPI_FUNC(PyObject*) PyLong_FromUnsignedNativeBytes(const void* buffer,
size_t n_bytes, int flags);
PyAPI_FUNC(int) PyUnstable_Long_IsCompact(const PyLongObject* op);
PyAPI_FUNC(Py_ssize_t) PyUnstable_Long_CompactValue(const PyLongObject* op);

View file

@ -40,6 +40,58 @@ PyAPI_FUNC(int) PyLong_AsInt32(PyObject *obj, int32_t *value);
PyAPI_FUNC(int) PyLong_AsUInt32(PyObject *obj, uint32_t *value);
PyAPI_FUNC(int) PyLong_AsInt64(PyObject *obj, int64_t *value);
PyAPI_FUNC(int) PyLong_AsUInt64(PyObject *obj, uint64_t *value);
#define Py_ASNATIVEBYTES_DEFAULTS -1
#define Py_ASNATIVEBYTES_BIG_ENDIAN 0
#define Py_ASNATIVEBYTES_LITTLE_ENDIAN 1
#define Py_ASNATIVEBYTES_NATIVE_ENDIAN 3
#define Py_ASNATIVEBYTES_UNSIGNED_BUFFER 4
#define Py_ASNATIVEBYTES_REJECT_NEGATIVE 8
#define Py_ASNATIVEBYTES_ALLOW_INDEX 16
/* PyLong_AsNativeBytes: Copy the integer value to a native variable.
buffer points to the first byte of the variable.
n_bytes is the number of bytes available in the buffer. Pass 0 to request
the required size for the value.
flags is a bitfield of the following flags:
* 1 - little endian
* 2 - native endian
* 4 - unsigned destination (e.g. don't reject copying 255 into one byte)
* 8 - raise an exception for negative inputs
* 16 - call __index__ on non-int types
If flags is -1 (all bits set), native endian is used, value truncation
behaves most like C (allows negative inputs and allow MSB set), and non-int
objects will raise a TypeError.
Big endian mode will write the most significant byte into the address
directly referenced by buffer; little endian will write the least significant
byte into that address.
If an exception is raised, returns a negative value.
Otherwise, returns the number of bytes that are required to store the value.
To check that the full value is represented, ensure that the return value is
equal or less than n_bytes.
All n_bytes are guaranteed to be written (unless an exception occurs), and
so ignoring a positive return value is the equivalent of a downcast in C.
In cases where the full value could not be represented, the returned value
may be larger than necessary - this function is not an accurate way to
calculate the bit length of an integer object.
*/
PyAPI_FUNC(Py_ssize_t) PyLong_AsNativeBytes(PyObject* v, void* buffer,
Py_ssize_t n_bytes, int flags);
/* PyLong_FromNativeBytes: Create an int value from a native integer
n_bytes is the number of bytes to read from the buffer. Passing 0 will
always produce the zero int.
PyLong_FromUnsignedNativeBytes always produces a non-negative int.
flags is the same as for PyLong_AsNativeBytes, but only supports selecting
the endianness or forcing an unsigned buffer.
Returns the int object, or NULL with an exception set. */
PyAPI_FUNC(PyObject*) PyLong_FromNativeBytes(const void* buffer, size_t n_bytes,
int flags);
PyAPI_FUNC(PyObject*) PyLong_FromUnsignedNativeBytes(const void* buffer,
size_t n_bytes, int flags);
#endif
PyAPI_FUNC(PyObject *) PyLong_GetInfo(void);

View file

@ -397,6 +397,7 @@ SYMBOL_NAMES = (
"PyLong_AsLongAndOverflow",
"PyLong_AsLongLong",
"PyLong_AsLongLongAndOverflow",
"PyLong_AsNativeBytes",
"PyLong_AsSize_t",
"PyLong_AsSsize_t",
"PyLong_AsUInt32",
@ -411,6 +412,7 @@ SYMBOL_NAMES = (
"PyLong_FromInt64",
"PyLong_FromLong",
"PyLong_FromLongLong",
"PyLong_FromNativeBytes",
"PyLong_FromSize_t",
"PyLong_FromSsize_t",
"PyLong_FromString",
@ -418,6 +420,7 @@ SYMBOL_NAMES = (
"PyLong_FromUInt64",
"PyLong_FromUnsignedLong",
"PyLong_FromUnsignedLongLong",
"PyLong_FromUnsignedNativeBytes",
"PyLong_FromVoidPtr",
"PyLong_GetInfo",
"PyLong_Type",

View file

@ -0,0 +1,2 @@
Added :c:func:`PyLong_AsNativeBytes`, :c:func:`PyLong_FromNativeBytes` and
:c:func:`PyLong_FromUnsignedNativeBytes` to the limited C API.

View file

@ -2528,6 +2528,26 @@
added = '3.14'
[function.PyLong_AsUInt64]
added = '3.14'
[function.PyLong_AsNativeBytes]
added = '3.14'
[function.PyLong_FromNativeBytes]
added = '3.14'
[function.PyLong_FromUnsignedNativeBytes]
added = '3.14'
[const.Py_ASNATIVEBYTES_DEFAULTS]
added = '3.14'
[const.Py_ASNATIVEBYTES_BIG_ENDIAN]
added = '3.14'
[const.Py_ASNATIVEBYTES_LITTLE_ENDIAN]
added = '3.14'
[const.Py_ASNATIVEBYTES_NATIVE_ENDIAN]
added = '3.14'
[const.Py_ASNATIVEBYTES_UNSIGNED_BUFFER]
added = '3.14'
[const.Py_ASNATIVEBYTES_REJECT_NEGATIVE]
added = '3.14'
[const.Py_ASNATIVEBYTES_ALLOW_INDEX]
added = '3.14'
[const.Py_tp_vectorcall]
added = '3.14'
[function.PyType_GetBaseByToken]

3
PC/python3dll.c generated
View file

@ -351,6 +351,7 @@ EXPORT_FUNC(PyLong_AsLong)
EXPORT_FUNC(PyLong_AsLongAndOverflow)
EXPORT_FUNC(PyLong_AsLongLong)
EXPORT_FUNC(PyLong_AsLongLongAndOverflow)
EXPORT_FUNC(PyLong_AsNativeBytes)
EXPORT_FUNC(PyLong_AsSize_t)
EXPORT_FUNC(PyLong_AsSsize_t)
EXPORT_FUNC(PyLong_AsUInt32)
@ -365,6 +366,7 @@ EXPORT_FUNC(PyLong_FromInt32)
EXPORT_FUNC(PyLong_FromInt64)
EXPORT_FUNC(PyLong_FromLong)
EXPORT_FUNC(PyLong_FromLongLong)
EXPORT_FUNC(PyLong_FromNativeBytes)
EXPORT_FUNC(PyLong_FromSize_t)
EXPORT_FUNC(PyLong_FromSsize_t)
EXPORT_FUNC(PyLong_FromString)
@ -372,6 +374,7 @@ EXPORT_FUNC(PyLong_FromUInt32)
EXPORT_FUNC(PyLong_FromUInt64)
EXPORT_FUNC(PyLong_FromUnsignedLong)
EXPORT_FUNC(PyLong_FromUnsignedLongLong)
EXPORT_FUNC(PyLong_FromUnsignedNativeBytes)
EXPORT_FUNC(PyLong_FromVoidPtr)
EXPORT_FUNC(PyLong_GetInfo)
EXPORT_FUNC(PyMapping_Check)