Issue #1172711: Add 'long long' support to the array module.

Initial patch by Oren Tirosh and Hirokazu Yamamoto.
This commit is contained in:
Meador Inge 2011-09-20 19:55:51 -05:00
parent 4ad6ed7d4d
commit 1c9f0c93ad
4 changed files with 141 additions and 28 deletions

View 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 |
+-----------+----------------+-------------------+-----------------------+
+-----------+--------------------+-------------------+-----------------------+-------+
| 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 | |
+-----------+--------------------+-------------------+-----------------------+-------+
.. note::
Notes:
The ``'u'`` typecode corresponds to Python's unicode character. On narrow
(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.

View File

@ -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]

View File

@ -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.

View 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\