General reorganization.
[mLib-python] / mapping.pyx
diff --git a/mapping.pyx b/mapping.pyx
new file mode 100644 (file)
index 0000000..aa5de85
--- /dev/null
@@ -0,0 +1,201 @@
+# -*-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 ----------------------------------------------------