summaryrefslogtreecommitdiffstats
path: root/Modules/_testcapi/long.c
diff options
context:
space:
mode:
Diffstat (limited to 'Modules/_testcapi/long.c')
-rw-r--r--Modules/_testcapi/long.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/Modules/_testcapi/long.c b/Modules/_testcapi/long.c
index ebea090..4224302 100644
--- a/Modules/_testcapi/long.c
+++ b/Modules/_testcapi/long.c
@@ -141,6 +141,127 @@ pylong_aspid(PyObject *module, PyObject *arg)
}
+static PyObject *
+layout_to_dict(const PyLongLayout *layout)
+{
+ return Py_BuildValue("{sisisisi}",
+ "bits_per_digit", (int)layout->bits_per_digit,
+ "digit_size", (int)layout->digit_size,
+ "digits_order", (int)layout->digits_order,
+ "digit_endianness", (int)layout->digit_endianness);
+}
+
+
+static PyObject *
+pylong_export(PyObject *module, PyObject *obj)
+{
+ PyLongExport export_long;
+ if (PyLong_Export(obj, &export_long) < 0) {
+ return NULL;
+ }
+
+ if (export_long.digits == NULL) {
+ assert(export_long.negative == 0);
+ assert(export_long.ndigits == 0);
+ assert(export_long.digits == NULL);
+ PyObject *res = PyLong_FromInt64(export_long.value);
+ PyLong_FreeExport(&export_long);
+ return res;
+ }
+
+ assert(PyLong_GetNativeLayout()->digit_size == sizeof(digit));
+ const digit *export_long_digits = export_long.digits;
+
+ PyObject *digits = PyList_New(0);
+ if (digits == NULL) {
+ goto error;
+ }
+ for (Py_ssize_t i = 0; i < export_long.ndigits; i++) {
+ PyObject *item = PyLong_FromUnsignedLong(export_long_digits[i]);
+ if (item == NULL) {
+ goto error;
+ }
+
+ if (PyList_Append(digits, item) < 0) {
+ Py_DECREF(item);
+ goto error;
+ }
+ Py_DECREF(item);
+ }
+
+ assert(export_long.value == 0);
+ PyObject *res = Py_BuildValue("(iN)", export_long.negative, digits);
+
+ PyLong_FreeExport(&export_long);
+ assert(export_long._reserved == 0);
+
+ return res;
+
+error:
+ Py_XDECREF(digits);
+ PyLong_FreeExport(&export_long);
+ return NULL;
+}
+
+
+static PyObject *
+pylongwriter_create(PyObject *module, PyObject *args)
+{
+ int negative;
+ PyObject *list;
+ // TODO(vstinner): write test for negative ndigits and digits==NULL
+ if (!PyArg_ParseTuple(args, "iO!", &negative, &PyList_Type, &list)) {
+ return NULL;
+ }
+ Py_ssize_t ndigits = PyList_GET_SIZE(list);
+
+ digit *digits = PyMem_Malloc((size_t)ndigits * sizeof(digit));
+ if (digits == NULL) {
+ return PyErr_NoMemory();
+ }
+
+ for (Py_ssize_t i = 0; i < ndigits; i++) {
+ PyObject *item = PyList_GET_ITEM(list, i);
+
+ long num = PyLong_AsLong(item);
+ if (num == -1 && PyErr_Occurred()) {
+ goto error;
+ }
+
+ if (num < 0 || num >= PyLong_BASE) {
+ PyErr_SetString(PyExc_ValueError, "digit doesn't fit into digit");
+ goto error;
+ }
+ digits[i] = (digit)num;
+ }
+
+ void *writer_digits;
+ PyLongWriter *writer = PyLongWriter_Create(negative, ndigits,
+ &writer_digits);
+ if (writer == NULL) {
+ goto error;
+ }
+ assert(PyLong_GetNativeLayout()->digit_size == sizeof(digit));
+ memcpy(writer_digits, digits, (size_t)ndigits * sizeof(digit));
+ PyObject *res = PyLongWriter_Finish(writer);
+ PyMem_Free(digits);
+
+ return res;
+
+error:
+ PyMem_Free(digits);
+ return NULL;
+}
+
+
+static PyObject *
+get_pylong_layout(PyObject *module, PyObject *Py_UNUSED(args))
+{
+ const PyLongLayout *layout = PyLong_GetNativeLayout();
+ return layout_to_dict(layout);
+}
+
+
static PyMethodDef test_methods[] = {
_TESTCAPI_CALL_LONG_COMPACT_API_METHODDEF
{"pylong_fromunicodeobject", pylong_fromunicodeobject, METH_VARARGS},
@@ -148,6 +269,9 @@ static PyMethodDef test_methods[] = {
{"pylong_fromnativebytes", pylong_fromnativebytes, METH_VARARGS},
{"pylong_getsign", pylong_getsign, METH_O},
{"pylong_aspid", pylong_aspid, METH_O},
+ {"pylong_export", pylong_export, METH_O},
+ {"pylongwriter_create", pylongwriter_create, METH_VARARGS},
+ {"get_pylong_layout", get_pylong_layout, METH_NOARGS},
{"pylong_ispositive", pylong_ispositive, METH_O},
{"pylong_isnegative", pylong_isnegative, METH_O},
{"pylong_iszero", pylong_iszero, METH_O},