summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMeador Inge <meadori@gmail.com>2011-09-21 00:55:51 (GMT)
committerMeador Inge <meadori@gmail.com>2011-09-21 00:55:51 (GMT)
commit1c9f0c93ad26033aed79677fa0504af5a3cf0bbf (patch)
tree4fe6a5731001f84dec30ac34850459d24fa0a0fc
parent4ad6ed7d4dd79bed50b8f4d0bdbfa7af161e7294 (diff)
downloadcpython-1c9f0c93ad26033aed79677fa0504af5a3cf0bbf.zip
cpython-1c9f0c93ad26033aed79677fa0504af5a3cf0bbf.tar.gz
cpython-1c9f0c93ad26033aed79677fa0504af5a3cf0bbf.tar.bz2
Issue #1172711: Add 'long long' support to the array module.
Initial patch by Oren Tirosh and Hirokazu Yamamoto.
-rw-r--r--Doc/library/array.rst70
-rwxr-xr-xLib/test/test_array.py21
-rw-r--r--Misc/NEWS3
-rw-r--r--Modules/arraymodule.c79
4 files changed, 143 insertions, 30 deletions
diff --git a/Doc/library/array.rst b/Doc/library/array.rst
index d563cce..75f680e 100644
--- a/Doc/library/array.rst
+++ b/Doc/library/array.rst
@@ -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.
diff --git a/Lib/test/test_array.py b/Lib/test/test_array.py
index 5190c35..604dcdf 100755
--- a/Lib/test/test_array.py
+++ b/Lib/test/test_array.py
@@ -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]
diff --git a/Misc/NEWS b/Misc/NEWS
index 567e492..7b3cbd7 100644
--- 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.
diff --git a/Modules/arraymodule.c b/Modules/arraymodule.c
index 81c9c36..5748a3c 100644
--- a/Modules/arraymodule.c
+++ b/Modules/arraymodule.c
@@ -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\