📄 arraymodule.c
字号:
/* Array object implementation */
/* An array is a uniform list -- all items have the same type.
The item type is restricted to simple C types like int or float */
#include "Python.h"
#ifdef STDC_HEADERS
#include <stddef.h>
#else /* !STDC_HEADERS */
#ifndef DONT_HAVE_SYS_TYPES_H
#include <sys/types.h> /* For size_t */
#endif /* DONT_HAVE_SYS_TYPES_H */
#endif /* !STDC_HEADERS */
struct arrayobject; /* Forward */
/* All possible arraydescr values are defined in the vector "descriptors"
* below. That's defined later because the appropriate get and set
* functions aren't visible yet.
*/
struct arraydescr {
int typecode;
int itemsize;
PyObject * (*getitem)(struct arrayobject *, int);
int (*setitem)(struct arrayobject *, int, PyObject *);
};
typedef struct arrayobject {
PyObject_VAR_HEAD
char *ob_item;
struct arraydescr *ob_descr;
} arrayobject;
staticforward PyTypeObject Arraytype;
#define is_arrayobject(op) ((op)->ob_type == &Arraytype)
/****************************************************************************
Get and Set functions for each type.
A Get function takes an arrayobject* and an integer index, returning the
array value at that index wrapped in an appropriate PyObject*.
A Set function takes an arrayobject, integer index, and PyObject*; sets
the array value at that index to the raw C data extracted from the PyObject*,
and returns 0 if successful, else nonzero on failure (PyObject* not of an
appropriate type or value).
Note that the basic Get and Set functions do NOT check that the index is
in bounds; that's the responsibility of the caller.
****************************************************************************/
static PyObject *
c_getitem(arrayobject *ap, int i)
{
return PyString_FromStringAndSize(&((char *)ap->ob_item)[i], 1);
}
static int
c_setitem(arrayobject *ap, int i, PyObject *v)
{
char x;
if (!PyArg_Parse(v, "c;array item must be char", &x))
return -1;
if (i >= 0)
((char *)ap->ob_item)[i] = x;
return 0;
}
static PyObject *
b_getitem(arrayobject *ap, int i)
{
long x = ((char *)ap->ob_item)[i];
if (x >= 128)
x -= 256;
return PyInt_FromLong(x);
}
static int
b_setitem(arrayobject *ap, int i, PyObject *v)
{
short x;
/* PyArg_Parse's 'b' formatter is for an unsigned char, therefore
must use the next size up that is signed ('h') and manually do
the overflow checking */
if (!PyArg_Parse(v, "h;array item must be integer", &x))
return -1;
else if (x < -128) {
PyErr_SetString(PyExc_OverflowError,
"signed char is less than minimum");
return -1;
}
else if (x > 127) {
PyErr_SetString(PyExc_OverflowError,
"signed char is greater than maximum");
return -1;
}
if (i >= 0)
((char *)ap->ob_item)[i] = (char)x;
return 0;
}
static PyObject *
BB_getitem(arrayobject *ap, int i)
{
long x = ((unsigned char *)ap->ob_item)[i];
return PyInt_FromLong(x);
}
static int
BB_setitem(arrayobject *ap, int i, PyObject *v)
{
unsigned char x;
/* 'B' == unsigned char, maps to PyArg_Parse's 'b' formatter */
if (!PyArg_Parse(v, "b;array item must be integer", &x))
return -1;
if (i >= 0)
((char *)ap->ob_item)[i] = x;
return 0;
}
static PyObject *
h_getitem(arrayobject *ap, int i)
{
return PyInt_FromLong((long) ((short *)ap->ob_item)[i]);
}
static int
h_setitem(arrayobject *ap, int i, PyObject *v)
{
short x;
/* 'h' == signed short, maps to PyArg_Parse's 'h' formatter */
if (!PyArg_Parse(v, "h;array item must be integer", &x))
return -1;
if (i >= 0)
((short *)ap->ob_item)[i] = x;
return 0;
}
static PyObject *
HH_getitem(arrayobject *ap, int i)
{
return PyInt_FromLong((long) ((unsigned short *)ap->ob_item)[i]);
}
static int
HH_setitem(arrayobject *ap, int i, PyObject *v)
{
int x;
/* PyArg_Parse's 'h' formatter is for a signed short, therefore
must use the next size up and manually do the overflow checking */
if (!PyArg_Parse(v, "i;array item must be integer", &x))
return -1;
else if (x < 0) {
PyErr_SetString(PyExc_OverflowError,
"unsigned short is less than minimum");
return -1;
}
else if (x > USHRT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"unsigned short is greater than maximum");
return -1;
}
if (i >= 0)
((short *)ap->ob_item)[i] = (short)x;
return 0;
}
static PyObject *
i_getitem(arrayobject *ap, int i)
{
return PyInt_FromLong((long) ((int *)ap->ob_item)[i]);
}
static int
i_setitem(arrayobject *ap, int i, PyObject *v)
{
int x;
/* 'i' == signed int, maps to PyArg_Parse's 'i' formatter */
if (!PyArg_Parse(v, "i;array item must be integer", &x))
return -1;
if (i >= 0)
((int *)ap->ob_item)[i] = x;
return 0;
}
static PyObject *
II_getitem(arrayobject *ap, int i)
{
return PyLong_FromUnsignedLong(
(unsigned long) ((unsigned int *)ap->ob_item)[i]);
}
static int
II_setitem(arrayobject *ap, int i, PyObject *v)
{
unsigned long x;
if (PyLong_Check(v)) {
x = PyLong_AsUnsignedLong(v);
if (x == (unsigned long) -1 && PyErr_Occurred())
return -1;
}
else {
long y;
if (!PyArg_Parse(v, "l;array item must be integer", &y))
return -1;
if (y < 0) {
PyErr_SetString(PyExc_OverflowError,
"unsigned int is less than minimum");
return -1;
}
x = (unsigned long)y;
}
if (x > UINT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"unsigned int is greater than maximum");
return -1;
}
if (i >= 0)
((unsigned int *)ap->ob_item)[i] = (unsigned int)x;
return 0;
}
static PyObject *
l_getitem(arrayobject *ap, int i)
{
return PyInt_FromLong(((long *)ap->ob_item)[i]);
}
static int
l_setitem(arrayobject *ap, int i, PyObject *v)
{
long x;
if (!PyArg_Parse(v, "l;array item must be integer", &x))
return -1;
if (i >= 0)
((long *)ap->ob_item)[i] = x;
return 0;
}
static PyObject *
LL_getitem(arrayobject *ap, int i)
{
return PyLong_FromUnsignedLong(((unsigned long *)ap->ob_item)[i]);
}
static int
LL_setitem(arrayobject *ap, int i, PyObject *v)
{
unsigned long x;
if (PyLong_Check(v)) {
x = PyLong_AsUnsignedLong(v);
if (x == (unsigned long) -1 && PyErr_Occurred())
return -1;
}
else {
long y;
if (!PyArg_Parse(v, "l;array item must be integer", &y))
return -1;
if (y < 0) {
PyErr_SetString(PyExc_OverflowError,
"unsigned long is less than minimum");
return -1;
}
x = (unsigned long)y;
}
if (x > ULONG_MAX) {
PyErr_SetString(PyExc_OverflowError,
"unsigned long is greater than maximum");
return -1;
}
if (i >= 0)
((unsigned long *)ap->ob_item)[i] = x;
return 0;
}
static PyObject *
f_getitem(arrayobject *ap, int i)
{
return PyFloat_FromDouble((double) ((float *)ap->ob_item)[i]);
}
static int
f_setitem(arrayobject *ap, int i, PyObject *v)
{
float x;
if (!PyArg_Parse(v, "f;array item must be float", &x))
return -1;
if (i >= 0)
((float *)ap->ob_item)[i] = x;
return 0;
}
static PyObject *
d_getitem(arrayobject *ap, int i)
{
return PyFloat_FromDouble(((double *)ap->ob_item)[i]);
}
static int
d_setitem(arrayobject *ap, int i, PyObject *v)
{
double x;
if (!PyArg_Parse(v, "d;array item must be float", &x))
return -1;
if (i >= 0)
((double *)ap->ob_item)[i] = x;
return 0;
}
/* Description of types */
static struct arraydescr descriptors[] = {
{'c', sizeof(char), c_getitem, c_setitem},
{'b', sizeof(char), b_getitem, b_setitem},
{'B', sizeof(char), BB_getitem, BB_setitem},
{'h', sizeof(short), h_getitem, h_setitem},
{'H', sizeof(short), HH_getitem, HH_setitem},
{'i', sizeof(int), i_getitem, i_setitem},
{'I', sizeof(int), II_getitem, II_setitem},
{'l', sizeof(long), l_getitem, l_setitem},
{'L', sizeof(long), LL_getitem, LL_setitem},
{'f', sizeof(float), f_getitem, f_setitem},
{'d', sizeof(double), d_getitem, d_setitem},
{'\0', 0, 0, 0} /* Sentinel */
};
/****************************************************************************
Implementations of array object methods.
****************************************************************************/
static PyObject *
newarrayobject(int size, struct arraydescr *descr)
{
arrayobject *op;
size_t nbytes;
if (size < 0) {
PyErr_BadInternalCall();
return NULL;
}
nbytes = size * descr->itemsize;
/* Check for overflow */
if (nbytes / descr->itemsize != (size_t)size) {
return PyErr_NoMemory();
}
op = PyObject_NewVar(arrayobject, &Arraytype, size);
if (op == NULL) {
return PyErr_NoMemory();
}
if (size <= 0) {
op->ob_item = NULL;
}
else {
op->ob_item = PyMem_NEW(char, nbytes);
if (op->ob_item == NULL) {
PyObject_Del(op);
return PyErr_NoMemory();
}
}
op->ob_descr = descr;
return (PyObject *) op;
}
static PyObject *
getarrayitem(PyObject *op, int i)
{
register arrayobject *ap;
assert(is_arrayobject(op));
ap = (arrayobject *)op;
if (i < 0 || i >= ap->ob_size) {
PyErr_SetString(PyExc_IndexError, "array index out of range");
return NULL;
}
return (*ap->ob_descr->getitem)(ap, i);
}
static int
ins1(arrayobject *self, int where, PyObject *v)
{
char *items;
if (v == NULL) {
PyErr_BadInternalCall();
return -1;
}
if ((*self->ob_descr->setitem)(self, -1, v) < 0)
return -1;
items = self->ob_item;
PyMem_RESIZE(items, char,
(self->ob_size+1) * self->ob_descr->itemsize);
if (items == NULL) {
PyErr_NoMemory();
return -1;
}
if (where < 0)
where = 0;
if (where > self->ob_size)
where = self->ob_size;
memmove(items + (where+1)*self->ob_descr->itemsize,
items + where*self->ob_descr->itemsize,
(self->ob_size-where)*self->ob_descr->itemsize);
self->ob_item = items;
self->ob_size++;
return (*self->ob_descr->setitem)(self, where, v);
}
/* Methods */
static void
array_dealloc(arrayobject *op)
{
if (op->ob_item != NULL)
PyMem_DEL(op->ob_item);
PyObject_Del(op);
}
static PyObject *
array_richcompare(PyObject *v, PyObject *w, int op)
{
arrayobject *va, *wa;
PyObject *vi = NULL;
PyObject *wi = NULL;
int i, k;
PyObject *res;
if (!is_arrayobject(v) || !is_arrayobject(w)) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}
va = (arrayobject *)v;
wa = (arrayobject *)w;
if (va->ob_size != wa->ob_size && (op == Py_EQ || op == Py_NE)) {
/* Shortcut: if the lengths differ, the arrays differ */
if (op == Py_EQ)
res = Py_False;
else
res = Py_True;
Py_INCREF(res);
return res;
}
/* Search for the first index where items are different */
k = 1;
for (i = 0; i < va->ob_size && i < wa->ob_size; i++) {
vi = getarrayitem(v, i);
wi = getarrayitem(w, i);
if (vi == NULL || wi == NULL) {
Py_XDECREF(vi);
Py_XDECREF(wi);
return NULL;
}
k = PyObject_RichCompareBool(vi, wi, Py_EQ);
if (k == 0)
break; /* Keeping vi and wi alive! */
Py_DECREF(vi);
Py_DECREF(wi);
if (k < 0)
return NULL;
}
if (k) {
/* No more items to compare -- compare sizes */
int vs = va->ob_size;
int ws = wa->ob_size;
int cmp;
switch (op) {
case Py_LT: cmp = vs < ws; break;
case Py_LE: cmp = vs <= ws; break;
case Py_EQ: cmp = vs == ws; break;
case Py_NE: cmp = vs != ws; break;
case Py_GT: cmp = vs > ws; break;
case Py_GE: cmp = vs >= ws; break;
default: return NULL; /* cannot happen */
}
if (cmp)
res = Py_True;
else
res = Py_False;
Py_INCREF(res);
return res;
}
/* We have an item that differs. First, shortcuts for EQ/NE */
if (op == Py_EQ) {
Py_INCREF(Py_False);
res = Py_False;
}
else if (op == Py_NE) {
Py_INCREF(Py_True);
res = Py_True;
}
else {
/* Compare the final item again using the proper operator */
res = PyObject_RichCompare(vi, wi, op);
}
Py_DECREF(vi);
Py_DECREF(wi);
return res;
}
static int
array_length(arrayobject *a)
{
return a->ob_size;
}
static PyObject *
array_item(arrayobject *a, int i)
{
if (i < 0 || i >= a->ob_size) {
PyErr_SetString(PyExc_IndexError, "array index out of range");
return NULL;
}
return getarrayitem((PyObject *)a, i);
}
static PyObject *
array_slice(arrayobject *a, int ilow, int ihigh)
{
arrayobject *np;
if (ilow < 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -