[pypy-svn] pypy default: cpyext: implement PyLong_AsLongAndOverflow
amauryfa
commits-noreply at bitbucket.org
Fri Dec 17 19:00:13 CET 2010
Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch:
Changeset: r40097:dd665acd02c1
Date: 2010-11-06 23:32 +0000
http://bitbucket.org/pypy/pypy/changeset/dd665acd02c1/
Log: cpyext: implement PyLong_AsLongAndOverflow
(transplanted from 530b4cfd30162ce5e05acf9f06c328e0c42de38f)
diff --git a/pypy/module/cpyext/longobject.py b/pypy/module/cpyext/longobject.py
--- a/pypy/module/cpyext/longobject.py
+++ b/pypy/module/cpyext/longobject.py
@@ -62,6 +62,48 @@
raised."""
return rffi.cast(rffi.ULONGLONG, space.r_ulonglong_w(w_long))
+ at cpython_api([PyObject, rffi.CArrayPtr(rffi.INT_real)], lltype.Signed,
+ error=-1)
+def PyLong_AsLongAndOverflow(space, w_long, overflow_ptr):
+ """
+ Return a C long representation of the contents of pylong. If pylong is
+ greater than LONG_MAX or less than LONG_MIN, set *overflow to 1 or -1,
+ respectively, and return -1; otherwise, set *overflow to 0. If any other
+ exception occurs (for example a TypeError or MemoryError), then -1 will be
+ returned and *overflow will be 0."""
+ overflow_ptr[0] = 0
+ try:
+ return space.int_w(w_long)
+ except OperationError, e:
+ if not e.match(space, space.w_OverflowError):
+ raise
+ if space.is_true(space.gt(w_long, space.wrap(0))):
+ overflow_ptr[0] = 1
+ else:
+ overflow_ptr[0] = -1
+ return -1
+
+ at cpython_api([PyObject, rffi.CArrayPtr(rffi.INT_real)], rffi.LONGLONG,
+ error=-1)
+def PyLong_AsLongLongAndOverflow(space, w_long, overflow_ptr):
+ """
+ Return a C long long representation of the contents of pylong. If pylong is
+ greater than PY_LLONG_MAX or less than PY_LLONG_MIN, set *overflow to 1 or
+ -1, respectively, and return -1; otherwise, set *overflow to 0. If any
+ other exception occurs (for example a TypeError or MemoryError), then -1
+ will be returned and *overflow will be 0."""
+ overflow_ptr[0] = 0
+ try:
+ return rffi.cast(rffi.LONGLONG, space.r_longlong_w(w_long))
+ except OperationError, e:
+ if not e.match(space, space.w_OverflowError):
+ raise
+ if space.is_true(space.gt(w_long, space.wrap(0))):
+ overflow_ptr[0] = 1
+ else:
+ overflow_ptr[0] = -1
+ return -1
+
@cpython_api([lltype.Float], PyObject)
def PyLong_FromDouble(space, val):
"""Return a new PyLongObject object from v, or NULL on failure."""
diff --git a/pypy/module/cpyext/test/test_longobject.py b/pypy/module/cpyext/test/test_longobject.py
--- a/pypy/module/cpyext/test/test_longobject.py
+++ b/pypy/module/cpyext/test/test_longobject.py
@@ -64,6 +64,30 @@
assert api.PyErr_Occurred()
api.PyErr_Clear()
+ def test_as_long_and_overflow(self, space, api):
+ overflow = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
+ assert api.PyLong_AsLongAndOverflow(
+ space.wrap(sys.maxint), overflow) == sys.maxint
+ assert api.PyLong_AsLongAndOverflow(
+ space.wrap(-sys.maxint - 2), overflow) == -1
+ assert not api.PyErr_Occurred()
+ assert overflow[0] == -1
+ lltype.free(overflow, flavor='raw')
+
+ def test_as_longlong_and_overflow(self, space, api):
+ overflow = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
+ assert api.PyLong_AsLongLongAndOverflow(
+ space.wrap(1<<62), overflow) == 1<<62
+ assert api.PyLong_AsLongLongAndOverflow(
+ space.wrap(1<<63), overflow) == -1
+ assert not api.PyErr_Occurred()
+ assert overflow[0] == 1
+ assert api.PyLong_AsLongLongAndOverflow(
+ space.wrap(-1<<64), overflow) == -1
+ assert not api.PyErr_Occurred()
+ assert overflow[0] == -1
+ lltype.free(overflow, flavor='raw')
+
def test_as_voidptr(self, space, api):
w_l = api.PyLong_FromVoidPtr(lltype.nullptr(rffi.VOIDP.TO))
assert space.unwrap(w_l) == 0L
More information about the Pypy-commit
mailing list