chiark / gitweb /
Initial import.
[mLib-python] / sym.pyx
1 # -*-pyrex-*-
2 #
3 # $Id$
4 #
5 # Symbol table, using universal hashing
6 #
7 # (c) 2005 Straylight/Edgeware
8 #
9
10 #----- Licensing notice -----------------------------------------------------
11 #
12 # This file is part of the Python interface to mLib.
13 #
14 # mLib/Python is free software; you can redistribute it and/or modify
15 # it under the terms of the GNU General Public License as published by
16 # the Free Software Foundation; either version 2 of the License, or
17 # (at your option) any later version.
18
19 # mLib/Python is distributed in the hope that it will be useful,
20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 # GNU General Public License for more details.
23
24 # You should have received a copy of the GNU General Public License
25 # along with mLib/Python; if not, write to the Free Software Foundation,
26 # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27
28 cdef extern from 'mLib/sym.h':
29   ctypedef struct sym_table:
30     pass
31   ctypedef struct sym_base:
32     pass
33   ctypedef struct sym_iter:
34     pass
35   void sym_create(sym_table *t)
36   void sym_destroy(sym_table *t)
37   void *sym_find(sym_table *t, char *n, long l, int sz, unsigned *f)
38   void sym_remove(sym_table *t, void *b)
39   char *SYM_NAME(void *b)
40   int SYM_LEN(void *b)
41   void sym_mkiter(sym_iter *i, sym_table *t)
42   void *sym_next(sym_iter *i)
43
44 cdef extern from 'grim.h':
45   int PSIZEOF(void *p)
46
47 cdef extern from 'Python.h':
48   int PyObject_AsReadBuffer(obj, void **buf, int *len) except -1
49   PyString_FromStringAndSize(char *p, int n)
50   ctypedef struct PyObject:
51     pass
52   void Py_INCREF(PyObject *obj)
53   void Py_DECREF(PyObject *obj)
54
55 cdef struct entry:
56   sym_base _b
57   PyObject *v
58
59 cdef entry *_find(sym_table *t, object k, unsigned *f) except ?NULL:
60   cdef void *p
61   cdef int n
62   cdef entry *e
63   PyObject_AsReadBuffer(key, &p, &n)
64   if f:
65     f[0] = 0
66     e = <entry *>sym_find(t, <char *>p, n, PSIZEOF(e), f)
67     if not f[0]:
68       e.v = NULL
69   else:
70     e = <entry *>sym_find(t, <char *>p, n, 0, NULL)
71   return e
72
73 cdef _eget(entry *e):
74   Py_INCREF(e.v)
75   return <object>e.v
76
77 cdef void _eset(entry *e, v):
78   if e.v:
79     Py_DECREF(e.v)
80   e.v = <PyObject *>v
81   Py_INCREF(e.v)
82
83 cdef void _edel(sym_table *t, entry *e):
84   if e.v:
85     Py_DECREF(e.v)
86   sym_remove(t, <void *>e)
87
88 cdef _key(entry *e):
89   return PyString_FromStringAndSize(SYM_NAME(<void *>e), SYM_LEN(<void *>e))
90
91 cdef class Table:
92   cdef sym_table _t
93   def __new__(me, *hunoz, **hukairz):
94     sym_create(&me._t)
95   def __init__(me, stuff = None, **kw):
96     me.update(stuff, kw)
97   def __getitem__(me, key):
98     cdef entry *e
99     e = _find(&me._t, key, NULL)
100     if not e:
101       raise KeyError, key
102     return _eget(e)
103   def __setitem__(me, key, value):
104     cdef unsigned f
105     _eset(_find(&me._t, key, &f), value)
106   def __delitem__(me, key):
107     cdef entry *e
108     cdef unsigned f
109     e = _find(&me._t, key, &f)
110     if not e:
111       raise KeyError, key
112     _edel(&me._t, e)
113   def get(me, key, default = None):
114     cdef entry *e
115     e = _find(&me._t, key, NULL)
116     if not e:
117       return default
118     return _eget(e)
119   def setdefault(me, key, default = None):
120     cdef entry *e
121     cdef unsigned f
122     e = _find(&me._t, key, &f)
123     if f:
124       return _eget(e)
125     else:
126       _eset(e, default)
127       return default
128   def pop(me, key, default = None):
129     cdef entry *e
130     e = _find(&me._t, key, NULL)
131     if not e:
132       return default
133     rc = _eget(e)
134     _edel(&me._t, e)
135     return rc
136   def popitem(me):
137     cdef entry *e
138     cdef sym_iter i
139     sym_mkiter(&i, &me._t)
140     e = <entry *>sym_next(&i)
141     if not e:
142       raise ValueError, 'popitem(): table is empty'
143     return _key(e), _eget(e)
144   def keys(me):
145     cdef sym_iter i
146     cdef entry *e
147     l = []
148     sym_mkiter(&i, &me._t)
149     while 1:
150       e = <entry *>sym_next(&i)
151       if not e:
152         break
153       l.append(_key(e))
154     return l
155   def values(me):
156     cdef sym_iter i
157     cdef entry *e
158     l = []
159     sym_mkiter(&i, &me._t)
160     while 1:
161       e = <entry *>sym_next(&i)
162       if not e:
163         break
164       l.append(_eget(e))
165     return l
166   def items(me):
167     cdef sym_iter i
168     cdef entry *e
169     l = []
170     sym_mkiter(&i, &me._t)
171     while 1:
172       e = <entry *>sym_next(&i)
173       if not e:
174         break
175       l.append((_key(e), _eget(e)))
176     return l
177   def clear(me):
178     cdef sym_iter i
179     cdef entry *e
180     sym_mkiter(&i, &me._t)
181     while 1:
182       e = <entry *>sym_next(&i)
183       if not e:
184         break
185       _edel(&me._t, e)
186     return me
187   def __dealloc__(me):
188     cdef sym_iter i
189     cdef entry *e
190     sym_mkiter(&i, &me._t)
191     while 1:
192       e = <entry *>sym_next(&i)
193       if not e:
194         break
195       _edel(&me._t, e)
196     sym_destroy(&me._t)
197   def iterkeys(me):
198     return KeyIter(me)
199   def __iter__(me):
200     return KeyIter(me)
201   def itervalues(me):
202     return ValueIter(me)
203   def iteritems(me):
204     return ItemIter(me)
205   def update(me, stuff = None, **kw):
206     cdef unsigned f
207     if stuff is None:
208       pass
209     elif hasattr(stuff, 'itemiter'):
210       for k, v in stuff.itemiter:
211         _eset(_find(&me._t, k, &f), v)
212     elif hasattr(stuff, 'keys'):
213       for k in stuff.keys():
214         _eset(_find(&me._t, k, &f), stuff[k])
215     else:
216       for k, v in stuff:
217         _eset(_find(&me._t, k, &f), v)
218     for k, v in kw.iteritems():
219       _eset(_find(&me._t, k, &f), v)
220     return me
221
222 cdef class KeyIter:
223   cdef Table _t
224   cdef sym_iter _i
225   def __new__(me, Table t):
226     me._t = t
227     sym_mkiter(&me._i, &t._t)
228   def __iter__(me):
229     return me
230   def __next__(me):
231     cdef entry *e
232     e = <entry *>sym_next(&me._i)
233     if not e:
234       raise StopIteration
235     return _key(e)
236
237 cdef class ValueIter:
238   cdef Table _t
239   cdef sym_iter _i
240   def __new__(me, Table t):
241     me._t = t
242     sym_mkiter(&me._i, &t._t)
243   def __iter__(me):
244     return me
245   def __next__(me):
246     cdef entry *e
247     e = <entry *>sym_next(&me._i)
248     if not e:
249       raise StopIteration
250     return _eget(e)
251
252 cdef class ItemIter:
253   cdef Table _t
254   cdef sym_iter _i
255   def __new__(me, Table t):
256     me._t = t
257     sym_mkiter(&me._i, &t._t)
258   def __iter__(me):
259     return me
260   def __next__(me):
261     cdef entry *e
262     e = <entry *>sym_next(&me._i)
263     if not e:
264       raise StopIteration
265     return _key(e), _eget(e)
266
267 #----- That's all, folks ----------------------------------------------------