mirror of
https://github.com/python/cpython.git
synced 2025-12-04 00:30:19 +00:00
Merged revisions 77842 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r77842 | mark.dickinson | 2010-01-30 10:08:33 +0000 (Sat, 30 Jan 2010) | 4 lines Issue #7767: Add new C-API function PyLong_AsLongLongAndOverflow, a long long variant of PyLong_AsLongAndOverflow. Patch by Case Van Horsen. ........
This commit is contained in:
parent
a79b75743a
commit
93f562c4f9
5 changed files with 280 additions and 0 deletions
|
|
@ -971,6 +971,7 @@ PyLong_AsVoidPtr(PyObject *vv)
|
|||
*/
|
||||
|
||||
#define IS_LITTLE_ENDIAN (int)*(unsigned char*)&one
|
||||
#define PY_ABS_LLONG_MIN (0-(unsigned PY_LONG_LONG)PY_LLONG_MIN)
|
||||
|
||||
/* Create a new long int object from a C PY_LONG_LONG int. */
|
||||
|
||||
|
|
@ -1269,6 +1270,101 @@ PyLong_AsUnsignedLongLongMask(register PyObject *op)
|
|||
}
|
||||
#undef IS_LITTLE_ENDIAN
|
||||
|
||||
/* Get a C long long int from a Python long or Python int object.
|
||||
On overflow, returns -1 and sets *overflow to 1 or -1 depending
|
||||
on the sign of the result. Otherwise *overflow is 0.
|
||||
|
||||
For other errors (e.g., type error), returns -1 and sets an error
|
||||
condition.
|
||||
*/
|
||||
|
||||
PY_LONG_LONG
|
||||
PyLong_AsLongLongAndOverflow(PyObject *vv, int *overflow)
|
||||
{
|
||||
/* This version by Tim Peters */
|
||||
register PyLongObject *v;
|
||||
unsigned PY_LONG_LONG x, prev;
|
||||
PY_LONG_LONG res;
|
||||
Py_ssize_t i;
|
||||
int sign;
|
||||
int do_decref = 0; /* if nb_int was called */
|
||||
|
||||
*overflow = 0;
|
||||
if (vv == NULL) {
|
||||
PyErr_BadInternalCall();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!PyLong_Check(vv)) {
|
||||
PyNumberMethods *nb;
|
||||
nb = vv->ob_type->tp_as_number;
|
||||
if (nb == NULL || nb->nb_int == NULL) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"an integer is required");
|
||||
return -1;
|
||||
}
|
||||
vv = (*nb->nb_int) (vv);
|
||||
if (vv == NULL)
|
||||
return -1;
|
||||
do_decref = 1;
|
||||
if (!PyLong_Check(vv)) {
|
||||
Py_DECREF(vv);
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"nb_int should return int object");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
res = -1;
|
||||
v = (PyLongObject *)vv;
|
||||
i = Py_SIZE(v);
|
||||
|
||||
switch (i) {
|
||||
case -1:
|
||||
res = -(sdigit)v->ob_digit[0];
|
||||
break;
|
||||
case 0:
|
||||
res = 0;
|
||||
break;
|
||||
case 1:
|
||||
res = v->ob_digit[0];
|
||||
break;
|
||||
default:
|
||||
sign = 1;
|
||||
x = 0;
|
||||
if (i < 0) {
|
||||
sign = -1;
|
||||
i = -(i);
|
||||
}
|
||||
while (--i >= 0) {
|
||||
prev = x;
|
||||
x = (x << PyLong_SHIFT) + v->ob_digit[i];
|
||||
if ((x >> PyLong_SHIFT) != prev) {
|
||||
*overflow = sign;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
/* Haven't lost any bits, but casting to long requires extra
|
||||
* care (see comment above).
|
||||
*/
|
||||
if (x <= (unsigned PY_LONG_LONG)PY_LLONG_MAX) {
|
||||
res = (PY_LONG_LONG)x * sign;
|
||||
}
|
||||
else if (sign < 0 && x == PY_ABS_LLONG_MIN) {
|
||||
res = PY_LLONG_MIN;
|
||||
}
|
||||
else {
|
||||
*overflow = sign;
|
||||
/* res is already set to -1 */
|
||||
}
|
||||
}
|
||||
exit:
|
||||
if (do_decref) {
|
||||
Py_DECREF(vv);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#endif /* HAVE_LONG_LONG */
|
||||
|
||||
#define CHECK_BINOP(v,w) \
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue