--- /dev/null
+# -*-pyrex-*-
+#
+# $Id$
+#
+# Common mapping stuff
+#
+# (c) 2005 Straylight/Edgeware
+#
+
+#----- Licensing notice -----------------------------------------------------
+#
+# This file is part of the Python interface to mLib.
+#
+# mLib/Python is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# mLib/Python is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with mLib/Python; if not, write to the Free Software Foundation,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+cdef class Mapping
+
+cdef class _MapIterator:
+ cdef void *_next(me):
+ return NULL
+
+cdef class Mapping:
+
+ ## Subclasses must implement these
+ cdef int _init(me) except -1:
+ raise TypeError, 'abstract class'
+ cdef void *_find(me, object key, unsigned *f) except NULL:
+ raise SystemError, 'unimplemented _find'
+ cdef object _key(me, void *e):
+ return None
+ cdef object _value(me, void *e):
+ return None
+ cdef void _setval(me, void *e, object val):
+ pass
+ cdef void _del(me, void *e):
+ pass
+ cdef _MapIterator _iter(me):
+ raise SystemError, 'unimplemented _iter'
+
+ ## Initialization
+ def __new__(me, *hunoz, **hukairz):
+ me._init()
+ def __init__(me, stuff = None, **kw):
+ me.update(stuff, kw)
+
+ ## Bulk update
+ def update(me, stuff = None, **kw):
+ cdef unsigned f
+ if stuff is None:
+ pass
+ elif hasattr(stuff, 'itemiter'):
+ for k, v in stuff.itemiter:
+ me._setval(me._find(k, &f), v)
+ elif hasattr(stuff, 'keys'):
+ for k in stuff.keys():
+ me._setval(me._find( k, &f), stuff[k])
+ else:
+ for k, v in stuff:
+ me._setval(me._find(k, &f), v)
+ for k, v in kw.iteritems():
+ me._setval(me._find(k, &f), v)
+ return me
+
+ ## Item access
+ def __getitem__(me, key):
+ cdef void *e
+ e = me._find(key, NULL)
+ if not e:
+ raise KeyError, key
+ return me._value(e)
+ def __setitem__(me, key, value):
+ cdef unsigned f
+ me._setval(me._find(key, &f), value)
+ def __delitem__(me, key):
+ cdef void *e
+ cdef unsigned f
+ e = me._find(key, &f)
+ if not e:
+ raise KeyError, key
+ me._del(e)
+ def get(me, key, default = None):
+ cdef void *e
+ e = me._find(key, NULL)
+ if not e:
+ return default
+ return me._value(e)
+ def setdefault(me, key, default = None):
+ cdef void *e
+ cdef unsigned f
+ e = me._find(key, &f)
+ if f:
+ return me._value(e)
+ else:
+ me._setval(e, default)
+ return default
+ def pop(me, key, default = None):
+ cdef void *e
+ e = me._find(key, NULL)
+ if not e:
+ return default
+ rc = me._value(e)
+ me._del(e)
+ return rc
+ def popitem(me):
+ cdef _MapIterator i
+ cdef void *e
+ i = me._iter()
+ e = i._next()
+ if not e:
+ raise ValueError, 'popitem(): table is empty'
+ return me._key(e), me._value(e)
+
+ ## Lists of items
+ cdef object _list(me, object (*func)(Mapping m, void *e)):
+ cdef _MapIterator i
+ cdef void *e
+ i = me._iter()
+ l = []
+ while 1:
+ e = i._next()
+ if not e:
+ break
+ l.append(func(me, e))
+ return l
+
+ def keys(me):
+ return me._list(_map_key)
+ def values(me):
+ return me._list(_map_value)
+ def items(me):
+ return me._list(_map_item)
+
+ def clear(me):
+ cdef _MapIterator i
+ cdef void *e
+ i = me._iter()
+ while 1:
+ e = i._next()
+ if not e:
+ break
+ me._del(e)
+ return me
+
+ ## Iteration
+ def __iter__(me):
+ return MapKeyIter(me)
+ def iterkeys(me):
+ return MapKeyIter(me)
+ def itervalues(me):
+ return MapValueIter(me)
+ def iteritems(me):
+ return MapItemIter(me)
+
+cdef class MapIterBase:
+ cdef Mapping m
+ cdef object (*func)(Mapping m, void *e)
+ cdef _MapIterator i
+ cdef int _init(me) except -1:
+ raise TypeError, 'abstract class'
+ def __new__(me):
+ me.i = m._iter()
+ me._init()
+ def __next__(me):
+ cdef void *e
+ e = me.i._next()
+ if not e:
+ raise StopIteration
+ return me.func(me.m, e)
+cdef class MapKeyIter (MapIterBase):
+ cdef int _init(me) except -1:
+ me.func = _map_key
+ return 0
+cdef class MapValueIter (MapIterBase):
+ cdef int _init(me) except -1:
+ me.func = _map_value
+ return 0
+cdef class MapItemIter (MapIterBase):
+ cdef int _init(me) except -1:
+ me.func = _map_item
+ return 0
+
+cdef object _map_key(Mapping m, void *e):
+ return m._key(e)
+cdef object _map_value(Mapping m, void *e):
+ return m._value(e)
+cdef object _map_item(Mapping m, void *e):
+ return m._key(e), m._value(e)
+
+#----- That's all, folks ----------------------------------------------------