blob: 936fb45ab1dd0b9c3bf10fab6ae3c197133a7353 [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;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000174 INCREF(None);
175 return None;
176}
177
178static object *
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000179dbm_keys(dp, args)
180 register dbmobject *dp;
181 object *args;
182{
183 register object *v, *item;
184 datum key;
Guido van Rossumd5039131995-01-30 12:45:38 +0000185 int err;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000186
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000187 if (!getnoarg(args))
188 return NULL;
189 v = newlistobject(0);
190 if (v == NULL)
191 return NULL;
192 for (key = dbm_firstkey(dp->di_dbm); key.dptr;
Guido van Rossumd5039131995-01-30 12:45:38 +0000193 key = dbm_nextkey(dp->di_dbm)) {
194 item = newsizedstringobject(key.dptr, key.dsize);
195 if (item == NULL) {
196 DECREF(v);
197 return NULL;
198 }
199 err = addlistitem(v, item);
200 DECREF(item);
201 if (err != 0) {
202 DECREF(v);
203 return NULL;
204 }
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000205 }
206 return v;
207}
208
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000209static object *
210dbm_has_key(dp, args)
211 register dbmobject *dp;
212 object *args;
213{
214 datum key, val;
215
216 if (!getargs(args, "s#", &key.dptr, &key.dsize))
217 return NULL;
218 val = dbm_fetch(dp->di_dbm, key);
219 return newintobject(val.dptr != NULL);
220}
221
222static struct methodlist dbm_methods[] = {
Guido van Rossum807b7be1995-07-07 22:37:11 +0000223 {"close", (method)dbm__close},
Guido van Rossumb6775db1994-08-01 11:34:53 +0000224 {"keys", (method)dbm_keys},
225 {"has_key", (method)dbm_has_key},
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000226 {NULL, NULL} /* sentinel */
227};
228
229static object *
230dbm_getattr(dp, name)
231 dbmobject *dp;
232 char *name;
233{
234 return findmethod(dbm_methods, (object *)dp, name);
235}
236
Guido van Rossumb6775db1994-08-01 11:34:53 +0000237static typeobject Dbmtype = {
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000238 OB_HEAD_INIT(&Typetype)
239 0,
Guido van Rossum807b7be1995-07-07 22:37:11 +0000240 "dbm",
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000241 sizeof(dbmobject),
242 0,
Guido van Rossumb6775db1994-08-01 11:34:53 +0000243 (destructor)dbm_dealloc, /*tp_dealloc*/
244 0, /*tp_print*/
245 (getattrfunc)dbm_getattr, /*tp_getattr*/
246 0, /*tp_setattr*/
247 0, /*tp_compare*/
248 0, /*tp_repr*/
249 0, /*tp_as_number*/
250 0, /*tp_as_sequence*/
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000251 &dbm_as_mapping, /*tp_as_mapping*/
252};
253
254/* ----------------------------------------------------------------- */
255
256static object *
257dbmopen(self, args)
258 object *self;
259 object *args;
260{
Guido van Rossum807b7be1995-07-07 22:37:11 +0000261 char *name;
262 char *flags = "r";
263 int iflags;
264 int mode = 0666;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000265
Guido van Rossum807b7be1995-07-07 22:37:11 +0000266 if ( !newgetargs(args, "s|si", &name, &flags, &mode) )
267 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000268 if ( strcmp(flags, "r") == 0 )
269 iflags = O_RDONLY;
270 else if ( strcmp(flags, "w") == 0 )
Guido van Rossum807b7be1995-07-07 22:37:11 +0000271 iflags = O_RDWR;
272 else if ( strcmp(flags, "rw") == 0 ) /* B/W compat */
273 iflags = O_RDWR|O_CREAT;
274 else if ( strcmp(flags, "c") == 0 )
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000275 iflags = O_RDWR|O_CREAT;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000276 else if ( strcmp(flags, "n") == 0 )
277 iflags = O_RDWR|O_CREAT|O_TRUNC;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000278 else {
279 err_setstr(DbmError,
Guido van Rossum807b7be1995-07-07 22:37:11 +0000280 "Flags should be one of 'r', 'w', 'c' or 'n'");
281 return NULL;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000282 }
283 return newdbmobject(name, iflags, mode);
284}
285
286static struct methodlist dbmmodule_methods[] = {
Guido van Rossum807b7be1995-07-07 22:37:11 +0000287 { "open", (method)dbmopen, 1 },
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000288 { 0, 0 },
289};
290
291void
292initdbm() {
293 object *m, *d;
294
295 m = initmodule("dbm", dbmmodule_methods);
296 d = getmoduledict(m);
297 DbmError = newstringobject("dbm.error");
298 if ( DbmError == NULL || dictinsert(d, "error", DbmError) )
299 fatal("can't define dbm.error");
300}