summaryrefslogtreecommitdiffstats
path: root/Modules/_decimal/_decimal.c
diff options
context:
space:
mode:
authorStefan Krah <skrah@bytereef.org>2013-01-16 11:58:59 (GMT)
committerStefan Krah <skrah@bytereef.org>2013-01-16 11:58:59 (GMT)
commit59a4a93f43f2fa4f44b03ce0c1816eb2ae089fb9 (patch)
tree0d7a01f9fbd8e496282ba1df95872c97150209f5 /Modules/_decimal/_decimal.c
parent0ad344a8322a7c69b099e25c203d675a5ea3b60d (diff)
downloadcpython-59a4a93f43f2fa4f44b03ce0c1816eb2ae089fb9.zip
cpython-59a4a93f43f2fa4f44b03ce0c1816eb2ae089fb9.tar.gz
cpython-59a4a93f43f2fa4f44b03ce0c1816eb2ae089fb9.tar.bz2
Issue #16422: Use strings for rounding mode constants for better readability
and pickling compatibility.
Diffstat (limited to 'Modules/_decimal/_decimal.c')
-rw-r--r--Modules/_decimal/_decimal.c120
1 files changed, 55 insertions, 65 deletions
diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c
index 4dc9087..5e9fd67 100644
--- a/Modules/_decimal/_decimal.c
+++ b/Modules/_decimal/_decimal.c
@@ -202,6 +202,13 @@ static const char *dec_signal_string[MPD_NUM_FLAGS] = {
"Underflow",
};
+#ifdef EXTRA_FUNCTIONALITY
+ #define _PY_DEC_ROUND_GUARD MPD_ROUND_GUARD
+#else
+ #define _PY_DEC_ROUND_GUARD (MPD_ROUND_GUARD-1)
+#endif
+static PyObject *round_map[_PY_DEC_ROUND_GUARD];
+
static const char *invalid_rounding_err =
"valid values for rounding are:\n\
[ROUND_CEILING, ROUND_FLOOR, ROUND_UP, ROUND_DOWN,\n\
@@ -249,13 +256,6 @@ type_error_int(const char *mesg)
return -1;
}
-static PyObject *
-type_error_ptr(const char *mesg)
-{
- PyErr_SetString(PyExc_TypeError, mesg);
- return NULL;
-}
-
static int
runtime_error_int(const char *mesg)
{
@@ -502,6 +502,27 @@ dec_addstatus(PyObject *context, uint32_t status)
return 0;
}
+static int
+getround(PyObject *v)
+{
+ int i;
+
+ if (PyUnicode_Check(v)) {
+ for (i = 0; i < _PY_DEC_ROUND_GUARD; i++) {
+ if (v == round_map[i]) {
+ return i;
+ }
+ }
+ for (i = 0; i < _PY_DEC_ROUND_GUARD; i++) {
+ if (PyUnicode_Compare(v, round_map[i]) == 0) {
+ return i;
+ }
+ }
+ }
+
+ return type_error_int(invalid_rounding_err);
+}
+
/******************************************************************************/
/* SignalDict Object */
@@ -715,7 +736,6 @@ context_get##mem(PyObject *self, void *closure UNUSED) \
Dec_CONTEXT_GET_SSIZE(prec)
Dec_CONTEXT_GET_SSIZE(emax)
Dec_CONTEXT_GET_SSIZE(emin)
-Dec_CONTEXT_GET_SSIZE(round)
Dec_CONTEXT_GET_SSIZE(clamp)
#ifdef EXTRA_FUNCTIONALITY
@@ -724,6 +744,15 @@ Dec_CONTEXT_GET_ULONG(status)
#endif
static PyObject *
+context_getround(PyObject *self, void *closure UNUSED)
+{
+ int i = mpd_getround(CTX(self));
+
+ Py_INCREF(round_map[i]);
+ return round_map[i];
+}
+
+static PyObject *
context_getcapitals(PyObject *self, void *closure UNUSED)
{
return PyLong_FromLong(CtxCaps(self));
@@ -875,17 +904,16 @@ static int
context_setround(PyObject *self, PyObject *value, void *closure UNUSED)
{
mpd_context_t *ctx;
- mpd_ssize_t x;
+ int x;
- x = PyLong_AsSsize_t(value);
- if (x == -1 && PyErr_Occurred()) {
+ x = getround(value);
+ if (x == -1) {
return -1;
}
- BOUNDS_CHECK(x, INT_MIN, INT_MAX);
ctx = CTX(self);
- if (!mpd_qsetround(ctx, (int)x)) {
- return type_error_int(invalid_rounding_err);
+ if (!mpd_qsetround(ctx, x)) {
+ INTERNAL_ERROR_INT("context_setround"); /* GCOV_NOT_REACHED */
}
return 0;
@@ -1208,33 +1236,6 @@ context_dealloc(PyDecContextObject *self)
}
static int
-getround(PyObject *v)
-{
- const char *s;
- long x;
- int i;
-
- if (PyLong_Check(v)) {
- x = PyLong_AsLong(v);
- if (x == -1 && PyErr_Occurred()) {
- return -1;
- }
- BOUNDS_CHECK(x, 0, INT_MAX);
- return (int)x;
- }
- else if (PyUnicode_Check(v)) {
- for (i = 0; i < MPD_ROUND_GUARD; i++) {
- s = mpd_round_string[i];
- if (PyUnicode_CompareWithASCIIString(v, s) == 0) {
- return i;
- }
- }
- }
-
- return type_error_int("invalid rounding mode");
-}
-
-static int
context_init(PyObject *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {
@@ -1264,6 +1265,9 @@ context_init(PyObject *self, PyObject *args, PyObject *kwds)
if (prec != Py_None && context_setprec(self, prec, NULL) < 0) {
return -1;
}
+ if (rounding != Py_None && context_setround(self, rounding, NULL) < 0) {
+ return -1;
+ }
if (emin != Py_None && context_setemin(self, emin, NULL) < 0) {
return -1;
}
@@ -1277,16 +1281,6 @@ context_init(PyObject *self, PyObject *args, PyObject *kwds)
return -1;
}
- if (rounding != Py_None) {
- int x = getround(rounding);
- if (x < 0) {
- return -1;
- }
- if (!mpd_qsetround(CTX(self), x)) {
- return type_error_int(invalid_rounding_err);
- }
- }
-
if (traps != Py_None) {
if (PyList_Check(traps)) {
ret = context_settraps_list(self, traps);
@@ -3345,7 +3339,7 @@ PyDec_ToIntegralValue(PyObject *dec, PyObject *args, PyObject *kwds)
return NULL;
}
if (!mpd_qsetround(&workctx, round)) {
- return type_error_ptr(invalid_rounding_err);
+ INTERNAL_ERROR_PTR("PyDec_ToIntegralValue"); /* GCOV_NOT_REACHED */
}
}
@@ -3386,7 +3380,7 @@ PyDec_ToIntegralExact(PyObject *dec, PyObject *args, PyObject *kwds)
return NULL;
}
if (!mpd_qsetround(&workctx, round)) {
- return type_error_ptr(invalid_rounding_err);
+ INTERNAL_ERROR_PTR("PyDec_ToIntegralExact"); /* GCOV_NOT_REACHED */
}
}
@@ -4187,7 +4181,7 @@ dec_mpd_qquantize(PyObject *v, PyObject *args, PyObject *kwds)
return NULL;
}
if (!mpd_qsetround(&workctx, round)) {
- return type_error_ptr(invalid_rounding_err);
+ INTERNAL_ERROR_PTR("dec_mpd_qquantize"); /* GCOV_NOT_REACHED */
}
}
@@ -5419,17 +5413,6 @@ static struct int_constmap int_constants [] = {
{"DECIMAL64", MPD_DECIMAL64},
{"DECIMAL128", MPD_DECIMAL128},
{"IEEE_CONTEXT_MAX_BITS", MPD_IEEE_CONTEXT_MAX_BITS},
-#endif
- {"ROUND_CEILING", MPD_ROUND_CEILING},
- {"ROUND_FLOOR", MPD_ROUND_FLOOR},
- {"ROUND_UP", MPD_ROUND_UP},
- {"ROUND_DOWN", MPD_ROUND_DOWN},
- {"ROUND_HALF_UP", MPD_ROUND_HALF_UP},
- {"ROUND_HALF_DOWN", MPD_ROUND_HALF_DOWN},
- {"ROUND_HALF_EVEN", MPD_ROUND_HALF_EVEN},
- {"ROUND_05UP", MPD_ROUND_05UP},
-#ifdef EXTRA_FUNCTIONALITY
- {"ROUND_TRUNC", MPD_ROUND_TRUNC},
/* int condition flags */
{"DecClamped", MPD_Clamped},
{"DecConversionSyntax", MPD_Conversion_syntax},
@@ -5680,6 +5663,13 @@ PyInit__decimal(void)
int_cm->val));
}
+ /* Init string constants */
+ for (i = 0; i < _PY_DEC_ROUND_GUARD; i++) {
+ ASSIGN_PTR(round_map[i], PyUnicode_InternFromString(mpd_round_string[i]));
+ Py_INCREF(round_map[i]);
+ CHECK_INT(PyModule_AddObject(m, mpd_round_string[i], round_map[i]));
+ }
+
/* Add specification version number */
CHECK_INT(PyModule_AddStringConstant(m, "__version__", " 1.70"));