util.c: Add conversions between Python objects and `kludge64'.
[pyke] / util.c
CommitLineData
68ec53f3
MW
1/* -*-c-*-
2 *
68ec53f3
MW
3 * Miscellaneous utilities (not Catacomb-specific)
4 *
5 * (c) 2005 Straylight/Edgeware
6 */
7
0b1eafbf 8/*----- Licensing notice --------------------------------------------------*
68ec53f3
MW
9 *
10 * This file is part of the Python interface to Catacomb.
11 *
12 * Catacomb/Python is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
0b1eafbf 16 *
68ec53f3
MW
17 * Catacomb/Python is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
0b1eafbf 21 *
68ec53f3
MW
22 * You should have received a copy of the GNU General Public License
23 * along with Catacomb/Python; if not, write to the Free Software Foundation,
24 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 */
26
27/*----- Header files ------------------------------------------------------*/
28
29#include "catacomb-python.h"
30
0156e402
MW
31/*----- External values ---------------------------------------------------*/
32
33static PyObject *modname = 0;
34
68ec53f3
MW
35/*----- Conversions -------------------------------------------------------*/
36
1e082a86
MW
37PyObject *getulong(unsigned long w)
38{
4f3d0934 39 if (w <= LONG_MAX)
1e082a86
MW
40 return (PyInt_FromLong(w));
41 else
42 return (PyLong_FromUnsignedLong(w));
43}
68ec53f3 44
1b6734b6
MW
45static PyObject *i32 = 0;
46static int init_i32(void)
47 { if (!i32 && (i32 = PyInt_FromLong(32)) == 0) return (-1); return (0); }
48
49PyObject *getk64(kludge64 u)
50{
51 PyObject *i = 0, *j = 0, *t;
52 PyObject *rc = 0;
53
54 if (init_i32()) goto end;
55 if ((i = PyLong_FromUnsignedLong(HI64(u))) == 0) goto end;
56 if ((t = PyNumber_InPlaceLshift(i, i32)) == 0) goto end;
57 Py_DECREF(i); i = t;
58 if ((j = PyLong_FromUnsignedLong(LO64(u))) == 0) goto end;
59 if ((t = PyNumber_InPlaceOr(i, j)) == 0) goto end;
60 Py_DECREF(i); i = t;
61 if ((rc = PyNumber_Int(i)) == 0) goto end;
62end:
63 if (i) Py_DECREF(i);
64 if (j) Py_DECREF(j);
65 return (rc);
66}
67
68ec53f3
MW
68PyObject *getbool(int b)
69{
70 if (b) RETURN_TRUE;
71 else RETURN_FALSE;
72}
73
74PyObject *abstract_pynew(PyTypeObject *ty, PyObject *arg, PyObject *kw)
75{
76 PyErr_SetString(PyExc_TypeError, "can't instantiate this class");
77 return (0);
78}
79
80int convulong(PyObject *o, void *pp)
81{
82 long i;
83 unsigned long *p = pp;
84 PyObject *t;
85
86 if (PyInt_Check(o)) {
87 i = PyInt_AS_LONG(o);
799dffb2 88 if (i < 0) VALERR("must be nonnegative");
68ec53f3
MW
89 *p = i;
90 } else {
91 if ((t = PyNumber_Long(o)) == 0) goto end;
92 *p = PyLong_AsUnsignedLong(t);
93 Py_DECREF(t);
94 if (PyErr_Occurred()) goto end;
95 }
96 return (1);
97end:
98 return (0);
99}
100
101#define CONVU_(n) \
102 int convu##n(PyObject *o, void *pp) \
103 { \
104 unsigned long u; \
105 uint##n *p = pp; \
106 \
107 if (!convulong(o, &u)) goto end; \
799dffb2 108 if (u > MASK##n) VALERR("out of range"); \
68ec53f3
MW
109 *p = u; \
110 return (1); \
111 end: \
112 return (0); \
113 }
114DOUINTSZ(CONVU_)
115
116int convuint(PyObject *o, void *pp)
117{
118 unsigned long u;
119 unsigned *p = pp;
120
121 if (!convulong(o, &u)) goto end;
799dffb2 122 if (u > UINT_MAX) VALERR("out of range");
68ec53f3
MW
123 *p = u;
124 return (1);
125end:
126 return (0);
127}
128
1b6734b6
MW
129int convk64(PyObject *o, void *pp)
130{
131 PyObject *i = 0, *t;
132 int rc = 0;
133 uint32 lo, hi;
134
135 if (init_i32()) goto end;
136 if ((i = PyNumber_Int(o)) == 0) goto end;
137 lo = PyInt_AsUnsignedLongMask(i);
138 if ((t = PyNumber_InPlaceRshift(i, i32)) == 0) goto end;
139 Py_DECREF(i); i = t;
140 hi = PyInt_AsUnsignedLongMask(i);
141 if ((t = PyNumber_InPlaceRshift(i, i32)) == 0) goto end;
142 Py_DECREF(i); i = t;
143 if (PyObject_IsTrue(i)) VALERR("out of range");
144 SET64(*(kludge64 *)pp, hi, lo);
145 rc = 1;
146end:
147 if (i) Py_DECREF(i);
148 return (rc);
149}
150
68ec53f3
MW
151int convmpw(PyObject *o, void *pp)
152{
153 unsigned long u;
154 unsigned *p = pp;
155
156 if (!convulong(o, &u)) goto end;
799dffb2 157 if (u > MPW_MAX) VALERR("out of range");
68ec53f3
MW
158 *p = u;
159 return (1);
160end:
161 return (0);
162}
163
164int convszt(PyObject *o, void *pp)
165{
166 unsigned long u;
167 size_t *p = pp;
168
169 if (!convulong(o, &u)) goto end;
799dffb2 170 if (u > ~(size_t)0) VALERR("out of range");
68ec53f3
MW
171 *p = u;
172 return (1);
173end:
174 return (0);
175}
176
177int convbool(PyObject *o, void *pp)
178{
179 *(int *)pp = PyObject_IsTrue(o);
180 return (1);
181}
182
183/*----- Type messing ------------------------------------------------------*/
184
185static const PyTypeObject emptytype = { 0 };
186
187void *newtype(PyTypeObject *metaty,
188 const PyTypeObject *skel,
189 const char *name)
190{
191 PyHeapTypeObject *ty =
192 (PyHeapTypeObject *)_PyObject_GC_Malloc(_PyObject_VAR_SIZE(metaty, 0));
193 if (!skel) skel = &emptytype;
194 memcpy(ty, skel, sizeof(*skel));
d4a9e7e7 195 if (ty->ht_type.tp_base) Py_INCREF(ty->ht_type.tp_base);
68ec53f3 196#define COPY(blah) do { \
d4a9e7e7 197 if (ty->ht_type.tp_as_##blah) { \
68ec53f3 198 memcpy(&ty->as_##blah, \
d4a9e7e7 199 ty->ht_type.tp_as_##blah, \
68ec53f3 200 sizeof(ty->as_##blah)); \
d4a9e7e7 201 ty->ht_type.tp_as_##blah = &ty->as_##blah; \
68ec53f3
MW
202 } \
203 } while (0)
204 COPY(number);
205 COPY(sequence);
206 COPY(mapping);
207 COPY(buffer);
208#undef COPY
209 if (name)
d4a9e7e7
MW
210 ty->ht_name = PyString_FromString(name);
211 else if (ty->ht_type.tp_name)
212 ty->ht_name = PyString_FromString(ty->ht_type.tp_name);
213 if (ty->ht_name)
214 ty->ht_type.tp_name = PyString_AS_STRING(ty->ht_name);
f60b520f 215 DISCARD(PyObject_INIT(&ty->ht_type, metaty));
68ec53f3
MW
216 Py_INCREF(metaty);
217 return (ty);
218}
219
0156e402
MW
220void typeready(PyTypeObject *ty)
221{
222 PyType_Ready(ty);
223 PyDict_SetItemString(ty->tp_dict, "__module__", modname);
224}
225
68ec53f3
MW
226PyTypeObject *inittype(PyTypeObject *tyskel)
227{
228 PyTypeObject *ty = newtype(&PyType_Type, tyskel, 0);
229 ty->tp_flags |= Py_TPFLAGS_HEAPTYPE;
0156e402 230 typeready(ty);
68ec53f3
MW
231 return (ty);
232}
233
234/*----- Constants ---------------------------------------------------------*/
235
236void setconstants(PyObject *mod, const struct nameval *c)
237{
238 PyObject *x;
239
240 while (c->name) {
241 if (c->value > LONG_MAX)
242 x = PyLong_FromUnsignedLong(c->value);
243 else
244 x = PyInt_FromLong(c->value);
245 PyModule_AddObject(mod, (/*unconst*/ char *)c->name, x);
246 c++;
247 }
248}
249
250/*----- Building method tables --------------------------------------------*/
251
252DA_DECL(method_v, PyMethodDef);
253static method_v global_pymethods = DA_INIT;
254void addmethods(const PyMethodDef *m)
255{
256 size_t n;
257
258 for (n = 0; m[n].ml_name; n++);
259 DA_ENSURE(&global_pymethods, n);
260 memcpy(DA(&global_pymethods) + DA_LEN(&global_pymethods),
261 m, n * sizeof(*m));
262 DA_EXTEND(&global_pymethods, n);
263}
264
265PyMethodDef *donemethods(void)
266{
267 static const PyMethodDef mzero = { 0 };
268 DA_PUSH(&global_pymethods, mzero);
269 return (DA(&global_pymethods));
270}
271
272/*----- Exceptions --------------------------------------------------------*/
273
35c34efb
MW
274PyObject *mkexc(PyObject *mod, PyObject *base,
275 const char *name, PyMethodDef *mm)
68ec53f3
MW
276{
277 PyObject *nameobj = 0;
278 PyObject *dict = 0;
279 PyObject *exc = 0;
280 PyObject *func = 0;
281 PyObject *meth = 0;
282
283 if ((nameobj = PyString_FromFormat("%s.%s",
284 PyModule_GetName(mod),
285 name)) == 0 ||
286 (dict = PyDict_New()) == 0 ||
287 (exc = PyErr_NewException(PyString_AS_STRING(nameobj),
288 base, dict)) == 0)
289 goto fail;
290
291 if (mm) {
292 while (mm->ml_name) {
293 if ((func = PyCFunction_NewEx(mm, 0, mod)) == 0 ||
294 (meth = PyMethod_New(func, 0, exc)) == 0 ||
295 PyDict_SetItemString(dict, mm->ml_name, meth))
296 goto fail;
297 Py_DECREF(func); func = 0;
298 Py_DECREF(meth); meth = 0;
299 mm++;
300 }
301 }
302
303done:
304 Py_XDECREF(nameobj);
305 Py_XDECREF(dict);
306 return (exc);
307
308fail:
309 Py_XDECREF(exc);
310 Py_XDECREF(func);
311 Py_XDECREF(meth);
312 exc = 0;
313 goto done;
314}
315
316/*----- Generic dictionary methods ----------------------------------------*/
317
318static PyTypeObject *itemiter_pytype, *valiter_pytype;
319
320typedef struct iter_pyobj {
321 PyObject_HEAD
322 PyObject *map;
323 PyObject *i;
324} iter_pyobj;
325#define ITER_MAP(o) (((iter_pyobj *)(o))->map)
326#define ITER_I(o) (((iter_pyobj *)(o))->i)
327
328static void iter_pydealloc(PyObject *me)
329 { Py_DECREF(ITER_MAP(me)); Py_DECREF(ITER_I(me)); FREEOBJ(me); }
330
331static PyObject *itemiter_pynext(PyObject *me)
332{
333 PyObject *k = 0, *v = 0, *rc = 0;
0b1eafbf 334
68ec53f3
MW
335 if ((k = PyIter_Next(ITER_I(me))) != 0 &&
336 (v = PyObject_GetItem(ITER_MAP(me), k)) != 0)
337 rc = Py_BuildValue("(OO)", k, v);
338 Py_XDECREF(k); Py_XDECREF(v);
339 return (rc);
340}
341
342static PyTypeObject itemiter_pytype_skel = {
343 PyObject_HEAD_INIT(0) 0, /* Header */
344 "ItemIter", /* @tp_name@ */
345 sizeof(iter_pyobj), /* @tp_basicsize@ */
346 0, /* @tp_itemsize@ */
347
348 iter_pydealloc, /* @tp_dealloc@ */
349 0, /* @tp_print@ */
350 0, /* @tp_getattr@ */
351 0, /* @tp_setattr@ */
352 0, /* @tp_compare@ */
353 0, /* @tp_repr@ */
354 0, /* @tp_as_number@ */
355 0, /* @tp_as_sequence@ */
356 0, /* @tp_as_mapping@ */
357 0, /* @tp_hash@ */
358 0, /* @tp_call@ */
359 0, /* @tp_str@ */
360 0, /* @tp_getattro@ */
361 0, /* @tp_setattro@ */
362 0, /* @tp_as_buffer@ */
363 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
364 Py_TPFLAGS_BASETYPE,
365
366 /* @tp_doc@ */
367"Iterates over the items of a mapping.",
368
369 0, /* @tp_traverse@ */
370 0, /* @tp_clear@ */
371 0, /* @tp_richcompare@ */
372 0, /* @tp_weaklistoffset@ */
373 PyObject_SelfIter, /* @tp_iter@ */
374 itemiter_pynext, /* @tp_iternext@ */
375 0, /* @tp_methods@ */
376 0, /* @tp_members@ */
377 0, /* @tp_getset@ */
378 0, /* @tp_base@ */
379 0, /* @tp_dict@ */
380 0, /* @tp_descr_get@ */
381 0, /* @tp_descr_set@ */
382 0, /* @tp_dictoffset@ */
383 0, /* @tp_init@ */
384 PyType_GenericAlloc, /* @tp_alloc@ */
385 abstract_pynew, /* @tp_new@ */
386 0, /* @tp_free@ */
387 0 /* @tp_is_gc@ */
388};
389
390static PyObject *valiter_pynext(PyObject *me)
391{
392 PyObject *k = 0, *rc = 0;
0b1eafbf 393
68ec53f3
MW
394 if ((k = PyIter_Next(ITER_I(me))) != 0)
395 rc = PyObject_GetItem(ITER_MAP(me), k);
396 Py_XDECREF(k);
397 return (rc);
398}
399
400static PyTypeObject valiter_pytype_skel = {
401 PyObject_HEAD_INIT(0) 0, /* Header */
402 "ValueIter", /* @tp_name@ */
403 sizeof(iter_pyobj), /* @tp_basicsize@ */
404 0, /* @tp_itemsize@ */
405
406 iter_pydealloc, /* @tp_dealloc@ */
407 0, /* @tp_print@ */
408 0, /* @tp_getattr@ */
409 0, /* @tp_setattr@ */
410 0, /* @tp_compare@ */
411 0, /* @tp_repr@ */
412 0, /* @tp_as_number@ */
413 0, /* @tp_as_sequence@ */
414 0, /* @tp_as_mapping@ */
415 0, /* @tp_hash@ */
416 0, /* @tp_call@ */
417 0, /* @tp_str@ */
418 0, /* @tp_getattro@ */
419 0, /* @tp_setattro@ */
420 0, /* @tp_as_buffer@ */
421 Py_TPFLAGS_DEFAULT | /* @tp_flags@ */
422 Py_TPFLAGS_BASETYPE,
423
424 /* @tp_doc@ */
425"Iterates over the items of a mapping.",
426
427 0, /* @tp_traverse@ */
428 0, /* @tp_clear@ */
429 0, /* @tp_richcompare@ */
430 0, /* @tp_weaklistoffset@ */
431 PyObject_SelfIter, /* @tp_iter@ */
432 valiter_pynext, /* @tp_iternext@ */
433 0, /* @tp_methods@ */
434 0, /* @tp_members@ */
435 0, /* @tp_getset@ */
436 0, /* @tp_base@ */
437 0, /* @tp_dict@ */
438 0, /* @tp_descr_get@ */
439 0, /* @tp_descr_set@ */
440 0, /* @tp_dictoffset@ */
441 0, /* @tp_init@ */
442 PyType_GenericAlloc, /* @tp_alloc@ */
443 abstract_pynew, /* @tp_new@ */
444 0, /* @tp_free@ */
445 0 /* @tp_is_gc@ */
446};
447
448PySequenceMethods gmap_pysequence = {
449 0, /* @sq_length@ */
450 0, /* @sq_concat@ */
451 0, /* @sq_repeat@ */
452 0, /* @sq_item@ */
453 0, /* @sq_slice@ */
454 0, /* @sq_ass_item@ */
455 0, /* @sq_ass_slice@ */
456 PyMapping_HasKey, /* @sq_contains@ */
457 0, /* @sq_inplace_concat@ */
458 0 /* @sq_inplace_repeat@ */
0b1eafbf 459};
68ec53f3 460
9d73ed80 461Py_ssize_t gmap_pysize(PyObject *me)
68ec53f3
MW
462{
463 PyObject *i = 0, *x = 0;
464 int rc = -1;
465 int n = 0;
466
467 if ((i = PyObject_GetIter(me)) == 0) goto done;
468 while ((x = PyIter_Next(i)) != 0) { n++; Py_DECREF(x); x = 0; }
469 if (PyErr_Occurred()) goto done;
470 rc = n;
471done:
472 Py_XDECREF(i); Py_XDECREF(x);
473 return (rc);
474}
475
476PyObject *gmapmeth_has_key(PyObject *me, PyObject *arg)
477{
478 PyObject *k;
479 if (!PyArg_ParseTuple(arg, "O:has_key", &k)) return (0);
480 return (getbool(PyMapping_HasKey(me, k)));
481}
482
483PyObject *gmapmeth_keys(PyObject *me, PyObject *arg)
484{
485 PyObject *l = 0, *i = 0, *k, *rc = 0;
486 int err;
487
488 if (!PyArg_ParseTuple(arg, ":keys") ||
489 (l = PyList_New(0)) == 0 ||
490 (i = PyObject_GetIter(me)) == 0)
491 goto done;
492 while ((k = PyIter_Next(i)) != 0)
493 { err = PyList_Append(l, k); Py_DECREF(k); if (err) goto done; }
494 if (PyErr_Occurred()) goto done;
495 rc = l; l = 0;
496done:
497 Py_XDECREF(l); Py_XDECREF(i);
498 return (rc);
499}
500
501PyObject *gmapmeth_values(PyObject *me, PyObject *arg)
502{
503 PyObject *l = 0, *i = 0, *k, *v, *rc = 0;
504 int err = 0;
505
506 if (!PyArg_ParseTuple(arg, ":values") ||
507 (l = PyList_New(0)) == 0 ||
508 (i = PyObject_GetIter(me)) == 0)
509 goto done;
0b1eafbf 510 while ((k = PyIter_Next(i)) != 0) {
68ec53f3
MW
511 if ((v = PyObject_GetItem(me, k)) == 0 ||
512 PyList_Append(l, v))
513 err = -1;
514 Py_DECREF(k); Py_XDECREF(v);
515 if (err) goto done;
516 }
517 if (PyErr_Occurred()) goto done;
518 rc = l; l = 0;
519done:
520 Py_XDECREF(l); Py_XDECREF(i);
521 return (rc);
522}
523
524PyObject *gmapmeth_items(PyObject *me, PyObject *arg)
525{
526 PyObject *l = 0, *i = 0, *k, *v, *z, *rc = 0;
527 int err = 0;
528
529 if (!PyArg_ParseTuple(arg, ":items") ||
530 (l = PyList_New(0)) == 0 ||
531 (i = PyObject_GetIter(me)) == 0)
532 goto done;
533 while ((k = PyIter_Next(i)) != 0) {
534 z = 0;
535 if ((v = PyObject_GetItem(me, k)) == 0 ||
536 (z = Py_BuildValue("(OO)", k, v)) == 0 ||
537 PyList_Append(l, z))
538 err = -1;
539 Py_DECREF(k); Py_XDECREF(v); Py_XDECREF(z);
540 if (err) goto done;
541 }
542 if (PyErr_Occurred()) goto done;
543 rc = l; l = 0;
544done:
545 Py_XDECREF(l); Py_XDECREF(i);
546 return (rc);
547}
548
549PyObject *gmapmeth_iterkeys(PyObject *me, PyObject *arg)
550{
551 if (!PyArg_ParseTuple(arg, ":iterkeys")) return (0);
552 return (PyObject_GetIter(me));
553}
554
555PyObject *gmapmeth_itervalues(PyObject *me, PyObject *arg)
556{
557 PyObject *i;
558 iter_pyobj *ii;
559
560 if (!PyArg_ParseTuple(arg, ":itervalues") ||
561 (i = PyObject_GetIter(me)) == 0)
562 return (0);
563 ii = PyObject_NEW(iter_pyobj, valiter_pytype);
564 ii->map = me; Py_INCREF(me);
565 ii->i = i;
566 return ((PyObject *)ii);
567}
568
569PyObject *gmapmeth_iteritems(PyObject *me, PyObject *arg)
570{
571 PyObject *i;
572 iter_pyobj *ii;
573
574 if (!PyArg_ParseTuple(arg, ":iteritems") ||
575 (i = PyObject_GetIter(me)) == 0)
576 return (0);
577 ii = PyObject_NEW(iter_pyobj, itemiter_pytype);
578 ii->map = me; Py_INCREF(me);
579 ii->i = i;
580 return ((PyObject *)ii);
581}
582
583PyObject *gmapmeth_clear(PyObject *me, PyObject *arg)
584{
585 PyObject *i = 0, *k = 0, *rc = 0;
586
587 if (!PyArg_ParseTuple(arg, ":clear") ||
588 (i = PyObject_GetIter(me)) == 0)
589 goto end;
590 while ((k = PyIter_Next(i)) != 0) {
591 PyObject_DelItem(me, k);
592 Py_DECREF(k);
593 }
594 if (PyErr_Occurred()) goto end;
595 rc = me; Py_INCREF(me);
596end:
597 Py_XDECREF(i);
598 return (rc);
599}
600
601static char *def_kwlist[] = { "key", "default", 0 };
602
603PyObject *gmapmeth_get(PyObject *me, PyObject *arg, PyObject *kw)
604{
605 PyObject *k, *def = Py_None, *v;
606
607 if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO:get", def_kwlist, &k, &def))
608 return (0);
609 if ((v = PyObject_GetItem(me, k)) != 0) return (v);
610 PyErr_Clear();
611 RETURN_OBJ(def);
612}
613
614PyObject *gmapmeth_setdefault(PyObject *me, PyObject *arg, PyObject *kw)
615{
616 PyObject *k, *def = Py_None, *v;
617
618 if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO:setdefault",
619 def_kwlist, &k, &def))
620 return (0);
621 if ((v = PyObject_GetItem(me, k)) != 0) return (v);
622 PyErr_Clear();
623 if (PyObject_SetItem(me, k, def)) return (0);
624 RETURN_OBJ(def);
625}
626
627PyObject *gmapmeth_pop(PyObject *me, PyObject *arg, PyObject *kw)
628{
629 PyObject *k, *def = 0, *v;
630
631 if (!PyArg_ParseTupleAndKeywords(arg, kw, "OO:pop", def_kwlist, &k, &def))
632 return (0);
633 if ((v = PyObject_GetItem(me, k)) != 0) {
634 PyObject_DelItem(me, k);
635 return (v);
636 }
637 PyErr_Clear();
638 RETURN_OBJ(def);
639}
640
641PyObject *gmapmeth_update(PyObject *me, PyObject *arg)
642{
643 PyObject *map, *i = 0, *k, *v, *rc = 0;
644 int err = 0;
645
646 if (!PyArg_ParseTuple(arg, "O:update", &map) ||
647 (i = PyObject_GetIter(map)) == 0)
648 goto end;
649 while ((k = PyIter_Next(i)) != 0) {
650 if ((v = PyObject_GetItem(map, k)) == 0 ||
651 PyObject_SetItem(me, k, v))
652 err = -1;
653 Py_DECREF(k); Py_XDECREF(v);
654 if (err) goto end;
655 }
656 if (PyErr_Occurred()) goto end;
657 rc = me; Py_INCREF(me);
658end:
659 Py_XDECREF(i);
660 return (rc);
661}
662
663PyObject *gmapmeth_popitem(PyObject *me, PyObject *arg)
664{
665 PyObject *i = 0, *k = 0, *v = 0, *rc = 0;
666
667 if (!PyArg_ParseTuple(arg, ":popitem") ||
668 (i = PyObject_GetIter(me)))
669 goto end;
670 if ((k = PyIter_Next(i)) == 0) {
671 if (!PyErr_Occurred()) VALERR("popitem(): mapping is empty");
672 goto end;
673 }
674 if ((v = PyObject_GetItem(me, k)) == 0 ||
675 PyObject_DelItem(me, k))
676 goto end;
677 rc = Py_BuildValue("(OO)", k, v);
678end:
679 Py_XDECREF(i); Py_XDECREF(k); Py_XDECREF(v);
680 return (rc);
681}
682
683PyMethodDef gmap_pymethods[] = {
684 GMAP_METHODS
685 { 0 }
686};
687
688/*----- Initialization ----------------------------------------------------*/
689
8ca23175 690void util_pyinit(void)
68ec53f3 691{
0156e402 692 modname = PyString_FromString("catacomb");
68ec53f3
MW
693 INITTYPE(itemiter, root);
694 INITTYPE(valiter, root);
695}
696
8ca23175 697void util_pyinsert(PyObject *mod)
68ec53f3
MW
698{
699 INSERT("ItemIter", itemiter_pytype);
700 INSERT("ValueIter", valiter_pytype);
701}
702
703/*----- That's all, folks -------------------------------------------------*/