]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Issue #1172711: Add 'long long' support to the array module.
authorMeador Inge <meadori@gmail.com>
Wed, 21 Sep 2011 00:55:51 +0000 (19:55 -0500)
committerMeador Inge <meadori@gmail.com>
Wed, 21 Sep 2011 00:55:51 +0000 (19:55 -0500)
Initial patch by Oren Tirosh and Hirokazu Yamamoto.

Doc/library/array.rst
Lib/test/test_array.py
Misc/NEWS
Modules/arraymodule.c

index d563cceb77aeaca1fa5c05c48da2f8d36493887f..75f680e5b4a89c24ab559010b0b5c8c87ade6507 100644 (file)
@@ -14,37 +14,49 @@ them is constrained.  The type is specified at object creation time by using a
 :dfn:`type code`, which is a single character.  The following type codes are
 defined:
 
-+-----------+----------------+-------------------+-----------------------+
-| Type code | C Type         | Python Type       | Minimum size in bytes |
-+===========+================+===================+=======================+
-| ``'b'``   | signed char    | int               | 1                     |
-+-----------+----------------+-------------------+-----------------------+
-| ``'B'``   | unsigned char  | int               | 1                     |
-+-----------+----------------+-------------------+-----------------------+
-| ``'u'``   | Py_UNICODE     | Unicode character | 2 (see note)          |
-+-----------+----------------+-------------------+-----------------------+
-| ``'h'``   | signed short   | int               | 2                     |
-+-----------+----------------+-------------------+-----------------------+
-| ``'H'``   | unsigned short | int               | 2                     |
-+-----------+----------------+-------------------+-----------------------+
-| ``'i'``   | signed int     | int               | 2                     |
-+-----------+----------------+-------------------+-----------------------+
-| ``'I'``   | unsigned int   | int               | 2                     |
-+-----------+----------------+-------------------+-----------------------+
-| ``'l'``   | signed long    | int               | 4                     |
-+-----------+----------------+-------------------+-----------------------+
-| ``'L'``   | unsigned long  | int               | 4                     |
-+-----------+----------------+-------------------+-----------------------+
-| ``'f'``   | float          | float             | 4                     |
-+-----------+----------------+-------------------+-----------------------+
-| ``'d'``   | double         | float             | 8                     |
-+-----------+----------------+-------------------+-----------------------+
-
-.. note::
-
-   The ``'u'`` typecode corresponds to Python's unicode character.  On narrow
++-----------+--------------------+-------------------+-----------------------+-------+
+| Type code | C Type             | Python Type       | Minimum size in bytes | Notes |
++===========+====================+===================+=======================+=======+
+| ``'b'``   | signed char        | int               | 1                     |       |
++-----------+--------------------+-------------------+-----------------------+-------+
+| ``'B'``   | unsigned char      | int               | 1                     |       |
++-----------+--------------------+-------------------+-----------------------+-------+
+| ``'u'``   | Py_UNICODE         | Unicode character | 2                     | \(1)  |
++-----------+--------------------+-------------------+-----------------------+-------+
+| ``'h'``   | signed short       | int               | 2                     |       |
++-----------+--------------------+-------------------+-----------------------+-------+
+| ``'H'``   | unsigned short     | int               | 2                     |       |
++-----------+--------------------+-------------------+-----------------------+-------+
+| ``'i'``   | signed int         | int               | 2                     |       |
++-----------+--------------------+-------------------+-----------------------+-------+
+| ``'I'``   | unsigned int       | int               | 2                     |       |
++-----------+--------------------+-------------------+-----------------------+-------+
+| ``'l'``   | signed long        | int               | 4                     |       |
++-----------+--------------------+-------------------+-----------------------+-------+
+| ``'L'``   | unsigned long      | int               | 4                     |       |
++-----------+--------------------+-------------------+-----------------------+-------+
+| ``'q'``   | signed long long   | int               | 8                     | \(2)  |
++-----------+--------------------+-------------------+-----------------------+-------+
+| ``'Q'``   | unsigned long long | int               | 8                     | \(2)  |
++-----------+--------------------+-------------------+-----------------------+-------+
+| ``'f'``   | float              | float             | 4                     |       |
++-----------+--------------------+-------------------+-----------------------+-------+
+| ``'d'``   | double             | float             | 8                     |       |
++-----------+--------------------+-------------------+-----------------------+-------+
+
+Notes:
+
+(1)
+   The ``'u'`` type code corresponds to Python's unicode character.  On narrow
    Unicode builds this is 2-bytes, on wide builds this is 4-bytes.
 
+(2)
+   The ``'q'`` and ``'Q'`` type codes are available only if
+   the platform C compiler used to build Python supports C :ctype:`long long`,
+   or, on Windows, :ctype:`__int64`.
+
+   .. versionadded:: 3.3
+
 The actual representation of values is determined by the machine architecture
 (strictly speaking, by the C implementation).  The actual size can be accessed
 through the :attr:`itemsize` attribute.
index 5190c357ea949c803144df10be91289a254d0bfa..604dcdf8a5e51b83b6dbb4f60a8473e42c46f4ca 100755 (executable)
@@ -16,6 +16,13 @@ import warnings
 import array
 from array import _array_reconstructor as array_reconstructor
 
+try:
+    # Try to determine availability of long long independently
+    # of the array module under test
+    struct.calcsize('@q')
+    have_long_long = True
+except struct.error:
+    have_long_long = False
 
 class ArraySubclass(array.array):
     pass
@@ -26,6 +33,8 @@ class ArraySubclassWithKwargs(array.array):
 
 tests = [] # list to accumulate all tests
 typecodes = "ubBhHiIlLfd"
+if have_long_long:
+    typecodes += 'qQ'
 
 class BadConstructorTest(unittest.TestCase):
 
@@ -1205,6 +1214,18 @@ class UnsignedLongTest(UnsignedNumberTest):
     minitemsize = 4
 tests.append(UnsignedLongTest)
 
+@unittest.skipIf(not have_long_long, 'need long long support')
+class LongLongTest(SignedNumberTest):
+    typecode = 'q'
+    minitemsize = 8
+tests.append(LongLongTest)
+
+@unittest.skipIf(not have_long_long, 'need long long support')
+class UnsignedLongLongTest(UnsignedNumberTest):
+    typecode = 'Q'
+    minitemsize = 8
+tests.append(UnsignedLongLongTest)
+
 class FPTest(NumberTest):
     example = [-42.0, 0, 42, 1e5, -1e10]
     smallerexample = [-42.0, 0, 42, 1e5, -2e10]
index 567e49299197ae1491ba1fd8f8837395f8525b73..7b3cbd71a9d06a7dc05c3d8b7190b1838732f35d 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -1287,6 +1287,9 @@ Tools/Demos
 Extension Modules
 -----------------
 
+- Issue #1172711: Add 'long long' support to the array module.
+  Initial patch by Oren Tirosh and Hirokazu Yamamoto.
+
 - Issue #12483: ctypes: Fix a crash when the destruction of a callback
   object triggers the garbage collector.
 
index 81c9c363d36b4a89b6108b1b56ca68be11e258e5..5748a3c04758104ce1a2a72cc2b92e854774a5f8 100644 (file)
@@ -356,6 +356,59 @@ LL_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
     return 0;
 }
 
+#ifdef HAVE_LONG_LONG
+
+static PyObject *
+q_getitem(arrayobject *ap, Py_ssize_t i)
+{
+    return PyLong_FromLongLong(((PY_LONG_LONG *)ap->ob_item)[i]);
+}
+
+static int
+q_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
+{
+    PY_LONG_LONG x;
+    if (!PyArg_Parse(v, "L;array item must be integer", &x))
+        return -1;
+    if (i >= 0)
+        ((PY_LONG_LONG *)ap->ob_item)[i] = x;
+    return 0;
+}
+
+static PyObject *
+QQ_getitem(arrayobject *ap, Py_ssize_t i)
+{
+    return PyLong_FromUnsignedLongLong(
+        ((unsigned PY_LONG_LONG *)ap->ob_item)[i]);
+}
+
+static int
+QQ_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
+{
+    unsigned PY_LONG_LONG x;
+    if (PyLong_Check(v)) {
+        x = PyLong_AsUnsignedLongLong(v);
+        if (x == (unsigned PY_LONG_LONG) -1 && PyErr_Occurred())
+            return -1;
+    }
+    else {
+        PY_LONG_LONG y;
+        if (!PyArg_Parse(v, "L;array item must be integer", &y))
+            return -1;
+        if (y < 0) {
+            PyErr_SetString(PyExc_OverflowError,
+                "unsigned long long is less than minimum");
+            return -1;
+        }
+        x = (unsigned PY_LONG_LONG)y;
+    }
+
+    if (i >= 0)
+        ((unsigned PY_LONG_LONG *)ap->ob_item)[i] = x;
+    return 0;
+}
+#endif
+
 static PyObject *
 f_getitem(arrayobject *ap, Py_ssize_t i)
 {
@@ -406,6 +459,10 @@ static struct arraydescr descriptors[] = {
     {'I', sizeof(int), II_getitem, II_setitem, "I", 1, 0},
     {'l', sizeof(long), l_getitem, l_setitem, "l", 1, 1},
     {'L', sizeof(long), LL_getitem, LL_setitem, "L", 1, 0},
+#ifdef HAVE_LONG_LONG
+    {'q', sizeof(PY_LONG_LONG), q_getitem, q_setitem, "q", 1, 1},
+    {'Q', sizeof(PY_LONG_LONG), QQ_getitem, QQ_setitem, "Q", 1, 0},
+#endif
     {'f', sizeof(float), f_getitem, f_setitem, "f", 0, 0},
     {'d', sizeof(double), d_getitem, d_setitem, "d", 0, 0},
     {'\0', 0, 0, 0, 0, 0, 0} /* Sentinel */
@@ -1655,6 +1712,16 @@ typecode_to_mformat_code(int typecode)
         intsize = sizeof(long);
         is_signed = 0;
         break;
+#if HAVE_LONG_LONG
+    case 'q':
+        intsize = sizeof(PY_LONG_LONG);
+        is_signed = 1;
+        break;
+    case 'Q':
+        intsize = sizeof(PY_LONG_LONG);
+        is_signed = 0;
+        break;
+#endif 
     default:
         return UNKNOWN_FORMAT;
     }
@@ -2501,7 +2568,11 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         }
     }
     PyErr_SetString(PyExc_ValueError,
+#ifdef HAVE_LONG_LONG
+        "bad typecode (must be b, B, u, h, H, i, I, l, L, q, Q, f or d)");
+#else
         "bad typecode (must be b, B, u, h, H, i, I, l, L, f or d)");
+#endif
     return NULL;
 }
 
@@ -2524,12 +2595,18 @@ is a single character.  The following type codes are defined:\n\
     'I'         unsigned integer   2 \n\
     'l'         signed integer     4 \n\
     'L'         unsigned integer   4 \n\
+    'q'         signed integer     8 (see note) \n\
+    'Q'         unsigned integer   8 (see note) \n\
     'f'         floating point     4 \n\
     'd'         floating point     8 \n\
 \n\
-NOTE: The 'u' typecode corresponds to Python's unicode character. On \n\
+NOTE: The 'u' type code corresponds to Python's unicode character. On \n\
 narrow builds this is 2-bytes on wide builds this is 4-bytes.\n\
 \n\
+NOTE: The 'q' and 'Q' type codes are only available if the platform \n\
+C compiler used to build Python supports 'long long', or, on Windows, \n\
+'__int64'.\n\
+\n\
 The constructor is:\n\
 \n\
 array(typecode [, initializer]) -- create a new array\n\