20bce5e9 |
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 ---------------------------------------------------- |