0 /* @tp_is_gc@ */
};
+/*----- Mapping views -----------------------------------------------------*/
+
+#ifdef PY3
+
+static PyTypeObject *keyview_pytype, *itemview_pytype, *valview_pytype;
+
+typedef struct view_pyobj {
+ PyObject_HEAD
+ PyObject *map;
+} view_pyobj;
+#define VIEW_MAP(o) (((view_pyobj *)(o))->map)
+
+static PyObject *gmap_mkview(PyObject *me, PyTypeObject *ty)
+{
+ view_pyobj *v = PyObject_NEW(view_pyobj, ty);
+ v->map = me; Py_INCREF(me);
+ return ((PyObject *)v);
+}
+
+static void view_pydealloc(PyObject *me)
+ { Py_DECREF(VIEW_MAP(me)); FREEOBJ(me); }
+
+#define BINOP(op, update) \
+ static PyObject *view_py##op(PyObject *me, PyObject *you) \
+ { \
+ PyObject *set = 0; \
+ PyObject *rc = 0; \
+ \
+ set = PySet_New(me); if (!set) goto end; \
+ if (!PyObject_CallMethod(set, #update, "(O)", you)) goto end; \
+ rc = set; set = 0; \
+ end: \
+ Py_XDECREF(set); \
+ return (rc); \
+ }
+BINOP(and, intersection_update)
+BINOP(or, update)
+BINOP(xor, symmetric_difference_update)
+#undef BINOP
+
+static int all_contained_p(PyObject *x, PyObject *y)
+{
+ PyObject *i = 0, *e;
+ int b, rc = -1;
+
+ i = PyObject_GetIter(x); if (!i) goto end;
+ for (;;) {
+ e = PyIter_Next(i); if (!e) break;
+ b = PySequence_Contains(y, e); Py_DECREF(e); if (b < 0) goto end;
+ if (!b) { rc = 0; goto end; }
+ }
+ if (PyErr_Occurred()) goto end;
+ rc = 1;
+end:
+ Py_XDECREF(i);
+ return (rc);
+}
+
+static Py_ssize_t view_pysize(PyObject *me)
+ { return (PyMapping_Size(VIEW_MAP(me))); }
+
+static PyObject *view_pyrichcompare(PyObject *me, PyObject *you, int op)
+{
+ PyObject *map = ITER_MAP(me);
+ Py_ssize_t mysz, yoursz;
+ int b;
+
+ mysz = PyMapping_Size(map); if (mysz < 0) return (0);
+ yoursz = PyObject_Size(you);
+ if (yoursz < 0) { PyErr_Clear(); RETURN_NOTIMPL; }
+
+ switch (op) {
+ case Py_EQ:
+ if (mysz != yoursz) RETURN_FALSE;
+ b = all_contained_p(you, me);
+ break;
+ case Py_NE:
+ if (mysz != yoursz) RETURN_TRUE;
+ b = all_contained_p(you, me);
+ break;
+ case Py_LT:
+ if (mysz >= yoursz) RETURN_FALSE;
+ b = all_contained_p(me, you);
+ break;
+ case Py_LE:
+ if (mysz > yoursz) RETURN_FALSE;
+ b = all_contained_p(me, you);
+ break;
+ case Py_GE:
+ if (mysz < yoursz) RETURN_FALSE;
+ b = all_contained_p(you, me);
+ break;
+ case Py_GT:
+ if (mysz <= yoursz) RETURN_FALSE;
+ b = all_contained_p(you, me);
+ break;
+ default:
+ abort();
+ }
+ if (b < 0) return (0);
+ return (getbool(b));
+}
+
+static PyObject *keyview_pyiter(PyObject *me)
+ { return (gmap_mkiter(VIEW_MAP(me), keyiter_pytype)); }
+
+static int keyview_pyhaskey(PyObject *me, PyObject *k)
+{
+ PyObject *map = VIEW_MAP(me);
+ const struct gmap_ops *gmops = GMAP_OPS(map);
+ return (gmops->lookup(map, k, 0) ? 1 : PyErr_Occurred() ? -1 : 0);
+}
+
+static int itemview_pyhaskey(PyObject *me, PyObject *it)
+{
+ PyObject *map = VIEW_MAP(me);
+ const struct gmap_ops *gmops = GMAP_OPS(map);
+ void *e;
+ int b;
+ PyObject *v;
+
+ if (!PyTuple_Check(it) || PyTuple_GET_SIZE(it) != 2) return (0);
+ e = gmops->lookup(map, PyTuple_GET_ITEM(it, 0), 0);
+ if (!e) return (PyErr_Occurred() ? -1 : 0);
+ v = gmops->entry_value(map, e); if (!v) return (-1);
+ b = PyObject_RichCompareBool(v, PyTuple_GET_ITEM(it, 1), Py_EQ);
+ Py_DECREF(v); return (b);
+}
+
+static PyObject *valview_pyiter(PyObject *me)
+ { return (gmap_mkiter(VIEW_MAP(me), valiter_pytype)); }
+
+static PyObject *itemview_pyiter(PyObject *me)
+ { return (gmap_mkiter(VIEW_MAP(me), itemiter_pytype)); }
+
+static const PyNumberMethods view_pynumber = {
+ 0, /* @nb_add@ */
+ 0, /* @nb_subtract@ */
+ 0, /* @nb_multiply@ */
+#ifdef PY2
+ 0, /* @nb_divide@ */
+#endif
+ 0, /* @nb_remainder@ */
+ 0, /* @nb_divmod@ */
+ 0, /* @nb_power@ */
+ 0, /* @nb_negative@ */
+ 0, /* @nb_positive@ */
+ 0, /* @nb_absolute@ */
+ 0, /* @nb_nonzero@ */
+ 0, /* @nb_invert@ */
+ 0, /* @nb_lshift@ */
+ 0, /* @nb_rshift@ */
+ view_pyand, /* @nb_and@ */
+ view_pyxor, /* @nb_xor@ */
+ view_pyor, /* @nb_or@ */
+ 0, /* @nb_coerce@ */
+ 0, /* @nb_int@ */
+ 0, /* @nb_long@ */
+ 0, /* @nb_float@ */
+ 0, /* @nb_oct@ */
+ 0, /* @nb_hex@ */
+};
+
+static const PySequenceMethods keyview_pysequence = {
+ view_pysize, /* @sq_length@ */
+ 0, /* @sq_concat@ */
+ 0, /* @sq_repeat@ */
+ 0, /* @sq_item@ */
+ 0, /* @sq_slice@ */
+ 0, /* @sq_ass_item@ */
+ 0, /* @sq_ass_slice@ */
+ keyview_pyhaskey, /* @sq_contains@ */
+ 0, /* @sq_inplace_concat@ */
+ 0, /* @sq_inplace_repeat@ */
+};
+
+static const PyTypeObject keyview_pytype_skel = {
+ PyVarObject_HEAD_INIT(0, 0) /* Header */
+ "_KeyView", /* @tp_name@ */
+ sizeof(view_pyobj), /* @tp_basicsize@ */
+ 0, /* @tp_itemsize@ */
+
+ view_pydealloc, /* @tp_dealloc@ */
+ 0, /* @tp_print@ */
+ 0, /* @tp_getattr@ */
+ 0, /* @tp_setattr@ */
+ 0, /* @tp_compare@ */
+ 0, /* @tp_repr@ */
+ PYNUMBER(view), /* @tp_as_number@ */
+ PYSEQUENCE(keyview), /* @tp_as_sequence@ */
+ 0, /* @tp_as_mapping@ */
+ 0, /* @tp_hash@ */
+ 0, /* @tp_call@ */
+ 0, /* @tp_str@ */
+ 0, /* @tp_getattro@ */
+ 0, /* @tp_setattro@ */
+ 0, /* @tp_as_buffer@ */
+ Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
+ Py_TPFLAGS_BASETYPE,
+
+ /* @tp_doc@ */
+ "View of a mapping's keys.",
+
+ 0, /* @tp_traverse@ */
+ 0, /* @tp_clear@ */
+ view_pyrichcompare, /* @tp_richcompare@ */
+ 0, /* @tp_weaklistoffset@ */
+ keyview_pyiter, /* @tp_iter@ */
+ 0, /* @tp_iternext@ */
+ 0, /* @tp_methods@ */
+ 0, /* @tp_members@ */
+ 0, /* @tp_getset@ */
+ 0, /* @tp_base@ */
+ 0, /* @tp_dict@ */
+ 0, /* @tp_descr_get@ */
+ 0, /* @tp_descr_set@ */
+ 0, /* @tp_dictoffset@ */
+ 0, /* @tp_init@ */
+ PyType_GenericAlloc, /* @tp_alloc@ */
+ abstract_pynew, /* @tp_new@ */
+ 0, /* @tp_free@ */
+ 0 /* @tp_is_gc@ */
+};
+
+static const PySequenceMethods valview_pysequence = {
+ view_pysize, /* @sq_length@ */
+ 0, /* @sq_concat@ */
+ 0, /* @sq_repeat@ */
+ 0, /* @sq_item@ */
+ 0, /* @sq_slice@ */
+ 0, /* @sq_ass_item@ */
+ 0, /* @sq_ass_slice@ */
+ 0, /* @sq_contains@ */
+ 0, /* @sq_inplace_concat@ */
+ 0, /* @sq_inplace_repeat@ */
+};
+
+static const PyTypeObject valview_pytype_skel = {
+ PyVarObject_HEAD_INIT(0, 0) /* Header */
+ "_ValueView", /* @tp_name@ */
+ sizeof(view_pyobj), /* @tp_basicsize@ */
+ 0, /* @tp_itemsize@ */
+
+ view_pydealloc, /* @tp_dealloc@ */
+ 0, /* @tp_print@ */
+ 0, /* @tp_getattr@ */
+ 0, /* @tp_setattr@ */
+ 0, /* @tp_compare@ */
+ 0, /* @tp_repr@ */
+ PYNUMBER(view), /* @tp_as_number@ */
+ PYSEQUENCE(valview), /* @tp_as_sequence@ */
+ 0, /* @tp_as_mapping@ */
+ 0, /* @tp_hash@ */
+ 0, /* @tp_call@ */
+ 0, /* @tp_str@ */
+ 0, /* @tp_getattro@ */
+ 0, /* @tp_setattro@ */
+ 0, /* @tp_as_buffer@ */
+ Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
+ Py_TPFLAGS_BASETYPE,
+
+ /* @tp_doc@ */
+ "View of a mapping's values.",
+
+ 0, /* @tp_traverse@ */
+ 0, /* @tp_clear@ */
+ 0, /* @tp_richcompare@ */
+ 0, /* @tp_weaklistoffset@ */
+ valview_pyiter, /* @tp_iter@ */
+ 0, /* @tp_iternext@ */
+ 0, /* @tp_methods@ */
+ 0, /* @tp_members@ */
+ 0, /* @tp_getset@ */
+ 0, /* @tp_base@ */
+ 0, /* @tp_dict@ */
+ 0, /* @tp_descr_get@ */
+ 0, /* @tp_descr_set@ */
+ 0, /* @tp_dictoffset@ */
+ 0, /* @tp_init@ */
+ PyType_GenericAlloc, /* @tp_alloc@ */
+ abstract_pynew, /* @tp_new@ */
+ 0, /* @tp_free@ */
+ 0 /* @tp_is_gc@ */
+};
+
+static const PySequenceMethods itemview_pysequence = {
+ view_pysize, /* @sq_length@ */
+ 0, /* @sq_concat@ */
+ 0, /* @sq_repeat@ */
+ 0, /* @sq_item@ */
+ 0, /* @sq_slice@ */
+ 0, /* @sq_ass_item@ */
+ 0, /* @sq_ass_slice@ */
+ itemview_pyhaskey, /* @sq_contains@ */
+ 0, /* @sq_inplace_concat@ */
+ 0, /* @sq_inplace_repeat@ */
+};
+
+static const PyTypeObject itemview_pytype_skel = {
+ PyVarObject_HEAD_INIT(0, 0) /* Header */
+ "_ItemView", /* @tp_name@ */
+ sizeof(view_pyobj), /* @tp_basicsize@ */
+ 0, /* @tp_itemsize@ */
+
+ view_pydealloc, /* @tp_dealloc@ */
+ 0, /* @tp_print@ */
+ 0, /* @tp_getattr@ */
+ 0, /* @tp_setattr@ */
+ 0, /* @tp_compare@ */
+ 0, /* @tp_repr@ */
+ PYNUMBER(view), /* @tp_as_number@ */
+ PYSEQUENCE(itemview), /* @tp_as_sequence@ */
+ 0, /* @tp_as_mapping@ */
+ 0, /* @tp_hash@ */
+ 0, /* @tp_call@ */
+ 0, /* @tp_str@ */
+ 0, /* @tp_getattro@ */
+ 0, /* @tp_setattro@ */
+ 0, /* @tp_as_buffer@ */
+ Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
+ Py_TPFLAGS_BASETYPE,
+
+ /* @tp_doc@ */
+ "View of a mapping's key/value items.",
+
+ 0, /* @tp_traverse@ */
+ 0, /* @tp_clear@ */
+ view_pyrichcompare, /* @tp_richcompare@ */
+ 0, /* @tp_weaklistoffset@ */
+ itemview_pyiter, /* @tp_iter@ */
+ 0, /* @tp_iternext@ */
+ 0, /* @tp_methods@ */
+ 0, /* @tp_members@ */
+ 0, /* @tp_getset@ */
+ 0, /* @tp_base@ */
+ 0, /* @tp_dict@ */
+ 0, /* @tp_descr_get@ */
+ 0, /* @tp_descr_set@ */
+ 0, /* @tp_dictoffset@ */
+ 0, /* @tp_init@ */
+ PyType_GenericAlloc, /* @tp_alloc@ */
+ abstract_pynew, /* @tp_new@ */
+ 0, /* @tp_free@ */
+ 0 /* @tp_is_gc@ */
+};
+
+#endif
+
/*----- Other mapping protocol support ------------------------------------*/
Py_ssize_t gmap_pysize(PyObject *me)
0 /* @sq_inplace_repeat@ */
};
+#ifdef PY3
+
+PyObject *gmapmeth_keys(PyObject *me)
+ { return (gmap_mkview(me, keyview_pytype)); }
+
+PyObject *gmapmeth_values(PyObject *me)
+ { return (gmap_mkview(me, valview_pytype)); }
+
+PyObject *gmapmeth_items(PyObject *me)
+ { return (gmap_mkview(me, itemview_pytype)); }
+
+#else
+
PyObject *gmapmeth_has_key(PyObject *me, PyObject *arg)
{
PyObject *k;
PyObject *gmapmeth_iteritems(PyObject *me)
{ return (gmap_mkiter(me, itemiter_pytype)); }
+#endif
+
PyObject *gmap_pyiter(PyObject *me)
{ return gmap_mkiter(me, keyiter_pytype); }
unsigned foundp;
int rc = -1;
- v = PyObject_CallMethod(map, "iteritems", 0);
+ v = PyObject_CallMethod(map, PY23("iteritems", "items"), 0);
+#ifdef PY3
+ if (v) { i = PyObject_GetIter(v); Py_DECREF(v); v = 0; }
+#else
i = v; v = 0;
+#endif
if (i) {
for (;;) {
INITTYPE(keyiter, root);
INITTYPE(itemiter, root);
INITTYPE(valiter, root);
+#ifdef PY3
+ INITTYPE(keyview, root);
+ INITTYPE(valview, root);
+ INITTYPE(itemview, root);
+#endif
}
void pyke_gmap_pyinsert(PyObject *mod)
INSERT("_KeyIter", keyiter_pytype);
INSERT("_ValueIter", valiter_pytype);
INSERT("_ItemIter", itemiter_pytype);
+#ifdef PY3
+ INSERT("_KeyView", keyview_pytype);
+ INSERT("_ValueView", valview_pytype);
+ INSERT("_ItemView", itemview_pytype);
+#endif
}
/*----- That's all, folks -------------------------------------------------*/