[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