/* 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; elseLines 1–500 of 890. Load more
/* 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_ALLOCS int 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_t PyTuple_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]; } int PyTuple_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 void tupledealloc(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 int tupleprint(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 long tuplehash(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_t tuplelength(PyTupleObject *a) { return a->ob_size; } static int tuplecontains(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 int tupletraverse(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