mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
bpo-41324 Add a minimal decimal capsule API (#21519)
This commit is contained in:
parent
416f0b71ba
commit
39042e00ab
8 changed files with 1096 additions and 7 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2008-2012 Stefan Krah. All rights reserved.
|
||||
* Copyright (c) 2008-2020 Stefan Krah. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
|
@ -33,6 +33,8 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define CPYTHON_DECIMAL_MODULE
|
||||
#include "pydecimal.h"
|
||||
#include "docstrings.h"
|
||||
|
||||
|
||||
|
@ -5555,6 +5557,160 @@ static PyTypeObject PyDecContext_Type =
|
|||
};
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* C-API */
|
||||
/****************************************************************************/
|
||||
|
||||
static void *_decimal_api[CPYTHON_DECIMAL_MAX_API];
|
||||
|
||||
/* Simple API */
|
||||
static int
|
||||
PyDec_TypeCheck(const PyObject *v)
|
||||
{
|
||||
return PyDec_Check(v);
|
||||
}
|
||||
|
||||
static int
|
||||
PyDec_IsSpecial(const PyObject *v)
|
||||
{
|
||||
if (!PyDec_Check(v)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"PyDec_IsSpecial: argument must be a Decimal");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return mpd_isspecial(MPD(v));
|
||||
}
|
||||
|
||||
static int
|
||||
PyDec_IsNaN(const PyObject *v)
|
||||
{
|
||||
if (!PyDec_Check(v)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"PyDec_IsNaN: argument must be a Decimal");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return mpd_isnan(MPD(v));
|
||||
}
|
||||
|
||||
static int
|
||||
PyDec_IsInfinite(const PyObject *v)
|
||||
{
|
||||
if (!PyDec_Check(v)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"PyDec_IsInfinite: argument must be a Decimal");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return mpd_isinfinite(MPD(v));
|
||||
}
|
||||
|
||||
static int64_t
|
||||
PyDec_GetDigits(const PyObject *v)
|
||||
{
|
||||
if (!PyDec_Check(v)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"PyDec_GetDigits: argument must be a Decimal");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return MPD(v)->digits;
|
||||
}
|
||||
|
||||
static mpd_uint128_triple_t
|
||||
PyDec_AsUint128Triple(const PyObject *v)
|
||||
{
|
||||
if (!PyDec_Check(v)) {
|
||||
mpd_uint128_triple_t triple = { MPD_TRIPLE_ERROR, 0, 0, 0, 0 };
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"PyDec_AsUint128Triple: argument must be a Decimal");
|
||||
return triple;
|
||||
}
|
||||
|
||||
return mpd_as_uint128_triple(MPD(v));
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
PyDec_FromUint128Triple(const mpd_uint128_triple_t *triple)
|
||||
{
|
||||
PyObject *context;
|
||||
PyObject *result;
|
||||
uint32_t status = 0;
|
||||
|
||||
CURRENT_CONTEXT(context);
|
||||
|
||||
result = dec_alloc();
|
||||
if (result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (mpd_from_uint128_triple(MPD(result), triple, &status) < 0) {
|
||||
if (dec_addstatus(context, status)) {
|
||||
Py_DECREF(result);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Advanced API */
|
||||
static PyObject *
|
||||
PyDec_Alloc(void)
|
||||
{
|
||||
return dec_alloc();
|
||||
}
|
||||
|
||||
static mpd_t *
|
||||
PyDec_Get(PyObject *v)
|
||||
{
|
||||
if (!PyDec_Check(v)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"PyDec_Get: argument must be a Decimal");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return MPD(v);
|
||||
}
|
||||
|
||||
static const mpd_t *
|
||||
PyDec_GetConst(const PyObject *v)
|
||||
{
|
||||
if (!PyDec_Check(v)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"PyDec_GetConst: argument must be a Decimal");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return MPD(v);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
init_api(void)
|
||||
{
|
||||
/* Simple API */
|
||||
_decimal_api[PyDec_TypeCheck_INDEX] = (void *)PyDec_TypeCheck;
|
||||
_decimal_api[PyDec_IsSpecial_INDEX] = (void *)PyDec_IsSpecial;
|
||||
_decimal_api[PyDec_IsNaN_INDEX] = (void *)PyDec_IsNaN;
|
||||
_decimal_api[PyDec_IsInfinite_INDEX] = (void *)PyDec_IsInfinite;
|
||||
_decimal_api[PyDec_GetDigits_INDEX] = (void *)PyDec_GetDigits;
|
||||
_decimal_api[PyDec_AsUint128Triple_INDEX] = (void *)PyDec_AsUint128Triple;
|
||||
_decimal_api[PyDec_FromUint128Triple_INDEX] = (void *)PyDec_FromUint128Triple;
|
||||
|
||||
/* Advanced API */
|
||||
_decimal_api[PyDec_Alloc_INDEX] = (void *)PyDec_Alloc;
|
||||
_decimal_api[PyDec_Get_INDEX] = (void *)PyDec_Get;
|
||||
_decimal_api[PyDec_GetConst_INDEX] = (void *)PyDec_GetConst;
|
||||
|
||||
return PyCapsule_New(_decimal_api, "_decimal._API", NULL);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* Module */
|
||||
/****************************************************************************/
|
||||
|
||||
static PyMethodDef _decimal_methods [] =
|
||||
{
|
||||
{ "getcontext", (PyCFunction)PyDec_GetCurrentContext, METH_NOARGS, doc_getcontext},
|
||||
|
@ -5665,17 +5821,27 @@ PyInit__decimal(void)
|
|||
DecCondMap *cm;
|
||||
struct ssize_constmap *ssize_cm;
|
||||
struct int_constmap *int_cm;
|
||||
static PyObject *capsule = NULL;
|
||||
static int initialized = 0;
|
||||
int i;
|
||||
|
||||
|
||||
/* Init libmpdec */
|
||||
mpd_traphandler = dec_traphandler;
|
||||
mpd_mallocfunc = PyMem_Malloc;
|
||||
mpd_reallocfunc = PyMem_Realloc;
|
||||
mpd_callocfunc = mpd_callocfunc_em;
|
||||
mpd_free = PyMem_Free;
|
||||
mpd_setminalloc(_Py_DEC_MINALLOC);
|
||||
if (!initialized) {
|
||||
mpd_traphandler = dec_traphandler;
|
||||
mpd_mallocfunc = PyMem_Malloc;
|
||||
mpd_reallocfunc = PyMem_Realloc;
|
||||
mpd_callocfunc = mpd_callocfunc_em;
|
||||
mpd_free = PyMem_Free;
|
||||
mpd_setminalloc(_Py_DEC_MINALLOC);
|
||||
|
||||
capsule = init_api();
|
||||
if (capsule == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
initialized = 1;
|
||||
}
|
||||
|
||||
/* Init external C-API functions */
|
||||
_py_long_multiply = PyLong_Type.tp_as_number->nb_multiply;
|
||||
|
@ -5900,6 +6066,11 @@ PyInit__decimal(void)
|
|||
CHECK_INT(PyModule_AddStringConstant(m, "__version__", "1.70"));
|
||||
CHECK_INT(PyModule_AddStringConstant(m, "__libmpdec_version__", mpd_version()));
|
||||
|
||||
/* Add capsule API */
|
||||
Py_INCREF(capsule);
|
||||
if (PyModule_AddObject(m, "_API", capsule) < 0) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
return m;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue