Kaydet (Commit) 1c9f0c93 authored tarafından Meador Inge's avatar Meador Inge

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

Initial patch by Oren Tirosh and Hirokazu Yamamoto.
üst 4ad6ed7d
...@@ -14,37 +14,49 @@ them is constrained. The type is specified at object creation time by using a ...@@ -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 :dfn:`type code`, which is a single character. The following type codes are
defined: defined:
+-----------+----------------+-------------------+-----------------------+ +-----------+--------------------+-------------------+-----------------------+-------+
| Type code | C Type | Python Type | Minimum size in bytes | | Type code | C Type | Python Type | Minimum size in bytes | Notes |
+===========+================+===================+=======================+ +===========+====================+===================+=======================+=======+
| ``'b'`` | signed char | int | 1 | | ``'b'`` | signed char | int | 1 | |
+-----------+----------------+-------------------+-----------------------+ +-----------+--------------------+-------------------+-----------------------+-------+
| ``'B'`` | unsigned char | int | 1 | | ``'B'`` | unsigned char | int | 1 | |
+-----------+----------------+-------------------+-----------------------+ +-----------+--------------------+-------------------+-----------------------+-------+
| ``'u'`` | Py_UNICODE | Unicode character | 2 (see note) | | ``'u'`` | Py_UNICODE | Unicode character | 2 | \(1) |
+-----------+----------------+-------------------+-----------------------+ +-----------+--------------------+-------------------+-----------------------+-------+
| ``'h'`` | signed short | int | 2 | | ``'h'`` | signed short | int | 2 | |
+-----------+----------------+-------------------+-----------------------+ +-----------+--------------------+-------------------+-----------------------+-------+
| ``'H'`` | unsigned short | int | 2 | | ``'H'`` | unsigned short | int | 2 | |
+-----------+----------------+-------------------+-----------------------+ +-----------+--------------------+-------------------+-----------------------+-------+
| ``'i'`` | signed int | int | 2 | | ``'i'`` | signed int | int | 2 | |
+-----------+----------------+-------------------+-----------------------+ +-----------+--------------------+-------------------+-----------------------+-------+
| ``'I'`` | unsigned int | int | 2 | | ``'I'`` | unsigned int | int | 2 | |
+-----------+----------------+-------------------+-----------------------+ +-----------+--------------------+-------------------+-----------------------+-------+
| ``'l'`` | signed long | int | 4 | | ``'l'`` | signed long | int | 4 | |
+-----------+----------------+-------------------+-----------------------+ +-----------+--------------------+-------------------+-----------------------+-------+
| ``'L'`` | unsigned long | int | 4 | | ``'L'`` | unsigned long | int | 4 | |
+-----------+----------------+-------------------+-----------------------+ +-----------+--------------------+-------------------+-----------------------+-------+
| ``'f'`` | float | float | 4 | | ``'q'`` | signed long long | int | 8 | \(2) |
+-----------+----------------+-------------------+-----------------------+ +-----------+--------------------+-------------------+-----------------------+-------+
| ``'d'`` | double | float | 8 | | ``'Q'`` | unsigned long long | int | 8 | \(2) |
+-----------+----------------+-------------------+-----------------------+ +-----------+--------------------+-------------------+-----------------------+-------+
| ``'f'`` | float | float | 4 | |
.. note:: +-----------+--------------------+-------------------+-----------------------+-------+
| ``'d'`` | double | float | 8 | |
The ``'u'`` typecode corresponds to Python's unicode character. On narrow +-----------+--------------------+-------------------+-----------------------+-------+
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. 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 The actual representation of values is determined by the machine architecture
(strictly speaking, by the C implementation). The actual size can be accessed (strictly speaking, by the C implementation). The actual size can be accessed
through the :attr:`itemsize` attribute. through the :attr:`itemsize` attribute.
......
...@@ -16,6 +16,13 @@ import warnings ...@@ -16,6 +16,13 @@ import warnings
import array import array
from array import _array_reconstructor as array_reconstructor 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): class ArraySubclass(array.array):
pass pass
...@@ -26,6 +33,8 @@ class ArraySubclassWithKwargs(array.array): ...@@ -26,6 +33,8 @@ class ArraySubclassWithKwargs(array.array):
tests = [] # list to accumulate all tests tests = [] # list to accumulate all tests
typecodes = "ubBhHiIlLfd" typecodes = "ubBhHiIlLfd"
if have_long_long:
typecodes += 'qQ'
class BadConstructorTest(unittest.TestCase): class BadConstructorTest(unittest.TestCase):
...@@ -1205,6 +1214,18 @@ class UnsignedLongTest(UnsignedNumberTest): ...@@ -1205,6 +1214,18 @@ class UnsignedLongTest(UnsignedNumberTest):
minitemsize = 4 minitemsize = 4
tests.append(UnsignedLongTest) 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): class FPTest(NumberTest):
example = [-42.0, 0, 42, 1e5, -1e10] example = [-42.0, 0, 42, 1e5, -1e10]
smallerexample = [-42.0, 0, 42, 1e5, -2e10] smallerexample = [-42.0, 0, 42, 1e5, -2e10]
......
...@@ -1287,6 +1287,9 @@ Tools/Demos ...@@ -1287,6 +1287,9 @@ Tools/Demos
Extension Modules 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 - Issue #12483: ctypes: Fix a crash when the destruction of a callback
object triggers the garbage collector. object triggers the garbage collector.
......
...@@ -356,6 +356,59 @@ LL_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v) ...@@ -356,6 +356,59 @@ LL_setitem(arrayobject *ap, Py_ssize_t i, PyObject *v)
return 0; 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 * static PyObject *
f_getitem(arrayobject *ap, Py_ssize_t i) f_getitem(arrayobject *ap, Py_ssize_t i)
{ {
...@@ -406,6 +459,10 @@ static struct arraydescr descriptors[] = { ...@@ -406,6 +459,10 @@ static struct arraydescr descriptors[] = {
{'I', sizeof(int), II_getitem, II_setitem, "I", 1, 0}, {'I', sizeof(int), II_getitem, II_setitem, "I", 1, 0},
{'l', sizeof(long), l_getitem, l_setitem, "l", 1, 1}, {'l', sizeof(long), l_getitem, l_setitem, "l", 1, 1},
{'L', sizeof(long), LL_getitem, LL_setitem, "L", 1, 0}, {'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}, {'f', sizeof(float), f_getitem, f_setitem, "f", 0, 0},
{'d', sizeof(double), d_getitem, d_setitem, "d", 0, 0}, {'d', sizeof(double), d_getitem, d_setitem, "d", 0, 0},
{'\0', 0, 0, 0, 0, 0, 0} /* Sentinel */ {'\0', 0, 0, 0, 0, 0, 0} /* Sentinel */
...@@ -1655,6 +1712,16 @@ typecode_to_mformat_code(int typecode) ...@@ -1655,6 +1712,16 @@ typecode_to_mformat_code(int typecode)
intsize = sizeof(long); intsize = sizeof(long);
is_signed = 0; is_signed = 0;
break; 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: default:
return UNKNOWN_FORMAT; return UNKNOWN_FORMAT;
} }
...@@ -2501,7 +2568,11 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds) ...@@ -2501,7 +2568,11 @@ array_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
} }
} }
PyErr_SetString(PyExc_ValueError, 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)"); "bad typecode (must be b, B, u, h, H, i, I, l, L, f or d)");
#endif
return NULL; return NULL;
} }
...@@ -2524,12 +2595,18 @@ is a single character. The following type codes are defined:\n\ ...@@ -2524,12 +2595,18 @@ is a single character. The following type codes are defined:\n\
'I' unsigned integer 2 \n\ 'I' unsigned integer 2 \n\
'l' signed integer 4 \n\ 'l' signed integer 4 \n\
'L' unsigned 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\ 'f' floating point 4 \n\
'd' floating point 8 \n\ 'd' floating point 8 \n\
\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\ narrow builds this is 2-bytes on wide builds this is 4-bytes.\n\
\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\ The constructor is:\n\
\n\ \n\
array(typecode [, initializer]) -- create a new array\n\ array(typecode [, initializer]) -- create a new array\n\
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment