blob: d0736f7ddb049757f4c6875d91230ffd205c1c72 [file] [log] [blame]
Guido van Rossumdd9ed831992-06-29 17:10:40 +00001/***********************************************************
Guido van Rossum524b5881995-01-04 19:10:35 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossumdd9ed831992-06-29 17:10:40 +00004
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
25/* DBM module using dictionary interface */
26
27
28#include "allobjects.h"
29#include "modsupport.h"
30
31#include <sys/types.h>
32#include <sys/stat.h>
33#include <fcntl.h>
34#include <ndbm.h>
35
36typedef struct {
37 OB_HEAD
38 int di_size; /* -1 means recompute */
39 DBM *di_dbm;
40} dbmobject;
41
Guido van Rossumb6775db1994-08-01 11:34:53 +000042staticforward typeobject Dbmtype;
Guido van Rossumdd9ed831992-06-29 17:10:40 +000043
44#define is_dbmobject(v) ((v)->ob_type == &Dbmtype)
45
46static object *DbmError;
47
48static object *
49newdbmobject(file, flags, mode)
50 char *file;
51 int flags;
52 int mode;
53{
54 dbmobject *dp;
55
56 dp = NEWOBJ(dbmobject, &Dbmtype);
57 if (dp == NULL)
58 return NULL;
59 dp->di_size = -1;
60 if ( (dp->di_dbm = dbm_open(file, flags, mode)) == 0 ) {
61 err_errno(DbmError);
62 DECREF(dp);
Guido van Rossum807b7be1995-07-07 22:37:11 +000063 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +000064 }
65 return (object *)dp;
66}
67
68/* Methods */
69
70static void
71dbm_dealloc(dp)
72 register dbmobject *dp;
73{
74 if ( dp->di_dbm )
75 dbm_close(dp->di_dbm);
76 DEL(dp);
77}
78
79static int
80dbm_length(dp)
81 dbmobject *dp;
82{
83 if ( dp->di_size < 0 ) {
84 datum key;
85 int size;
86
87 size = 0;
88 for ( key=dbm_firstkey(dp->di_dbm); key.dptr;
89 key = dbm_nextkey(dp->di_dbm))
90 size++;
91 dp->di_size = size;
92 }
93 return dp->di_size;
94}
95
96static object *
97dbm_subscript(dp, key)
98 dbmobject *dp;
99 register object *key;
100{
101 object *v;
102 datum drec, krec;
103
104 if (!getargs(key, "s#", &krec.dptr, &krec.dsize) )
105 return NULL;
106
107 drec = dbm_fetch(dp->di_dbm, krec);
108 if ( drec.dptr == 0 ) {
109 err_setstr(KeyError, GETSTRINGVALUE((stringobject *)key));
Guido van Rossum807b7be1995-07-07 22:37:11 +0000110 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000111 }
112 if ( dbm_error(dp->di_dbm) ) {
113 dbm_clearerr(dp->di_dbm);
114 err_setstr(DbmError, "");
Guido van Rossum807b7be1995-07-07 22:37:11 +0000115 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000116 }
117 return newsizedstringobject(drec.dptr, drec.dsize);
118}
119
120static int
121dbm_ass_sub(dp, v, w)
122 dbmobject *dp;
123 object *v, *w;
124{
125 datum krec, drec;
126
127 if ( !getargs(v, "s#", &krec.dptr, &krec.dsize) ) {
128 err_setstr(TypeError, "dbm mappings have string indices only");
129 return -1;
130 }
131 dp->di_size = -1;
132 if (w == NULL) {
133 if ( dbm_delete(dp->di_dbm, krec) < 0 ) {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000134 dbm_clearerr(dp->di_dbm);
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000135 err_setstr(KeyError, GETSTRINGVALUE((stringobject *)v));
136 return -1;
137 }
138 } else {
139 if ( !getargs(w, "s#", &drec.dptr, &drec.dsize) ) {
140 err_setstr(TypeError,
141 "dbm mappings have string elements only");
142 return -1;
143 }
144 if ( dbm_store(dp->di_dbm, krec, drec, DBM_REPLACE) < 0 ) {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000145 dbm_clearerr(dp->di_dbm);
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000146 err_setstr(DbmError, "Cannot add item to database");
147 return -1;
148 }
149 }
150 if ( dbm_error(dp->di_dbm) ) {
151 dbm_clearerr(dp->di_dbm);
152 err_setstr(DbmError, "");
153 return -1;
154 }
155 return 0;
156}
157
158static mapping_methods dbm_as_mapping = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000159 (inquiry)dbm_length, /*mp_length*/
160 (binaryfunc)dbm_subscript, /*mp_subscript*/
161 (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000162};
163
164static object *
Guido van Rossum807b7be1995-07-07 22:37:11 +0000165dbm__close(dp, args)
166 register dbmobject *dp;
167 object *args;
168{
169 if ( !getnoarg(args) )
170 return NULL;
171 if ( dp->di_dbm )
172 dbm_close(dp->di_dbm);
173 dp->di_dbm = NULL;
174 DEL(dp);
175 INCREF(None);
176 return None;
177}
178
179static object *
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000180dbm_keys(dp, args)
181 register dbmobject *dp;
182 object *args;
183{
184 register object *v, *item;
185 datum key;
Guido van Rossumd5039131995-01-30 12:45:38 +0000186 int err;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000187
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000188 if (!getnoarg(args))
189 return NULL;
190 v = newlistobject(0);
191 if (v == NULL)
192 return NULL;
193 for (key = dbm_firstkey(dp->di_dbm); key.dptr;
Guido van Rossumd5039131995-01-30 12:45:38 +0000194 key = dbm_nextkey(dp->di_dbm)) {
195 item = newsizedstringobject(key.dptr, key.dsize);
196 if (item == NULL) {
197 DECREF(v);
198 return NULL;
199 }
200 err = addlistitem(v, item);
201 DECREF(item);
202 if (err != 0) {
203 DECREF(v);
204 return NULL;
205 }
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000206 }
207 return v;
208}
209
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000210static object *
211dbm_has_key(dp, args)
212 register dbmobject *dp;
213 object *args;
214{
215 datum key, val;
216
217 if (!getargs(args, "s#", &key.dptr, &key.dsize))
218 return NULL;
219 val = dbm_fetch(dp->di_dbm, key);
220 return newintobject(val.dptr != NULL);
221}
222
223static struct methodlist dbm_methods[] = {
Guido van Rossum807b7be1995-07-07 22:37:11 +0000224 {"close", (method)dbm__close},
Guido van Rossumb6775db1994-08-01 11:34:53 +0000225 {"keys", (method)dbm_keys},
226 {"has_key", (method)dbm_has_key},
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000227 {NULL, NULL} /* sentinel */
228};
229
230static object *
231dbm_getattr(dp, name)
232 dbmobject *dp;
233 char *name;
234{
235 return findmethod(dbm_methods, (object *)dp, name);
236}
237
Guido van Rossumb6775db1994-08-01 11:34:53 +0000238static typeobject Dbmtype = {
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000239 OB_HEAD_INIT(&Typetype)
240 0,
Guido van Rossum807b7be1995-07-07 22:37:11 +0000241 "dbm",
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000242 sizeof(dbmobject),
243 0,
Guido van Rossumb6775db1994-08-01 11:34:53 +0000244 (destructor)dbm_dealloc, /*tp_dealloc*/
245 0, /*tp_print*/
246 (getattrfunc)dbm_getattr, /*tp_getattr*/
247 0, /*tp_setattr*/
248 0, /*tp_compare*/
249 0, /*tp_repr*/
250 0, /*tp_as_number*/
251 0, /*tp_as_sequence*/
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000252 &dbm_as_mapping, /*tp_as_mapping*/
253};
254
255/* ----------------------------------------------------------------- */
256
257static object *
258dbmopen(self, args)
259 object *self;
260 object *args;
261{
Guido van Rossum807b7be1995-07-07 22:37:11 +0000262 char *name;
263 char *flags = "r";
264 int iflags;
265 int mode = 0666;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000266
Guido van Rossum807b7be1995-07-07 22:37:11 +0000267 if ( !newgetargs(args, "s|si", &name, &flags, &mode) )
268 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000269 if ( strcmp(flags, "r") == 0 )
270 iflags = O_RDONLY;
271 else if ( strcmp(flags, "w") == 0 )
Guido van Rossum807b7be1995-07-07 22:37:11 +0000272 iflags = O_RDWR;
273 else if ( strcmp(flags, "rw") == 0 ) /* B/W compat */
274 iflags = O_RDWR|O_CREAT;
275 else if ( strcmp(flags, "c") == 0 )
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000276 iflags = O_RDWR|O_CREAT;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000277 else if ( strcmp(flags, "n") == 0 )
278 iflags = O_RDWR|O_CREAT|O_TRUNC;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000279 else {
280 err_setstr(DbmError,
Guido van Rossum807b7be1995-07-07 22:37:11 +0000281 "Flags should be one of 'r', 'w', 'c' or 'n'");
282 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000283 }
284 return newdbmobject(name, iflags, mode);
285}
286
287static struct methodlist dbmmodule_methods[] = {
Guido van Rossum807b7be1995-07-07 22:37:11 +0000288 { "open", (method)dbmopen, 1 },
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000289 { 0, 0 },
290};
291
292void
293initdbm() {
294 object *m, *d;
295
296 m = initmodule("dbm", dbmmodule_methods);
297 d = getmoduledict(m);
298 DbmError = newstringobject("dbm.error");
299 if ( DbmError == NULL || dictinsert(d, "error", DbmError) )
300 fatal("can't define dbm.error");
301}