diff --git a/Doc/c-api/long.rst b/Doc/c-api/long.rst index f09abea7429f14..7650d98fdea421 100644 --- a/Doc/c-api/long.rst +++ b/Doc/c-api/long.rst @@ -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: @@ -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) @@ -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. diff --git a/Include/cpython/longintrepr.h b/Include/cpython/longintrepr.h index 9c6422395664e1..357477b60d9a5a 100644 --- a/Include/cpython/longintrepr.h +++ b/Include/cpython/longintrepr.h @@ -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); diff --git a/Lib/test/test_capi/test_long.py b/Lib/test/test_capi/test_long.py index 894dea1d6bac25..4e6f86f3cf4b29 100644 --- a/Lib/test/test_capi/test_long.py +++ b/Lib/test/test_capi/test_long.py @@ -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) @@ -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) diff --git a/Modules/_testcapi/long.c b/Modules/_testcapi/long.c index 5b20b8c08c5e2a..a5f118bd481080 100644 --- a/Modules/_testcapi/long.c +++ b/Modules/_testcapi/long.c @@ -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; @@ -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; @@ -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); diff --git a/Objects/longobject.c b/Objects/longobject.c index 034ef08b2db9a4..c61c6ce7f57d2a 100644 --- a/Objects/longobject.c +++ b/Objects/longobject.c @@ -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), }; @@ -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; } @@ -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); }