cinap_lenrekadd hg and python4bb9e2215 years agoHistory
890 lines · 19.7 KB · C
RawDownload
 /* Tuple object implementation */ #include "Python.h" /* Speed optimization to avoid frequent malloc/free of small tuples */#ifndef MAXSAVESIZE#define MAXSAVESIZE	20  /* Largest tuple to save on free list */#endif#ifndef MAXSAVEDTUPLES #define MAXSAVEDTUPLES  2000  /* Maximum number of tuples of each size to save */#endif #if MAXSAVESIZE > 0/* Entries 1 up to MAXSAVESIZE are free lists, entry 0 is the empty   tuple () of which at most one instance will be allocated.*/static PyTupleObject *free_tuples[MAXSAVESIZE];static int num_free_tuples[MAXSAVESIZE];#endif#ifdef COUNT_ALLOCSint fast_tuple_allocs;int tuple_zero_allocs;#endif PyObject *PyTuple_New(register Py_ssize_t size){	register PyTupleObject *op;	Py_ssize_t i;	if (size < 0) {		PyErr_BadInternalCall();		return NULL;	}#if MAXSAVESIZE > 0	if (size == 0 && free_tuples[0]) {		op = free_tuples[0];		Py_INCREF(op);#ifdef COUNT_ALLOCS		tuple_zero_allocs++;#endif		return (PyObject *) op;	}	if (size < MAXSAVESIZE && (op = free_tuples[size]) != NULL) {		free_tuples[size] = (PyTupleObject *) op->ob_item[0];		num_free_tuples[size]--;#ifdef COUNT_ALLOCS		fast_tuple_allocs++;#endif		/* Inline PyObject_InitVar */#ifdef Py_TRACE_REFS		op->ob_size = size;		op->ob_type = &PyTuple_Type;#endif		_Py_NewReference((PyObject *)op);	}	else#endif	{		Py_ssize_t nbytes = size * sizeof(PyObject *);		/* Check for overflow */		if (nbytes / sizeof(PyObject *) != (size_t)size ||		    (nbytes += sizeof(PyTupleObject) - sizeof(PyObject *))		    <= 0)		{			return PyErr_NoMemory();		}		op = PyObject_GC_NewVar(PyTupleObject, &PyTuple_Type, size);		if (op == NULL)			return NULL;	}	for (i=0; i < size; i++)		op->ob_item[i] = NULL;#if MAXSAVESIZE > 0	if (size == 0) {		free_tuples[0] = op;		++num_free_tuples[0];		Py_INCREF(op);	/* extra INCREF so that this is never freed */	}#endif	_PyObject_GC_TRACK(op);	return (PyObject *) op;} Py_ssize_tPyTuple_Size(register PyObject *op){	if (!PyTuple_Check(op)) {		PyErr_BadInternalCall();		return -1;	}	else		return ((PyTupleObject *)op)->ob_size;} PyObject *PyTuple_GetItem(register PyObject *op, register Py_ssize_t i){	if (!PyTuple_Check(op)) {		PyErr_BadInternalCall();		return NULL;	}	if (i < 0 || i >= ((PyTupleObject *)op) -> ob_size) {		PyErr_SetString(PyExc_IndexError, "tuple index out of range");		return NULL;	}	return ((PyTupleObject *)op) -> ob_item[i];} intPyTuple_SetItem(register PyObject *op, register Py_ssize_t i, PyObject *newitem){	register PyObject *olditem;	register PyObject **p;	if (!PyTuple_Check(op) || op->ob_refcnt != 1) {		Py_XDECREF(newitem);		PyErr_BadInternalCall();		return -1;	}	if (i < 0 || i >= ((PyTupleObject *)op) -> ob_size) {		Py_XDECREF(newitem);		PyErr_SetString(PyExc_IndexError,				"tuple assignment index out of range");		return -1;	}	p = ((PyTupleObject *)op) -> ob_item + i;	olditem = *p;	*p = newitem;	Py_XDECREF(olditem);	return 0;} PyObject *PyTuple_Pack(Py_ssize_t n, ...){	Py_ssize_t i;	PyObject *o;	PyObject *result;	PyObject **items;	va_list vargs; 	va_start(vargs, n);	result = PyTuple_New(n);	if (result == NULL)		return NULL;	items = ((PyTupleObject *)result)->ob_item;	for (i = 0; i < n; i++) {		o = va_arg(vargs, PyObject *);		Py_INCREF(o);		items[i] = o;	}	va_end(vargs);	return result;}  /* Methods */ static voidtupledealloc(register PyTupleObject *op){	register Py_ssize_t i;	register Py_ssize_t len =  op->ob_size;	PyObject_GC_UnTrack(op);	Py_TRASHCAN_SAFE_BEGIN(op)	if (len > 0) {		i = len;		while (--i >= 0)			Py_XDECREF(op->ob_item[i]);#if MAXSAVESIZE > 0		if (len < MAXSAVESIZE &&		    num_free_tuples[len] < MAXSAVEDTUPLES &&		    op->ob_type == &PyTuple_Type)		{			op->ob_item[0] = (PyObject *) free_tuples[len];			num_free_tuples[len]++;			free_tuples[len] = op;			goto done; /* return */		}#endif	}	op->ob_type->tp_free((PyObject *)op);done:	Py_TRASHCAN_SAFE_END(op)} static inttupleprint(PyTupleObject *op, FILE *fp, int flags){	Py_ssize_t i;	fprintf(fp, "(");	for (i = 0; i < op->ob_size; i++) {		if (i > 0)			fprintf(fp, ", ");		if (PyObject_Print(op->ob_item[i], fp, 0) != 0)			return -1;	}	if (op->ob_size == 1)		fprintf(fp, ",");	fprintf(fp, ")");	return 0;} static PyObject *tuplerepr(PyTupleObject *v){	Py_ssize_t i, n;	PyObject *s, *temp;	PyObject *pieces, *result = NULL; 	n = v->ob_size;	if (n == 0)		return PyString_FromString("()"); 	pieces = PyTuple_New(n);	if (pieces == NULL)		return NULL; 	/* Do repr() on each element. */	for (i = 0; i < n; ++i) {		s = PyObject_Repr(v->ob_item[i]);		if (s == NULL)			goto Done;		PyTuple_SET_ITEM(pieces, i, s);	} 	/* Add "()" decorations to the first and last items. */	assert(n > 0);	s = PyString_FromString("(");	if (s == NULL)		goto Done;	temp = PyTuple_GET_ITEM(pieces, 0);	PyString_ConcatAndDel(&s, temp);	PyTuple_SET_ITEM(pieces, 0, s);	if (s == NULL)		goto Done; 	s = PyString_FromString(n == 1 ? ",)" : ")");	if (s == NULL)		goto Done;	temp = PyTuple_GET_ITEM(pieces, n-1);	PyString_ConcatAndDel(&temp, s);	PyTuple_SET_ITEM(pieces, n-1, temp);	if (temp == NULL)		goto Done; 	/* Paste them all together with ", " between. */	s = PyString_FromString(", ");	if (s == NULL)		goto Done;	result = _PyString_Join(s, pieces);	Py_DECREF(s);	 Done:	Py_DECREF(pieces);	return result;} /* The addend 82520, was selected from the range(0, 1000000) for    generating the greatest number of prime multipliers for tuples    upto length eight:      1082527, 1165049, 1082531, 1165057, 1247581, 1330103, 1082533,      1330111, 1412633, 1165069, 1247599, 1495177, 1577699*/ static longtuplehash(PyTupleObject *v){	register long x, y;	register Py_ssize_t len = v->ob_size;	register PyObject **p;	long mult = 1000003L;	x = 0x345678L;	p = v->ob_item;	while (--len >= 0) {		y = PyObject_Hash(*p++);		if (y == -1)			return -1;		x = (x ^ y) * mult;		/* the cast might truncate len; that doesn't change hash stability */		mult += (long)(82520L + len + len);	}	x += 97531L;	if (x == -1)		x = -2;	return x;} static Py_ssize_ttuplelength(PyTupleObject *a){	return a->ob_size;} static inttuplecontains(PyTupleObject *a, PyObject *el){	Py_ssize_t i;	int cmp; 	for (i = 0, cmp = 0 ; cmp == 0 && i < a->ob_size; ++i)		cmp = PyObject_RichCompareBool(el, PyTuple_GET_ITEM(a, i),						   Py_EQ);	return cmp;} static PyObject *tupleitem(register PyTupleObject *a, register Py_ssize_t i){	if (i < 0 || i >= a->ob_size) {		PyErr_SetString(PyExc_IndexError, "tuple index out of range");		return NULL;	}	Py_INCREF(a->ob_item[i]);	return a->ob_item[i];} static PyObject *tupleslice(register PyTupleObject *a, register Py_ssize_t ilow, 	   register Py_ssize_t ihigh){	register PyTupleObject *np;	PyObject **src, **dest;	register Py_ssize_t i;	Py_ssize_t len;	if (ilow < 0)		ilow = 0;	if (ihigh > a->ob_size)		ihigh = a->ob_size;	if (ihigh < ilow)		ihigh = ilow;	if (ilow == 0 && ihigh == a->ob_size && PyTuple_CheckExact(a)) {		Py_INCREF(a);		return (PyObject *)a;	}	len = ihigh - ilow;	np = (PyTupleObject *)PyTuple_New(len);	if (np == NULL)		return NULL;	src = a->ob_item + ilow;	dest = np->ob_item;	for (i = 0; i < len; i++) {		PyObject *v = src[i];		Py_INCREF(v);		dest[i] = v;	}	return (PyObject *)np;} PyObject *PyTuple_GetSlice(PyObject *op, Py_ssize_t i, Py_ssize_t j){	if (op == NULL || !PyTuple_Check(op)) {		PyErr_BadInternalCall();		return NULL;	}	return tupleslice((PyTupleObject *)op, i, j);} static PyObject *tupleconcat(register PyTupleObject *a, register PyObject *bb){	register Py_ssize_t size;	register Py_ssize_t i;	PyObject **src, **dest;	PyTupleObject *np;	if (!PyTuple_Check(bb)) {		PyErr_Format(PyExc_TypeError,       		     "can only concatenate tuple (not \"%.200s\") to tuple",			     bb->ob_type->tp_name);		return NULL;	}#define b ((PyTupleObject *)bb)	size = a->ob_size + b->ob_size;	if (size < 0)		return PyErr_NoMemory();	np = (PyTupleObject *) PyTuple_New(size);	if (np == NULL) {		return NULL;	}	src = a->ob_item;	dest = np->ob_item;	for (i = 0; i < a->ob_size; i++) {		PyObject *v = src[i];		Py_INCREF(v);		dest[i] = v;	}	src = b->ob_item;	dest = np->ob_item + a->ob_size;	for (i = 0; i < b->ob_size; i++) {		PyObject *v = src[i];		Py_INCREF(v);		dest[i] = v;	}	return (PyObject *)np;#undef b} static PyObject *tuplerepeat(PyTupleObject *a, Py_ssize_t n){	Py_ssize_t i, j;	Py_ssize_t size;	PyTupleObject *np;	PyObject **p, **items;	if (n < 0)		n = 0;	if (a->ob_size == 0 || n == 1) {		if (PyTuple_CheckExact(a)) {			/* Since tuples are immutable, we can return a shared			   copy in this case */			Py_INCREF(a);			return (PyObject *)a;		}		if (a->ob_size == 0)			return PyTuple_New(0);	}	size = a->ob_size * n;	if (size/a->ob_size != n)		return PyErr_NoMemory();	np = (PyTupleObject *) PyTuple_New(size);	if (np == NULL)		return NULL;	p = np->ob_item;	items = a->ob_item;	for (i = 0; i < n; i++) {		for (j = 0; j < a->ob_size; j++) {			*p = items[j];			Py_INCREF(*p);			p++;		}	}	return (PyObject *) np;} static inttupletraverse(PyTupleObject *o, visitproc visit, void *arg){	Py_ssize_t i; 	for (i = o->ob_size; --i >= 0; )		Py_VISIT(o->ob_item[i]);	return 0;} static PyObject *tuplerichcompare(PyObject *v, PyObject *w, int op){	PyTupleObject *vt, *wt;	Py_ssize_t i;	Py_ssize_t vlen, wlen; 	if (!PyTuple_Check(v) || !PyTuple_Check(w)) {		Py_INCREF(Py_NotImplemented);		return Py_NotImplemented;	} 	vt = (PyTupleObject *)v;	wt = (PyTupleObject *)w; 	vlen = vt->ob_size;	wlen = wt->ob_size; 	/* Note:  the corresponding code for lists has an "early out" test	 * here when op is EQ or NE and the lengths differ.  That pays there,	 * but Tim was unable to find any real code where EQ/NE tuple	 * compares don't have the same length, so testing for it here would	 * have cost without benefit.	 */ 	/* Search for the first index where items are different.	 * Note that because tuples are immutable, it's safe to reuse	 * vlen and wlen across the comparison calls.	 */	for (i = 0; i < vlen && i < wlen; i++) {		int k = PyObject_RichCompareBool(vt->ob_item[i],						 wt->ob_item[i], Py_EQ);		if (k < 0)			return NULL;		if (!k)			break;	} 	if (i >= vlen || i >= wlen) {		/* No more items to compare -- compare sizes */		int cmp;		PyObject *res;		switch (op) {		case Py_LT: cmp = vlen <  wlen; break;		case Py_LE: cmp = vlen <= wlen; break;		case Py_EQ: cmp = vlen == wlen; break;		case Py_NE: cmp = vlen != wlen; break;		case Py_GT: cmp = vlen >  wlen; break;		case Py_GE: cmp = vlen >= wlen; break;		default: return NULL; /* cannot happen */		}		if (cmp)			res = Py_True;		else

Lines 1–500 of 890.