2381 lines · 51.7 KB · C
RawDownload
/* Abstract Object Interface (many thanks to Jim Fulton) */ #include "Python.h"#include <ctype.h>#include "structmember.h" /* we need the offsetof() macro from there */#include "longintrepr.h" #define NEW_STYLE_NUMBER(o) PyType_HasFeature((o)->ob_type, \				Py_TPFLAGS_CHECKTYPES)  /* Shorthands to return certain errors */ static PyObject *type_error(const char *msg, PyObject *obj){	PyErr_Format(PyExc_TypeError, msg, obj->ob_type->tp_name);	return NULL;} static PyObject *null_error(void){	if (!PyErr_Occurred())		PyErr_SetString(PyExc_SystemError,				"null argument to internal routine");	return NULL;} /* Operations on any object */ intPyObject_Cmp(PyObject *o1, PyObject *o2, int *result){	int r; 	if (o1 == NULL || o2 == NULL) {		null_error();		return -1;	}	r = PyObject_Compare(o1, o2);	if (PyErr_Occurred())		return -1;	*result = r;	return 0;} PyObject *PyObject_Type(PyObject *o){	PyObject *v; 	if (o == NULL)		return null_error();	v = (PyObject *)o->ob_type;	Py_INCREF(v);	return v;} Py_ssize_tPyObject_Size(PyObject *o){	PySequenceMethods *m; 	if (o == NULL) {		null_error();		return -1;	} 	m = o->ob_type->tp_as_sequence;	if (m && m->sq_length)		return m->sq_length(o); 	return PyMapping_Size(o);} #undef PyObject_LengthPy_ssize_tPyObject_Length(PyObject *o){	return PyObject_Size(o);}#define PyObject_Length PyObject_Size Py_ssize_t_PyObject_LengthHint(PyObject *o){	Py_ssize_t rv = PyObject_Size(o);	if (rv != -1)		return rv;	if (PyErr_ExceptionMatches(PyExc_TypeError) ||	    PyErr_ExceptionMatches(PyExc_AttributeError)) {		PyObject *err_type, *err_value, *err_tb, *ro; 		PyErr_Fetch(&err_type, &err_value, &err_tb);		ro = PyObject_CallMethod(o, "__length_hint__", NULL);		if (ro != NULL) {			rv = PyInt_AsLong(ro);			Py_DECREF(ro);			Py_XDECREF(err_type);			Py_XDECREF(err_value);			Py_XDECREF(err_tb);			return rv;		}		PyErr_Restore(err_type, err_value, err_tb);	}	return -1;} PyObject *PyObject_GetItem(PyObject *o, PyObject *key){	PyMappingMethods *m; 	if (o == NULL || key == NULL)		return null_error(); 	m = o->ob_type->tp_as_mapping;	if (m && m->mp_subscript)		return m->mp_subscript(o, key); 	if (o->ob_type->tp_as_sequence) {		if (PyIndex_Check(key)) {			Py_ssize_t key_value;			key_value = PyNumber_AsSsize_t(key, PyExc_IndexError);			if (key_value == -1 && PyErr_Occurred())				return NULL;			return PySequence_GetItem(o, key_value);		}		else if (o->ob_type->tp_as_sequence->sq_item)			return type_error("sequence index must "					  "be integer, not '%.200s'", key);	} 	return type_error("'%.200s' object is unsubscriptable", o);} intPyObject_SetItem(PyObject *o, PyObject *key, PyObject *value){	PyMappingMethods *m; 	if (o == NULL || key == NULL || value == NULL) {		null_error();		return -1;	}	m = o->ob_type->tp_as_mapping;	if (m && m->mp_ass_subscript)		return m->mp_ass_subscript(o, key, value); 	if (o->ob_type->tp_as_sequence) {		if (PyIndex_Check(key)) {			Py_ssize_t key_value;			key_value = PyNumber_AsSsize_t(key, PyExc_IndexError);			if (key_value == -1 && PyErr_Occurred())				return -1;			return PySequence_SetItem(o, key_value, value);		}		else if (o->ob_type->tp_as_sequence->sq_ass_item) {			type_error("sequence index must be "				   "integer, not '%.200s'", key);			return -1;		}	} 	type_error("'%.200s' object does not support item assignment", o);	return -1;} intPyObject_DelItem(PyObject *o, PyObject *key){	PyMappingMethods *m; 	if (o == NULL || key == NULL) {		null_error();		return -1;	}	m = o->ob_type->tp_as_mapping;	if (m && m->mp_ass_subscript)		return m->mp_ass_subscript(o, key, (PyObject*)NULL); 	if (o->ob_type->tp_as_sequence) {		if (PyIndex_Check(key)) {			Py_ssize_t key_value;			key_value = PyNumber_AsSsize_t(key, PyExc_IndexError);			if (key_value == -1 && PyErr_Occurred())				return -1;			return PySequence_DelItem(o, key_value);		}		else if (o->ob_type->tp_as_sequence->sq_ass_item) {			type_error("sequence index must be "				   "integer, not '%.200s'", key);			return -1;		}	} 	type_error("'%.200s' object does not support item deletion", o);	return -1;} intPyObject_DelItemString(PyObject *o, char *key){	PyObject *okey;	int ret; 	if (o == NULL || key == NULL) {		null_error();		return -1;	}	okey = PyString_FromString(key);	if (okey == NULL)		return -1;	ret = PyObject_DelItem(o, okey);	Py_DECREF(okey);	return ret;} intPyObject_AsCharBuffer(PyObject *obj,			  const char **buffer,			  Py_ssize_t *buffer_len){	PyBufferProcs *pb;	char *pp;	Py_ssize_t len; 	if (obj == NULL || buffer == NULL || buffer_len == NULL) {		null_error();		return -1;	}	pb = obj->ob_type->tp_as_buffer;	if (pb == NULL ||	     pb->bf_getcharbuffer == NULL ||	     pb->bf_getsegcount == NULL) {		PyErr_SetString(PyExc_TypeError,				"expected a character buffer object");		return -1;	}	if ((*pb->bf_getsegcount)(obj,NULL) != 1) {		PyErr_SetString(PyExc_TypeError,				"expected a single-segment buffer object");		return -1;	}	len = (*pb->bf_getcharbuffer)(obj, 0, &pp);	if (len < 0)		return -1;	*buffer = pp;	*buffer_len = len;	return 0;} intPyObject_CheckReadBuffer(PyObject *obj){	PyBufferProcs *pb = obj->ob_type->tp_as_buffer; 	if (pb == NULL ||	    pb->bf_getreadbuffer == NULL ||	    pb->bf_getsegcount == NULL ||	    (*pb->bf_getsegcount)(obj, NULL) != 1)		return 0;	return 1;} int PyObject_AsReadBuffer(PyObject *obj,			  const void **buffer,			  Py_ssize_t *buffer_len){	PyBufferProcs *pb;	void *pp;	Py_ssize_t len; 	if (obj == NULL || buffer == NULL || buffer_len == NULL) {		null_error();		return -1;	}	pb = obj->ob_type->tp_as_buffer;	if (pb == NULL ||	     pb->bf_getreadbuffer == NULL ||	     pb->bf_getsegcount == NULL) {		PyErr_SetString(PyExc_TypeError,				"expected a readable buffer object");		return -1;	}	if ((*pb->bf_getsegcount)(obj, NULL) != 1) {		PyErr_SetString(PyExc_TypeError,				"expected a single-segment buffer object");		return -1;	}	len = (*pb->bf_getreadbuffer)(obj, 0, &pp);	if (len < 0)		return -1;	*buffer = pp;	*buffer_len = len;	return 0;} int PyObject_AsWriteBuffer(PyObject *obj,			   void **buffer,			   Py_ssize_t *buffer_len){	PyBufferProcs *pb;	void*pp;	Py_ssize_t len; 	if (obj == NULL || buffer == NULL || buffer_len == NULL) {		null_error();		return -1;	}	pb = obj->ob_type->tp_as_buffer;	if (pb == NULL ||	     pb->bf_getwritebuffer == NULL ||	     pb->bf_getsegcount == NULL) {		PyErr_SetString(PyExc_TypeError,				"expected a writeable buffer object");		return -1;	}	if ((*pb->bf_getsegcount)(obj, NULL) != 1) {		PyErr_SetString(PyExc_TypeError,				"expected a single-segment buffer object");		return -1;	}	len = (*pb->bf_getwritebuffer)(obj,0,&pp);	if (len < 0)		return -1;	*buffer = pp;	*buffer_len = len;	return 0;} /* Operations on numbers */ intPyNumber_Check(PyObject *o){	return o && o->ob_type->tp_as_number &&	       (o->ob_type->tp_as_number->nb_int ||		o->ob_type->tp_as_number->nb_float);} /* Binary operators */ /* New style number protocol support */ #define NB_SLOT(x) offsetof(PyNumberMethods, x)#define NB_BINOP(nb_methods, slot) \		(*(binaryfunc*)(& ((char*)nb_methods)[slot]))#define NB_TERNOP(nb_methods, slot) \		(*(ternaryfunc*)(& ((char*)nb_methods)[slot])) /*  Calling scheme used for binary operations:   v	w	Action  -------------------------------------------------------------------  new	new	w.op(v,w)[*], v.op(v,w), w.op(v,w)  new	old	v.op(v,w), coerce(v,w), v.op(v,w)  old	new	w.op(v,w), coerce(v,w), v.op(v,w)  old	old	coerce(v,w), v.op(v,w)   [*] only when v->ob_type != w->ob_type && w->ob_type is a subclass of      v->ob_type   Legend:  -------  * new == new style number  * old == old style number  * Action indicates the order in which operations are tried until either    a valid result is produced or an error occurs.  */ static PyObject *binary_op1(PyObject *v, PyObject *w, const int op_slot){	PyObject *x;	binaryfunc slotv = NULL;	binaryfunc slotw = NULL; 	if (v->ob_type->tp_as_number != NULL && NEW_STYLE_NUMBER(v))		slotv = NB_BINOP(v->ob_type->tp_as_number, op_slot);	if (w->ob_type != v->ob_type &&	    w->ob_type->tp_as_number != NULL && NEW_STYLE_NUMBER(w)) {		slotw = NB_BINOP(w->ob_type->tp_as_number, op_slot);		if (slotw == slotv)			slotw = NULL;	}	if (slotv) {		if (slotw && PyType_IsSubtype(w->ob_type, v->ob_type)) {			x = slotw(v, w);			if (x != Py_NotImplemented)				return x;			Py_DECREF(x); /* can't do it */			slotw = NULL;		}		x = slotv(v, w);		if (x != Py_NotImplemented)			return x;		Py_DECREF(x); /* can't do it */	}	if (slotw) {		x = slotw(v, w);		if (x != Py_NotImplemented)			return x;		Py_DECREF(x); /* can't do it */	}	if (!NEW_STYLE_NUMBER(v) || !NEW_STYLE_NUMBER(w)) {		int err = PyNumber_CoerceEx(&v, &w);		if (err < 0) {			return NULL;		}		if (err == 0) {			PyNumberMethods *mv = v->ob_type->tp_as_number;			if (mv) {				binaryfunc slot;				slot = NB_BINOP(mv, op_slot);				if (slot) {					x = slot(v, w);					Py_DECREF(v);					Py_DECREF(w);					return x;				}			}			/* CoerceEx incremented the reference counts */			Py_DECREF(v);			Py_DECREF(w);		}	}	Py_INCREF(Py_NotImplemented);	return Py_NotImplemented;} static PyObject *binop_type_error(PyObject *v, PyObject *w, const char *op_name){	PyErr_Format(PyExc_TypeError,		     "unsupported operand type(s) for %.100s: "		     "'%.100s' and '%.100s'",		     op_name,		     v->ob_type->tp_name,		     w->ob_type->tp_name);	return NULL;} static PyObject *binary_op(PyObject *v, PyObject *w, const int op_slot, const char *op_name){	PyObject *result = binary_op1(v, w, op_slot);	if (result == Py_NotImplemented) {		Py_DECREF(result);		return binop_type_error(v, w, op_name);	}	return result;}  /*  Calling scheme used for ternary operations:   *** In some cases, w.op is called before v.op; see binary_op1. ***   v	w	z	Action  -------------------------------------------------------------------  new	new	new	v.op(v,w,z), w.op(v,w,z), z.op(v,w,z)  new	old	new	v.op(v,w,z), z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)  old	new	new	w.op(v,w,z), z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)  old	old	new	z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)  new	new	old	v.op(v,w,z), w.op(v,w,z), coerce(v,w,z), v.op(v,w,z)  new	old	old	v.op(v,w,z), coerce(v,w,z), v.op(v,w,z)  old	new	old	w.op(v,w,z), coerce(v,w,z), v.op(v,w,z)  old	old	old	coerce(v,w,z), v.op(v,w,z)   Legend:  -------  * new == new style number  * old == old style number  * Action indicates the order in which operations are tried until either    a valid result is produced or an error occurs.  * coerce(v,w,z) actually does: coerce(v,w), coerce(v,z), coerce(w,z) and    only if z != Py_None; if z == Py_None, then it is treated as absent    variable and only coerce(v,w) is tried.  */ static PyObject *ternary_op(PyObject *v,	   PyObject *w,	   PyObject *z,	   const int op_slot,	   const char *op_name){	PyNumberMethods *mv, *mw, *mz;	PyObject *x = NULL;	ternaryfunc slotv = NULL;	ternaryfunc slotw = NULL;	ternaryfunc slotz = NULL; 	mv = v->ob_type->tp_as_number;

Lines 1–500 of 2381.