3 * Generic mapping support
5 * (c) 2019 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of Pyke: the Python Kit for Extensions.
12 * Pyke is free software: you can redistribute it and/or modify it under
13 * the terms of the GNU General Public License as published by the Free
14 * Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
17 * Pyke is distributed in the hope that it will be useful, but WITHOUT
18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 * You should have received a copy of the GNU General Public License
23 * along with Pyke. If not, write to the Free Software Foundation, Inc.,
24 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 /*----- Header files ------------------------------------------------------*/
31 /*----- Iteration ---------------------------------------------------------*/
33 static PyTypeObject
*keyiter_pytype
, *itemiter_pytype
, *valiter_pytype
;
40 typedef struct iter_pyobj
{
45 #define ITER_MAP(o) (((iter_pyobj *)(o))->map)
46 #define ITER_ITER(o) (&((iter_pyobj *)(o))->iter)
47 #define ITER_EXTERNALP(o) \
48 (GMAP_OPS(ITER_MAP(o))->isz > sizeof(union iterstate))
49 #define ITER_I(o) (ITER_EXTERNALP(o) ? ITER_ITER(o)->external \
50 : &ITER_ITER(o)->internal)
52 static void *iter_init(PyObject
*me
, union iterstate
*iter
)
54 const gmap_ops
*gmops
= GMAP_OPS(me
);
57 if (gmops
->isz
<= sizeof(*iter
)) i
= &iter
->internal
;
58 else { i
= iter
->external
= PyObject_Malloc(gmops
->isz
); assert(i
); }
59 gmops
->iter_init(me
, i
);
63 static void iter_free(PyObject
*me
, union iterstate
*iter
)
64 { if (GMAP_OPS(me
)->isz
> sizeof(*iter
)) PyObject_Free(iter
->external
); }
66 static void iter_pydealloc(PyObject
*me
)
68 PyObject
*map
= ITER_MAP(me
);
69 iter_free(map
, ITER_ITER(me
));
70 Py_DECREF(map
); FREEOBJ(me
);
73 static PyObject
*gmap_mkiter(PyObject
*me
, PyTypeObject
*ty
)
75 iter_pyobj
*iter
= PyObject_NEW(iter_pyobj
, ty
);
77 iter
->map
= me
; Py_INCREF(me
);
78 iter_init(me
, &iter
->iter
);
79 return ((PyObject
*)iter
);
82 static PyObject
*keyiter_pynext(PyObject
*me
)
84 PyObject
*map
= ITER_MAP(me
);
85 const struct gmap_ops
*gmops
= GMAP_OPS(map
);
86 void *e
= gmops
->iter_next(map
, ITER_I(me
));
89 else return (gmops
->entry_key(map
, e
));
92 static const PyTypeObject keyiter_pytype_skel
= {
93 PyVarObject_HEAD_INIT(0, 0) /* Header */
94 "_KeyIter", /* @tp_name@ */
95 sizeof(iter_pyobj
), /* @tp_basicsize@ */
96 0, /* @tp_itemsize@ */
98 iter_pydealloc
, /* @tp_dealloc@ */
100 0, /* @tp_getattr@ */
101 0, /* @tp_setattr@ */
102 0, /* @tp_compare@ */
104 0, /* @tp_as_number@ */
105 0, /* @tp_as_sequence@ */
106 0, /* @tp_as_mapping@ */
110 0, /* @tp_getattro@ */
111 0, /* @tp_setattro@ */
112 0, /* @tp_as_buffer@ */
113 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
117 "Iterates over the keys of a mapping.",
119 0, /* @tp_traverse@ */
121 0, /* @tp_richcompare@ */
122 0, /* @tp_weaklistoffset@ */
123 PyObject_SelfIter
, /* @tp_iter@ */
124 keyiter_pynext
, /* @tp_iternext@ */
125 0, /* @tp_methods@ */
126 0, /* @tp_members@ */
130 0, /* @tp_descr_get@ */
131 0, /* @tp_descr_set@ */
132 0, /* @tp_dictoffset@ */
134 PyType_GenericAlloc
, /* @tp_alloc@ */
135 abstract_pynew
, /* @tp_new@ */
140 static PyObject
*valiter_pynext(PyObject
*me
)
142 PyObject
*map
= ITER_MAP(me
);
143 const struct gmap_ops
*gmops
= GMAP_OPS(map
);
144 void *e
= gmops
->iter_next(map
, ITER_I(me
));
147 else return (gmops
->entry_value(map
, e
));
150 static const PyTypeObject valiter_pytype_skel
= {
151 PyVarObject_HEAD_INIT(0, 0) /* Header */
152 "_ValueIter", /* @tp_name@ */
153 sizeof(iter_pyobj
), /* @tp_basicsize@ */
154 0, /* @tp_itemsize@ */
156 iter_pydealloc
, /* @tp_dealloc@ */
158 0, /* @tp_getattr@ */
159 0, /* @tp_setattr@ */
160 0, /* @tp_compare@ */
162 0, /* @tp_as_number@ */
163 0, /* @tp_as_sequence@ */
164 0, /* @tp_as_mapping@ */
168 0, /* @tp_getattro@ */
169 0, /* @tp_setattro@ */
170 0, /* @tp_as_buffer@ */
171 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
175 "Iterates over the values of a mapping.",
177 0, /* @tp_traverse@ */
179 0, /* @tp_richcompare@ */
180 0, /* @tp_weaklistoffset@ */
181 PyObject_SelfIter
, /* @tp_iter@ */
182 valiter_pynext
, /* @tp_iternext@ */
183 0, /* @tp_methods@ */
184 0, /* @tp_members@ */
188 0, /* @tp_descr_get@ */
189 0, /* @tp_descr_set@ */
190 0, /* @tp_dictoffset@ */
192 PyType_GenericAlloc
, /* @tp_alloc@ */
193 abstract_pynew
, /* @tp_new@ */
198 static PyObject
*itemiter_pynext(PyObject
*me
)
200 PyObject
*map
= ITER_MAP(me
);
201 const struct gmap_ops
*gmops
= GMAP_OPS(map
);
202 void *e
= gmops
->iter_next(map
, ITER_I(me
));
206 rc
= Py_BuildValue("(NN)",
207 gmops
->entry_key(map
, e
),
208 gmops
->entry_value(map
, e
));
212 static const PyTypeObject itemiter_pytype_skel
= {
213 PyVarObject_HEAD_INIT(0, 0) /* Header */
214 "_ItemIter", /* @tp_name@ */
215 sizeof(iter_pyobj
), /* @tp_basicsize@ */
216 0, /* @tp_itemsize@ */
218 iter_pydealloc
, /* @tp_dealloc@ */
220 0, /* @tp_getattr@ */
221 0, /* @tp_setattr@ */
222 0, /* @tp_compare@ */
224 0, /* @tp_as_number@ */
225 0, /* @tp_as_sequence@ */
226 0, /* @tp_as_mapping@ */
230 0, /* @tp_getattro@ */
231 0, /* @tp_setattro@ */
232 0, /* @tp_as_buffer@ */
233 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
237 "Iterates over the items of a mapping.",
239 0, /* @tp_traverse@ */
241 0, /* @tp_richcompare@ */
242 0, /* @tp_weaklistoffset@ */
243 PyObject_SelfIter
, /* @tp_iter@ */
244 itemiter_pynext
, /* @tp_iternext@ */
245 0, /* @tp_methods@ */
246 0, /* @tp_members@ */
250 0, /* @tp_descr_get@ */
251 0, /* @tp_descr_set@ */
252 0, /* @tp_dictoffset@ */
254 PyType_GenericAlloc
, /* @tp_alloc@ */
255 abstract_pynew
, /* @tp_new@ */
260 /*----- Mapping views -----------------------------------------------------*/
264 static PyTypeObject
*keyview_pytype
, *itemview_pytype
, *valview_pytype
;
266 typedef struct view_pyobj
{
270 #define VIEW_MAP(o) (((view_pyobj *)(o))->map)
272 static PyObject
*gmap_mkview(PyObject
*me
, PyTypeObject
*ty
)
274 view_pyobj
*v
= PyObject_NEW(view_pyobj
, ty
);
275 v
->map
= me
; Py_INCREF(me
);
276 return ((PyObject
*)v
);
279 static void view_pydealloc(PyObject
*me
)
280 { Py_DECREF(VIEW_MAP(me
)); FREEOBJ(me
); }
282 #define BINOP(op, update) \
283 static PyObject *view_py##op(PyObject *me, PyObject *you) \
288 set = PySet_New(me); if (!set) goto end; \
289 if (!PyObject_CallMethod(set, #update, "(O)", you)) goto end; \
295 BINOP(and, intersection_update
)
297 BINOP(xor, symmetric_difference_update
)
300 static int all_contained_p(PyObject
*x
, PyObject
*y
)
305 i
= PyObject_GetIter(x
); if (!i
) goto end
;
307 e
= PyIter_Next(i
); if (!e
) break;
308 b
= PySequence_Contains(y
, e
); Py_DECREF(e
); if (b
< 0) goto end
;
309 if (!b
) { rc
= 0; goto end
; }
311 if (PyErr_Occurred()) goto end
;
318 static Py_ssize_t
view_pysize(PyObject
*me
)
319 { return (PyMapping_Size(VIEW_MAP(me
))); }
321 static PyObject
*view_pyrichcompare(PyObject
*me
, PyObject
*you
, int op
)
323 PyObject
*map
= ITER_MAP(me
);
324 Py_ssize_t mysz
, yoursz
;
327 mysz
= PyMapping_Size(map
); if (mysz
< 0) return (0);
328 yoursz
= PyObject_Size(you
);
329 if (yoursz
< 0) { PyErr_Clear(); RETURN_NOTIMPL
; }
333 if (mysz
!= yoursz
) RETURN_FALSE
;
334 b
= all_contained_p(you
, me
);
337 if (mysz
!= yoursz
) RETURN_TRUE
;
338 b
= all_contained_p(you
, me
);
341 if (mysz
>= yoursz
) RETURN_FALSE
;
342 b
= all_contained_p(me
, you
);
345 if (mysz
> yoursz
) RETURN_FALSE
;
346 b
= all_contained_p(me
, you
);
349 if (mysz
< yoursz
) RETURN_FALSE
;
350 b
= all_contained_p(you
, me
);
353 if (mysz
<= yoursz
) RETURN_FALSE
;
354 b
= all_contained_p(you
, me
);
359 if (b
< 0) return (0);
363 static PyObject
*keyview_pyiter(PyObject
*me
)
364 { return (gmap_mkiter(VIEW_MAP(me
), keyiter_pytype
)); }
366 static int keyview_pyhaskey(PyObject
*me
, PyObject
*k
)
368 PyObject
*map
= VIEW_MAP(me
);
369 const struct gmap_ops
*gmops
= GMAP_OPS(map
);
370 return (gmops
->lookup(map
, k
, 0) ?
1 : PyErr_Occurred() ?
-1 : 0);
373 static int itemview_pyhaskey(PyObject
*me
, PyObject
*it
)
375 PyObject
*map
= VIEW_MAP(me
);
376 const struct gmap_ops
*gmops
= GMAP_OPS(map
);
381 if (!PyTuple_Check(it
) || PyTuple_GET_SIZE(it
) != 2) return (0);
382 e
= gmops
->lookup(map
, PyTuple_GET_ITEM(it
, 0), 0);
383 if (!e
) return (PyErr_Occurred() ?
-1 : 0);
384 v
= gmops
->entry_value(map
, e
); if (!v
) return (-1);
385 b
= PyObject_RichCompareBool(v
, PyTuple_GET_ITEM(it
, 1), Py_EQ
);
386 Py_DECREF(v
); return (b
);
389 static PyObject
*valview_pyiter(PyObject
*me
)
390 { return (gmap_mkiter(VIEW_MAP(me
), valiter_pytype
)); }
392 static PyObject
*itemview_pyiter(PyObject
*me
)
393 { return (gmap_mkiter(VIEW_MAP(me
), itemiter_pytype
)); }
395 static const PyNumberMethods view_pynumber
= {
397 0, /* @nb_subtract@ */
398 0, /* @nb_multiply@ */
402 0, /* @nb_remainder@ */
405 0, /* @nb_negative@ */
406 0, /* @nb_positive@ */
407 0, /* @nb_absolute@ */
408 0, /* @nb_nonzero@ */
412 view_pyand
, /* @nb_and@ */
413 view_pyxor
, /* @nb_xor@ */
414 view_pyor
, /* @nb_or@ */
423 static const PySequenceMethods keyview_pysequence
= {
424 view_pysize
, /* @sq_length@ */
429 0, /* @sq_ass_item@ */
430 0, /* @sq_ass_slice@ */
431 keyview_pyhaskey
, /* @sq_contains@ */
432 0, /* @sq_inplace_concat@ */
433 0, /* @sq_inplace_repeat@ */
436 static const PyTypeObject keyview_pytype_skel
= {
437 PyVarObject_HEAD_INIT(0, 0) /* Header */
438 "_KeyView", /* @tp_name@ */
439 sizeof(view_pyobj
), /* @tp_basicsize@ */
440 0, /* @tp_itemsize@ */
442 view_pydealloc
, /* @tp_dealloc@ */
444 0, /* @tp_getattr@ */
445 0, /* @tp_setattr@ */
446 0, /* @tp_compare@ */
448 PYNUMBER(view
), /* @tp_as_number@ */
449 PYSEQUENCE(keyview
), /* @tp_as_sequence@ */
450 0, /* @tp_as_mapping@ */
454 0, /* @tp_getattro@ */
455 0, /* @tp_setattro@ */
456 0, /* @tp_as_buffer@ */
457 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
461 "View of a mapping's keys.",
463 0, /* @tp_traverse@ */
465 view_pyrichcompare
, /* @tp_richcompare@ */
466 0, /* @tp_weaklistoffset@ */
467 keyview_pyiter
, /* @tp_iter@ */
468 0, /* @tp_iternext@ */
469 0, /* @tp_methods@ */
470 0, /* @tp_members@ */
474 0, /* @tp_descr_get@ */
475 0, /* @tp_descr_set@ */
476 0, /* @tp_dictoffset@ */
478 PyType_GenericAlloc
, /* @tp_alloc@ */
479 abstract_pynew
, /* @tp_new@ */
484 static const PySequenceMethods valview_pysequence
= {
485 view_pysize
, /* @sq_length@ */
490 0, /* @sq_ass_item@ */
491 0, /* @sq_ass_slice@ */
492 0, /* @sq_contains@ */
493 0, /* @sq_inplace_concat@ */
494 0, /* @sq_inplace_repeat@ */
497 static const PyTypeObject valview_pytype_skel
= {
498 PyVarObject_HEAD_INIT(0, 0) /* Header */
499 "_ValueView", /* @tp_name@ */
500 sizeof(view_pyobj
), /* @tp_basicsize@ */
501 0, /* @tp_itemsize@ */
503 view_pydealloc
, /* @tp_dealloc@ */
505 0, /* @tp_getattr@ */
506 0, /* @tp_setattr@ */
507 0, /* @tp_compare@ */
509 PYNUMBER(view
), /* @tp_as_number@ */
510 PYSEQUENCE(valview
), /* @tp_as_sequence@ */
511 0, /* @tp_as_mapping@ */
515 0, /* @tp_getattro@ */
516 0, /* @tp_setattro@ */
517 0, /* @tp_as_buffer@ */
518 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
522 "View of a mapping's values.",
524 0, /* @tp_traverse@ */
526 0, /* @tp_richcompare@ */
527 0, /* @tp_weaklistoffset@ */
528 valview_pyiter
, /* @tp_iter@ */
529 0, /* @tp_iternext@ */
530 0, /* @tp_methods@ */
531 0, /* @tp_members@ */
535 0, /* @tp_descr_get@ */
536 0, /* @tp_descr_set@ */
537 0, /* @tp_dictoffset@ */
539 PyType_GenericAlloc
, /* @tp_alloc@ */
540 abstract_pynew
, /* @tp_new@ */
545 static const PySequenceMethods itemview_pysequence
= {
546 view_pysize
, /* @sq_length@ */
551 0, /* @sq_ass_item@ */
552 0, /* @sq_ass_slice@ */
553 itemview_pyhaskey
, /* @sq_contains@ */
554 0, /* @sq_inplace_concat@ */
555 0, /* @sq_inplace_repeat@ */
558 static const PyTypeObject itemview_pytype_skel
= {
559 PyVarObject_HEAD_INIT(0, 0) /* Header */
560 "_ItemView", /* @tp_name@ */
561 sizeof(view_pyobj
), /* @tp_basicsize@ */
562 0, /* @tp_itemsize@ */
564 view_pydealloc
, /* @tp_dealloc@ */
566 0, /* @tp_getattr@ */
567 0, /* @tp_setattr@ */
568 0, /* @tp_compare@ */
570 PYNUMBER(view
), /* @tp_as_number@ */
571 PYSEQUENCE(itemview
), /* @tp_as_sequence@ */
572 0, /* @tp_as_mapping@ */
576 0, /* @tp_getattro@ */
577 0, /* @tp_setattro@ */
578 0, /* @tp_as_buffer@ */
579 Py_TPFLAGS_DEFAULT
| /* @tp_flags@ */
583 "View of a mapping's key/value items.",
585 0, /* @tp_traverse@ */
587 view_pyrichcompare
, /* @tp_richcompare@ */
588 0, /* @tp_weaklistoffset@ */
589 itemview_pyiter
, /* @tp_iter@ */
590 0, /* @tp_iternext@ */
591 0, /* @tp_methods@ */
592 0, /* @tp_members@ */
596 0, /* @tp_descr_get@ */
597 0, /* @tp_descr_set@ */
598 0, /* @tp_dictoffset@ */
600 PyType_GenericAlloc
, /* @tp_alloc@ */
601 abstract_pynew
, /* @tp_new@ */
608 /*----- Other mapping protocol support ------------------------------------*/
610 Py_ssize_t
gmap_pysize(PyObject
*me
)
612 const gmap_ops
*gmops
= GMAP_OPS(me
);
613 union iterstate iter
;
617 i
= iter_init(me
, &iter
);
618 while (gmops
->iter_next(me
, i
)) n
++;
619 iter_free(me
, &iter
);
623 PyObject
*gmap_pylookup(PyObject
*me
, PyObject
*key
)
625 const gmap_ops
*gmops
= GMAP_OPS(me
);
626 void *e
= gmops
->lookup(me
, key
, 0);
629 if (!e
) { if (!PyErr_Occurred()) MAPERR(key
); else goto end
; }
630 rc
= gmops
->entry_value(me
, e
);
635 int gmap_pystore(PyObject
*me
, PyObject
*key
, PyObject
*value
)
637 const gmap_ops
*gmops
= GMAP_OPS(me
);
639 void *e
= gmops
->lookup(me
, key
, &f
);
644 rc
= gmops
->del_entry(me
, e
);
646 rc
= gmops
->set_entry(me
, e
, value
);
647 if (rc
&& !f
) gmops
->del_entry(me
, e
);
654 int gmap_pyhaskey(PyObject
*me
, PyObject
*key
)
655 { return (GMAP_OPS(me
)->lookup(me
, key
, 0) ?
1 : PyErr_Occurred() ?
-1 : 0); }
657 const PySequenceMethods gmap_pysequence
= {
663 0, /* @sq_ass_item@ */
664 0, /* @sq_ass_slice@ */
665 gmap_pyhaskey
, /* @sq_contains@ */
666 0, /* @sq_inplace_concat@ */
667 0 /* @sq_inplace_repeat@ */
672 PyObject
*gmapmeth_keys(PyObject
*me
)
673 { return (gmap_mkview(me
, keyview_pytype
)); }
675 PyObject
*gmapmeth_values(PyObject
*me
)
676 { return (gmap_mkview(me
, valview_pytype
)); }
678 PyObject
*gmapmeth_items(PyObject
*me
)
679 { return (gmap_mkview(me
, itemview_pytype
)); }
683 PyObject
*gmapmeth_has_key(PyObject
*me
, PyObject
*arg
)
687 if (!PyArg_ParseTuple(arg
, "O:has_key", &k
)) return (0);
688 e
= GMAP_OPS(me
)->lookup(me
, k
, 0);
690 else if (!PyErr_Occurred()) RETURN_FALSE
;
694 PyObject
*gmapmeth_keys(PyObject
*me
)
696 const gmap_ops
*gmops
= GMAP_OPS(me
);
697 union iterstate iter
; void *i
= 0, *e
;
698 PyObject
*l
= 0, *k
, *rc
= 0;
701 if ((l
= PyList_New(0)) == 0) goto done
;
702 i
= iter_init(me
, &iter
);
703 while ((e
= gmops
->iter_next(me
, i
)) != 0) {
704 k
= gmops
->entry_key(me
, e
);
705 err
= PyList_Append(l
, k
);
712 if (i
) iter_free(me
, &iter
);
716 PyObject
*gmapmeth_values(PyObject
*me
)
718 const gmap_ops
*gmops
= GMAP_OPS(me
);
719 union iterstate iter
; void *i
= 0, *e
;
720 PyObject
*l
= 0, *v
, *rc
= 0;
723 if ((l
= PyList_New(0)) == 0) goto done
;
724 i
= iter_init(me
, &iter
);
725 while ((e
= gmops
->iter_next(me
, i
)) != 0) {
726 v
= gmops
->entry_value(me
, e
);
727 err
= PyList_Append(l
, v
);
734 if (i
) iter_free(me
, &iter
);
738 PyObject
*gmapmeth_items(PyObject
*me
)
740 const gmap_ops
*gmops
= GMAP_OPS(me
);
741 union iterstate iter
; void *i
= 0, *e
;
742 PyObject
*l
= 0, *z
, *rc
= 0;
745 if ((l
= PyList_New(0)) == 0) goto done
;
746 i
= iter_init(me
, &iter
);
747 while ((e
= gmops
->iter_next(me
, i
)) != 0) {
748 if ((z
= Py_BuildValue("(NN)",
749 gmops
->entry_key(me
, e
),
750 gmops
->entry_value(me
, e
))) == 0)
752 err
= PyList_Append(l
, z
);
759 if (i
) iter_free(me
, &iter
);
763 PyObject
*gmapmeth_iterkeys(PyObject
*me
)
764 { return (gmap_mkiter(me
, keyiter_pytype
)); }
766 PyObject
*gmapmeth_itervalues(PyObject
*me
)
767 { return (gmap_mkiter(me
, valiter_pytype
)); }
769 PyObject
*gmapmeth_iteritems(PyObject
*me
)
770 { return (gmap_mkiter(me
, itemiter_pytype
)); }
774 PyObject
*gmap_pyiter(PyObject
*me
)
775 { return gmap_mkiter(me
, keyiter_pytype
); }
777 PyObject
*gmapmeth_clear(PyObject
*me
)
779 const gmap_ops
*gmops
= GMAP_OPS(me
);
780 union iterstate iter
;
784 i
= iter_init(me
, &iter
);
786 e
= gmops
->iter_next(me
, i
); if (!e
) break;
787 if (gmops
->del_entry(me
, e
)) goto end
;
789 iter_free(me
, &iter
);
790 rc
= me
; Py_INCREF(me
);
795 static const char *const def_kwlist
[] = { "key", "default", 0 };
796 #define DEF_KWLIST ((/*unconst*/ char **)def_kwlist)
798 PyObject
*gmapmeth_get(PyObject
*me
, PyObject
*arg
, PyObject
*kw
)
800 const gmap_ops
*gmops
= GMAP_OPS(me
);
801 PyObject
*k
, *def
= Py_None
;
804 if (!PyArg_ParseTupleAndKeywords(arg
, kw
, "O|O:get", DEF_KWLIST
, &k
, &def
))
806 e
= gmops
->lookup(me
, k
, 0);
807 if (e
) return (gmops
->entry_value(me
, e
));
808 else if (!PyErr_Occurred()) RETURN_OBJ(def
);
812 PyObject
*gmapmeth_setdefault(PyObject
*me
, PyObject
*arg
, PyObject
*kw
)
814 const gmap_ops
*gmops
= GMAP_OPS(me
);
815 PyObject
*k
, *def
= Py_None
;
819 if (!PyArg_ParseTupleAndKeywords(arg
, kw
, "O|O:setdefault", DEF_KWLIST
,
822 e
= gmops
->lookup(me
, k
, &f
);
824 else if (f
) return (gmops
->entry_value(me
, e
));
825 else if (gmops
->set_entry(me
, e
, def
)) return (0);
826 else RETURN_OBJ(def
);
829 PyObject
*gmapmeth_pop(PyObject
*me
, PyObject
*arg
, PyObject
*kw
)
831 const gmap_ops
*gmops
= GMAP_OPS(me
);
832 PyObject
*k
, *def
= 0;
836 if (!PyArg_ParseTupleAndKeywords(arg
, kw
, "O|O:pop", DEF_KWLIST
, &k
, &def
))
838 e
= gmops
->lookup(me
, k
, 0);
840 if (PyErr_Occurred()) goto end
;
841 else if (def
) { rc
= def
; Py_INCREF(rc
); }
844 rc
= gmops
->entry_value(me
, e
);
845 if (gmops
->del_entry(me
, e
)) { Py_DECREF(rc
); rc
= 0; }
851 int gmap_pyupdate(PyObject
*me
, PyObject
*map
)
853 const gmap_ops
*gmops
= GMAP_OPS(me
);
854 PyObject
*i
= 0, *item
= 0, *k
= 0, *v
= 0;
859 if (!map
) return (0);
860 v
= PyObject_CallMethod(map
, PY23("iteritems", "items"), 0);
862 if (v
) { i
= PyObject_GetIter(v
); Py_DECREF(v
); v
= 0; }
869 item
= PyIter_Next(i
); if (!item
) break;
870 if (!PyTuple_Check(item
) || PyTuple_GET_SIZE(item
) != 2)
871 TYERR("wanted a pair");
872 k
= PyTuple_GET_ITEM(item
, 0); Py_INCREF(k
);
873 v
= PyTuple_GET_ITEM(item
, 1); Py_INCREF(v
);
874 e
= gmops
->lookup(me
, k
, &foundp
); if (!e
) goto end
;
875 if (gmops
->set_entry(me
, e
, v
)) goto end
;
876 Py_DECREF(item
); Py_DECREF(k
); Py_DECREF(v
); item
= k
= v
= 0;
878 if (PyErr_Occurred()) goto end
;
881 i
= PyObject_GetIter(map
); if (!i
) goto end
;
883 k
= PyIter_Next(i
); if (!k
) goto end
;
884 v
= PyObject_GetItem(map
, k
); if (!v
) goto end
;
885 e
= gmops
->lookup(me
, k
, &foundp
); if (!e
) goto end
;
886 if (gmops
->set_entry(me
, e
, v
)) goto end
;
887 Py_DECREF(k
); Py_DECREF(v
); k
= v
= 0;
889 if (PyErr_Occurred()) goto end
;
893 Py_XDECREF(i
); Py_XDECREF(item
);
894 Py_XDECREF(k
); Py_XDECREF(v
);
898 PyObject
*gmapmeth_update(PyObject
*me
, PyObject
*arg
, PyObject
*kw
)
902 if (!PyArg_ParseTuple(arg
, "|O:update", &map
)) return (0);
903 if (gmap_pyupdate(me
, map
)) return (0);
904 if (gmap_pyupdate(me
, kw
)) return (0);
908 PyObject
*gmapmeth_popitem(PyObject
*me
)
910 const gmap_ops
*gmops
= GMAP_OPS(me
);
911 union iterstate iter
;
916 i
= iter_init(me
, &iter
);
917 e
= gmops
->iter_next(me
, i
);
918 iter_free(me
, &iter
);
922 rc
= Py_BuildValue("(NN)",
923 gmops
->entry_key(me
, e
), gmops
->entry_value(me
, e
));
924 if (gmops
->del_entry(me
, e
)) { Py_DECREF(rc
); rc
= 0; }
930 const PyMethodDef gmapro_pymethods
[] = {
935 const PyMethodDef gmap_pymethods
[] = {
940 /*----- Submodule initialization ------------------------------------------*/
942 void pyke_gmap_pyinit(void)
944 INITTYPE(keyiter
, root
);
945 INITTYPE(itemiter
, root
);
946 INITTYPE(valiter
, root
);
948 INITTYPE(keyview
, root
);
949 INITTYPE(valview
, root
);
950 INITTYPE(itemview
, root
);
954 void pyke_gmap_pyinsert(PyObject
*mod
)
956 INSERT("_KeyIter", keyiter_pytype
);
957 INSERT("_ValueIter", valiter_pytype
);
958 INSERT("_ItemIter", itemiter_pytype
);
960 INSERT("_KeyView", keyview_pytype
);
961 INSERT("_ValueView", valview_pytype
);
962 INSERT("_ItemView", itemview_pytype
);
966 /*----- That's all, folks -------------------------------------------------*/