blob: 021531c2b7f784a0fedc5c1798212e9ecf700237 [file] [log] [blame]
Guido van Rossum4b4c6641994-08-08 08:06:37 +00001/* GDBM module, hacked from the still-breathing corpse of the
2 DBM module by anthony.baxter@aaii.oz.au. Original copyright
3 follows:
4*/
5/***********************************************************
Guido van Rossum524b5881995-01-04 19:10:35 +00006Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
7The Netherlands.
Guido van Rossum4b4c6641994-08-08 08:06:37 +00008
9 All Rights Reserved
10
11Permission to use, copy, modify, and distribute this software and its
12documentation for any purpose and without fee is hereby granted,
13provided that the above copyright notice appear in all copies and that
14both that copyright notice and this permission notice appear in
15supporting documentation, and that the names of Stichting Mathematisch
16Centrum or CWI not be used in advertising or publicity pertaining to
17distribution of the software without specific, written prior permission.
18
19STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
20THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
21FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
22FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
23WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
24ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
25OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
26
27******************************************************************/
28
29/* DBM module using dictionary interface */
30
31
32#include "allobjects.h"
33#include "modsupport.h"
34
35#include <sys/types.h>
36#include <sys/stat.h>
37#include <fcntl.h>
38#include "gdbm.h"
39
40typedef struct {
41 OB_HEAD
42 int di_size; /* -1 means recompute */
43 GDBM_FILE di_dbm;
44} dbmobject;
45
46staticforward typeobject Dbmtype;
47
48#define is_dbmobject(v) ((v)->ob_type == &Dbmtype)
49
50static object *DbmError;
51
52static object *
53newdbmobject(file, flags, mode)
54 char *file;
55 int flags;
56 int mode;
57{
58 dbmobject *dp;
59
60 dp = NEWOBJ(dbmobject, &Dbmtype);
61 if (dp == NULL)
62 return NULL;
63 dp->di_size = -1;
Guido van Rossumb045afc1995-03-14 15:04:40 +000064 errno = 0;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000065 if ( (dp->di_dbm = gdbm_open(file, 0, flags, mode, NULL)) == 0 ) {
Guido van Rossumb045afc1995-03-14 15:04:40 +000066 if (errno != 0)
67 err_errno(DbmError);
68 else
69 err_setstr(DbmError, (char *) gdbm_strerror(gdbm_errno));
Guido van Rossum4b4c6641994-08-08 08:06:37 +000070 DECREF(dp);
Guido van Rossum807b7be1995-07-07 22:37:11 +000071 return NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000072 }
73 return (object *)dp;
74}
75
76/* Methods */
77
78static void
79dbm_dealloc(dp)
80 register dbmobject *dp;
81{
82 if ( dp->di_dbm )
83 gdbm_close(dp->di_dbm);
84 DEL(dp);
85}
86
87static int
88dbm_length(dp)
89 dbmobject *dp;
90{
91 if ( dp->di_size < 0 ) {
92 datum key,okey;
93 int size;
94 okey.dsize=0;
95
96 size = 0;
97 for ( key=gdbm_firstkey(dp->di_dbm); key.dptr;
98 key = gdbm_nextkey(dp->di_dbm,okey)) {
99 size++;
Sjoerd Mullender2abc4941994-10-13 09:11:13 +0000100 if(okey.dsize) free(okey.dptr);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000101 okey=key;
102 }
103 dp->di_size = size;
104 }
105 return dp->di_size;
106}
107
108static object *
109dbm_subscript(dp, key)
110 dbmobject *dp;
111 register object *key;
112{
113 object *v;
114 datum drec, krec;
115
116 if (!getargs(key, "s#", &krec.dptr, &krec.dsize) )
117 return NULL;
118
119 drec = gdbm_fetch(dp->di_dbm, krec);
120 if ( drec.dptr == 0 ) {
121 err_setstr(KeyError, GETSTRINGVALUE((stringobject *)key));
Guido van Rossum807b7be1995-07-07 22:37:11 +0000122 return NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000123 }
Guido van Rossumb045afc1995-03-14 15:04:40 +0000124 v = newsizedstringobject(drec.dptr, drec.dsize);
125 free(drec.dptr);
126 return v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000127}
128
129static int
130dbm_ass_sub(dp, v, w)
131 dbmobject *dp;
132 object *v, *w;
133{
134 datum krec, drec;
135
136 if ( !getargs(v, "s#", &krec.dptr, &krec.dsize) ) {
137 err_setstr(TypeError, "gdbm mappings have string indices only");
138 return -1;
139 }
140 dp->di_size = -1;
141 if (w == NULL) {
142 if ( gdbm_delete(dp->di_dbm, krec) < 0 ) {
143 err_setstr(KeyError, GETSTRINGVALUE((stringobject *)v));
144 return -1;
145 }
146 } else {
147 if ( !getargs(w, "s#", &drec.dptr, &drec.dsize) ) {
148 err_setstr(TypeError,
149 "gdbm mappings have string elements only");
150 return -1;
151 }
Guido van Rossumb045afc1995-03-14 15:04:40 +0000152 errno = 0;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000153 if ( gdbm_store(dp->di_dbm, krec, drec, GDBM_REPLACE) < 0 ) {
Guido van Rossumb045afc1995-03-14 15:04:40 +0000154 if (errno != 0)
155 err_errno(DbmError);
156 else
157 err_setstr(DbmError, (char *) gdbm_strerror(gdbm_errno));
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000158 return -1;
159 }
160 }
161 return 0;
162}
163
164static mapping_methods dbm_as_mapping = {
165 (inquiry)dbm_length, /*mp_length*/
166 (binaryfunc)dbm_subscript, /*mp_subscript*/
167 (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
168};
169
170static object *
Guido van Rossum807b7be1995-07-07 22:37:11 +0000171dbm_close(dp, args)
172 register dbmobject *dp;
173 object *args;
174{
175 if ( !getnoarg(args) )
176 return NULL;
177 if ( dp->di_dbm )
178 gdbm_close(dp->di_dbm);
179 dp->di_dbm = NULL;
180 DEL(dp);
181 INCREF(None);
182 return None;
183}
184
185static object *
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000186dbm_keys(dp, args)
187 register dbmobject *dp;
188 object *args;
189{
190 register object *v, *item;
191 datum key, okey={ (char *)NULL, 0};
192
193 if (dp == NULL || !is_dbmobject(dp)) {
194 err_badcall();
195 return NULL;
196 }
197 if (!getnoarg(args))
198 return NULL;
199 v = newlistobject(0);
200 if (v == NULL)
201 return NULL;
202 for (key = gdbm_firstkey(dp->di_dbm); key.dptr;
203 key = gdbm_nextkey(dp->di_dbm,okey) ) {
204 item = newsizedstringobject(key.dptr, key.dsize);
205 if ( item == 0 )
206 return NULL;
207 addlistitem(v, item);
Sjoerd Mullender2abc4941994-10-13 09:11:13 +0000208 if(okey.dsize) free(okey.dptr);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000209 okey=key;
210 }
211 return v;
212}
213
214
215static object *
216dbm_has_key(dp, args)
217 register dbmobject *dp;
218 object *args;
219{
Guido van Rossumb045afc1995-03-14 15:04:40 +0000220 datum key;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000221
222 if (!getargs(args, "s#", &key.dptr, &key.dsize))
223 return NULL;
Guido van Rossumb045afc1995-03-14 15:04:40 +0000224 return newintobject((long) gdbm_exists(dp->di_dbm, key));
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000225}
226
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000227static object *
228dbm_firstkey(dp, args)
229 register dbmobject *dp;
230 object *args;
231{
232 register object *v;
233 datum key;
234
235 if (!getnoarg(args))
236 return NULL;
237 key = gdbm_firstkey(dp->di_dbm);
238 if (key.dptr) {
239 v = newsizedstringobject(key.dptr, key.dsize);
240 free(key.dptr);
241 return v;
242 } else {
243 INCREF(None);
244 return None;
245 }
246}
247
248static object *
249dbm_nextkey(dp, args)
250 register dbmobject *dp;
251 object *args;
252{
253 register object *v;
254 datum key, nextkey;
255
256 if (!getargs(args, "s#", &key.dptr, &key.dsize))
257 return NULL;
258 nextkey = gdbm_nextkey(dp->di_dbm, key);
259 if (nextkey.dptr) {
260 v = newsizedstringobject(nextkey.dptr, nextkey.dsize);
261 free(nextkey.dptr);
262 return v;
263 } else {
264 INCREF(None);
265 return None;
266 }
267}
268
269static object *
270dbm_reorganize(dp, args)
271 register dbmobject *dp;
272 object *args;
273{
274 if (!getnoarg(args))
275 return NULL;
276 errno = 0;
277 if (gdbm_reorganize(dp->di_dbm) < 0) {
278 if (errno != 0)
279 err_errno(DbmError);
280 else
281 err_setstr(DbmError, (char *) gdbm_strerror(gdbm_errno));
282 return NULL;
283 }
284 INCREF(None);
285 return None;
286}
287
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000288static struct methodlist dbm_methods[] = {
Guido van Rossum807b7be1995-07-07 22:37:11 +0000289 {"close", (method)dbm_close},
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000290 {"keys", (method)dbm_keys},
291 {"has_key", (method)dbm_has_key},
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000292 {"firstkey", (method)dbm_firstkey},
293 {"nextkey", (method)dbm_nextkey},
294 {"reorganize", (method)dbm_reorganize},
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000295 {NULL, NULL} /* sentinel */
296};
297
298static object *
299dbm_getattr(dp, name)
300 dbmobject *dp;
301 char *name;
302{
303 return findmethod(dbm_methods, (object *)dp, name);
304}
305
306static typeobject Dbmtype = {
307 OB_HEAD_INIT(&Typetype)
308 0,
Guido van Rossum807b7be1995-07-07 22:37:11 +0000309 "gdbm",
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000310 sizeof(dbmobject),
311 0,
312 (destructor)dbm_dealloc, /*tp_dealloc*/
313 0, /*tp_print*/
314 (getattrfunc)dbm_getattr, /*tp_getattr*/
315 0, /*tp_setattr*/
316 0, /*tp_compare*/
317 0, /*tp_repr*/
318 0, /*tp_as_number*/
319 0, /*tp_as_sequence*/
320 &dbm_as_mapping, /*tp_as_mapping*/
321};
322
323/* ----------------------------------------------------------------- */
324
325static object *
326dbmopen(self, args)
327 object *self;
328 object *args;
329{
Guido van Rossum807b7be1995-07-07 22:37:11 +0000330 char *name;
331 char *flags = "r";
332 int iflags;
333 int mode = 0666;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000334
335/* XXXX add other flags */
Guido van Rossum807b7be1995-07-07 22:37:11 +0000336 if ( !newgetargs(args, "s|si", &name, &flags, &mode) )
337 return NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000338 if ( strcmp(flags, "r") == 0 )
339 iflags = GDBM_READER;
340 else if ( strcmp(flags, "w") == 0 )
341 iflags = GDBM_WRITER;
342 else if ( strcmp(flags, "c") == 0 )
343 iflags = GDBM_WRCREAT;
344 else if ( strcmp(flags, "n") == 0 )
345 iflags = GDBM_NEWDB;
346 else {
347 err_setstr(DbmError,
Guido van Rossumb045afc1995-03-14 15:04:40 +0000348 "Flags should be one of 'r', 'w', 'c' or 'n'");
Guido van Rossum807b7be1995-07-07 22:37:11 +0000349 return NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000350 }
351 return newdbmobject(name, iflags, mode);
352}
353
354static struct methodlist dbmmodule_methods[] = {
Guido van Rossum807b7be1995-07-07 22:37:11 +0000355 { "open", (method)dbmopen, 1 },
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000356 { 0, 0 },
357};
358
359void
360initgdbm() {
361 object *m, *d;
362
363 m = initmodule("gdbm", dbmmodule_methods);
364 d = getmoduledict(m);
365 DbmError = newstringobject("gdbm.error");
366 if ( DbmError == NULL || dictinsert(d, "error", DbmError) )
367 fatal("can't define gdbm.error");
368}