Initial import.
[mLib-python] / atom.pyx
CommitLineData
20bce5e9 1# -*-pyrex-*-
2#
3# $Id$
4#
5# Atom tables
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
28cdef extern from 'atom.h':
29 ctypedef struct atom:
30 pass
31 ctypedef struct atom_iter:
32 pass
33 ctypedef struct atom_table:
34 pass
35 atom_table *ATOM_GLOBAL
36 void atom_mkiter(atom_iter *i, atom_table *t)
37 atom *atom_next(atom_iter *)
38 atom_pystartup()
39 atom_pywrap(atom *a)
40 atom_pyintern(obj)
41 atom *ATOM_A(obj)
42
43cdef extern from 'mLib/assoc.h':
44 ctypedef struct assoc_table:
45 pass
46 ctypedef struct assoc_base:
47 pass
48 ctypedef struct assoc_iter:
49 pass
50 void assoc_create(assoc_table *t)
51 void assoc_destroy(assoc_table *t)
52 void *assoc_find(assoc_table *t, atom *a, int sz, unsigned *f)
53 void assoc_remove(assoc_table *t, void *b)
54 atom *ASSOC_ATOM(void *b)
55 void assoc_mkiter(assoc_iter *i, assoc_table *t)
56 void *assoc_next(assoc_iter *i)
57
58cdef extern from 'grim.h':
59 int PSIZEOF(void *p)
60
61cdef extern from 'Python.h':
62 int PyObject_AsReadBuffer(obj, void **buf, int *len) except -1
63 PyString_FromStringAndSize(char *p, int n)
64 ctypedef struct PyObject:
65 pass
66 void Py_INCREF(PyObject *obj)
67 void Py_DECREF(PyObject *obj)
68
69cdef class AtomIter:
70 cdef atom_iter _i
71 def __new__(me):
72 atom_mkiter(&me._i, ATOM_GLOBAL)
73 def __next__(me):
74 cdef atom *a
75 a = atom_next(&me._i)
76 if not a:
77 raise StopIteration
78 return atom_pywrap(a)
79 def __iter__(me):
80 return me
81
82def atoms():
83 return AtomIter()
84
85cdef struct entry:
86 assoc_base _b
87 PyObject *v
88
89cdef entry *_find(assoc_table *t, object key, unsigned *f) except ?NULL:
90 cdef void *p
91 cdef int n
92 cdef entry *e
93 cdef atom *a
94 a = ATOM_A(atom_pyintern(key))
95 if f:
96 f[0] = 0
97 e = <entry *>assoc_find(t, a, PSIZEOF(e), f)
98 if not f[0]:
99 e.v = NULL
100 else:
101 e = <entry *>assoc_find(t, a, 0, NULL)
102 return e
103
104cdef _key(entry *e):
105 return atom_pywrap(ASSOC_ATOM(<void *>e))
106
107cdef _eget(entry *e):
108 Py_INCREF(e.v)
109 return <object>e.v
110
111cdef void _eset(entry *e, v):
112 if e.v:
113 Py_DECREF(e.v)
114 e.v = <PyObject *>v
115 Py_INCREF(e.v)
116
117cdef void _edel(assoc_table *t, entry *e):
118 if e.v:
119 Py_DECREF(e.v)
120 assoc_remove(t, <void *>e)
121
122cdef class Table:
123 cdef assoc_table _t
124 def __new__(me, *hunoz, **hukairz):
125 assoc_create(&me._t)
126 def __init__(me, stuff = None, **kw):
127 me.update(stuff, **kw)
128 def __getitem__(me, key):
129 cdef entry *e
130 e = _find(&me._t, key, NULL)
131 if not e:
132 raise KeyError, key
133 return _eget(e)
134 def __setitem__(me, key, value):
135 cdef unsigned f
136 _eset(_find(&me._t, key, &f), value)
137 def __delitem__(me, key):
138 cdef entry *e
139 cdef unsigned f
140 e = _find(&me._t, key, &f)
141 if not e:
142 raise KeyError, key
143 _edel(&me._t, e)
144 def get(me, key, default = None):
145 cdef entry *e
146 e = _find(&me._t, key, NULL)
147 if not e:
148 return default
149 return _eget(e)
150 def setdefault(me, key, default = None):
151 cdef entry *e
152 cdef unsigned f
153 e = _find(&me._t, key, &f)
154 if f:
155 return _eget(e)
156 else:
157 _eset(e, default)
158 return default
159 def pop(me, key, default = None):
160 cdef entry *e
161 e = _find(&me._t, key, NULL)
162 if not e:
163 return default
164 rc = _eget(e)
165 _edel(&me._t, e)
166 return rc
167 def popitem(me):
168 cdef entry *e
169 cdef assoc_iter i
170 assoc_mkiter(&i, &me._t)
171 e = <entry *>assoc_next(&i)
172 if not e:
173 raise ValueError, 'popitem(): table is empty'
174 return _key(e), _eget(e)
175 def keys(me):
176 cdef assoc_iter i
177 cdef entry *e
178 l = []
179 assoc_mkiter(&i, &me._t)
180 while 1:
181 e = <entry *>assoc_next(&i)
182 if not e:
183 break
184 l.append(_key(e))
185 return l
186 def values(me):
187 cdef assoc_iter i
188 cdef entry *e
189 l = []
190 assoc_mkiter(&i, &me._t)
191 while 1:
192 e = <entry *>assoc_next(&i)
193 if not e:
194 break
195 l.append(_eget(e))
196 return l
197 def items(me):
198 cdef assoc_iter i
199 cdef entry *e
200 l = []
201 assoc_mkiter(&i, &me._t)
202 while 1:
203 e = <entry *>assoc_next(&i)
204 if not e:
205 break
206 l.append((_key(e), _eget(e)))
207 return l
208 def clear(me):
209 cdef assoc_iter i
210 cdef entry *e
211 assoc_mkiter(&i, &me._t)
212 while 1:
213 e = <entry *>assoc_next(&i)
214 if not e:
215 break
216 _edel(&me._t, e)
217 return me
218 def __dealloc__(me):
219 cdef assoc_iter i
220 cdef entry *e
221 assoc_mkiter(&i, &me._t)
222 while 1:
223 e = <entry *>assoc_next(&i)
224 if not e:
225 break
226 _edel(&me._t, e)
227 assoc_destroy(&me._t)
228 def iterkeys(me):
229 return KeyIter(me)
230 def __iter__(me):
231 return KeyIter(me)
232 def itervalues(me):
233 return ValueIter(me)
234 def iteritems(me):
235 return ItemIter(me)
236 def update(me, stuff = None, **kw):
237 if stuff is None:
238 pass
239 elif hasattr(stuff, 'keys'):
240 for k in stuff:
241 me[k] = stuff[k]
242 else:
243 for k, v in stuff:
244 me[k] = v
245 for k, v in kw.iteritems():
246 me[k] = kw[k]
247 return me
248
249cdef class KeyIter:
250 cdef Table _t
251 cdef assoc_iter _i
252 def __new__(me, Table t):
253 me._t = t
254 assoc_mkiter(&me._i, &t._t)
255 def __iter__(me):
256 return me
257 def __next__(me):
258 cdef entry *e
259 e = <entry *>assoc_next(&me._i)
260 if not e:
261 raise StopIteration
262 return _key(e)
263
264cdef class ValueIter:
265 cdef Table _t
266 cdef assoc_iter _i
267 def __new__(me, Table t):
268 me._t = t
269 assoc_mkiter(&me._i, &t._t)
270 def __iter__(me):
271 return me
272 def __next__(me):
273 cdef entry *e
274 e = <entry *>assoc_next(&me._i)
275 if not e:
276 raise StopIteration
277 return _eget(e)
278
279cdef class ItemIter:
280 cdef Table _t
281 cdef assoc_iter _i
282 def __new__(me, Table t):
283 me._t = t
284 assoc_mkiter(&me._i, &t._t)
285 def __iter__(me):
286 return me
287 def __next__(me):
288 cdef entry *e
289 e = <entry *>assoc_next(&me._i)
290 if not e:
291 raise StopIteration
292 return _key(e), _eget(e)
293
294Atom = atom_pystartup()
295
296#----- That's all, folks ----------------------------------------------------