Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 12 additions & 7 deletions Doc/c-api/long.rst
Original file line number Diff line number Diff line change
Expand Up @@ -685,7 +685,7 @@ Export API
- ``1`` for most significant digit first
- ``-1`` for least significant digit first

.. c:member:: int8_t endian
.. c:member:: int8_t digit_endianness

Digit endianness:

Expand Down Expand Up @@ -772,19 +772,20 @@ The :c:type:`PyLongWriter` API can be used to import an integer.

Create a :c:type:`PyLongWriter`.

On success, set *\*digits* and return a writer.
On success, allocate *\*digits* and return a writer.
On error, set an exception and return ``NULL``.

*negative* is ``1`` if the number is negative, or ``0`` otherwise.

*ndigits* is the number of digits in the *digits* array. It must be
greater than or equal to 0.
greater than 0.

The caller can either initialize the array of digits *digits* and then call
:c:func:`PyLongWriter_Finish` to get a Python :class:`int`, or call
The caller can either initialize the array of digits *digits* and then
either call :c:func:`PyLongWriter_Finish` to get a Python :class:`int` or
:c:func:`PyLongWriter_Discard` to destroy the writer instance. Digits must
be in the range [``0``; ``(1 << sys.int_info.bits_per_digit) - 1``]. Unused
digits must be set to ``0``.
be in the range [``0``; ``(1 << bits_per_digit) - 1``] (where the
:c:struct:`~PyLongLayout.bits_per_digit` is the number of bits per digit).
The unused most-significant digits must be set to ``0``.


.. c:function:: PyObject* PyLongWriter_Finish(PyLongWriter *writer)
Expand All @@ -797,7 +798,11 @@ The :c:type:`PyLongWriter` API can be used to import an integer.
The function takes care of normalizing the digits and converts the object
to a compact integer if needed.

The writer instance is invalid after the call.


.. c:function:: void PyLongWriter_Discard(PyLongWriter *writer)

Discard a :c:type:`PyLongWriter` created by :c:func:`PyLongWriter_Create`.

The writer instance is invalid after the call.
2 changes: 1 addition & 1 deletion Include/cpython/longintrepr.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ typedef struct PyLongLayout {
uint8_t bits_per_digit;
uint8_t digit_size;
int8_t digits_order;
int8_t endianness;
int8_t digit_endianness;
} PyLongLayout;

PyAPI_FUNC(const PyLongLayout*) PyLong_GetNativeLayout(void);
Expand Down
5 changes: 3 additions & 2 deletions Lib/test/test_capi/test_long.py
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,7 @@ def test_long_layout(self):
'bits_per_digit': int_info.bits_per_digit,
'digit_size': int_info.sizeof_digit,
'digits_order': -1,
'endianness': -1 if sys.byteorder == 'little' else 1,
'digit_endianness': -1 if sys.byteorder == 'little' else 1,
}
self.assertEqual(layout, expected)

Expand Down Expand Up @@ -756,7 +756,8 @@ def test_longwriter_create(self):
base = 2 ** layout['bits_per_digit']

pylongwriter_create = _testcapi.pylongwriter_create
self.assertEqual(pylongwriter_create(0, []), 0)
self.assertRaises(ValueError, pylongwriter_create, 0, [])
self.assertRaises(ValueError, pylongwriter_create, -123, [])
self.assertEqual(pylongwriter_create(0, [0]), 0)
self.assertEqual(pylongwriter_create(0, [123]), 123)
self.assertEqual(pylongwriter_create(1, [123]), -123)
Expand Down
8 changes: 4 additions & 4 deletions Modules/_testcapi/long.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,11 +180,11 @@ layout_to_dict(const PyLongLayout *layout)
goto error;
}

value = PyLong_FromLong(layout->endianness);
value = PyLong_FromLong(layout->digit_endianness);
if (value == NULL) {
goto error;
}
res = PyDict_SetItemString(dict, "endianness", value);
res = PyDict_SetItemString(dict, "digit_endianness", value);
Py_DECREF(value);
if (res < 0) {
goto error;
Expand Down Expand Up @@ -215,7 +215,7 @@ pylong_export(PyObject *module, PyObject *obj)
const digit *export_long_digits = export_long.digits;

PyObject *digits = PyList_New(0);
for (Py_ssize_t i=0; i < export_long.ndigits; i++) {
for (Py_ssize_t i = 0; i < export_long.ndigits; i++) {
PyObject *item = PyLong_FromUnsignedLong(export_long_digits[i]);
if (item == NULL) {
goto error;
Expand Down Expand Up @@ -258,7 +258,7 @@ pylongwriter_create(PyObject *module, PyObject *args)
return PyErr_NoMemory();
}

for (Py_ssize_t i=0; i < ndigits; i++) {
for (Py_ssize_t i = 0; i < ndigits; i++) {
PyObject *item = PyList_GET_ITEM(list, i);

long num = PyLong_AsLong(item);
Expand Down
7 changes: 2 additions & 5 deletions Objects/longobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -6781,7 +6781,7 @@ int PyLong_AsUInt64(PyObject *obj, uint64_t *value)
static const PyLongLayout PyLong_LAYOUT = {
.bits_per_digit = PyLong_SHIFT,
.digits_order = -1, // least significant first
.endianness = PY_LITTLE_ENDIAN ? -1 : 1,
.digit_endianness = PY_LITTLE_ENDIAN ? -1 : 1,
.digit_size = sizeof(digit),
};

Expand Down Expand Up @@ -6851,7 +6851,7 @@ PyLong_FreeExport(PyLongExport *export_long)
PyLongWriter*
PyLongWriter_Create(int negative, Py_ssize_t ndigits, void **digits)
{
if (ndigits < 0) {
if (ndigits <= 0) {
PyErr_SetString(PyExc_ValueError, "ndigits must be positive");
return NULL;
}
Expand All @@ -6861,9 +6861,6 @@ PyLongWriter_Create(int negative, Py_ssize_t ndigits, void **digits)
if (obj == NULL) {
return NULL;
}
if (ndigits == 0) {
assert(obj->long_value.ob_digit[0] == 0);
}
if (negative) {
_PyLong_FlipSign(obj);
}
Expand Down
Loading