blob: 2ec43ffb8034014948e406f9ed5f8ade63f7e256 [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);
63 return 0;
64 }
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));
110 return 0;
111 }
112 if ( dbm_error(dp->di_dbm) ) {
113 dbm_clearerr(dp->di_dbm);
114 err_setstr(DbmError, "");
115 return 0;
116 }
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 *
165dbm_keys(dp, args)
166 register dbmobject *dp;
167 object *args;
168{
169 register object *v, *item;
170 datum key;
Guido van Rossumd5039131995-01-30 12:45:38 +0000171 int err;
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000172
173 if (dp == NULL || !is_dbmobject(dp)) {
174 err_badcall();
175 return NULL;
176 }
177 if (!getnoarg(args))
178 return NULL;
179 v = newlistobject(0);
180 if (v == NULL)
181 return NULL;
182 for (key = dbm_firstkey(dp->di_dbm); key.dptr;
Guido van Rossumd5039131995-01-30 12:45:38 +0000183 key = dbm_nextkey(dp->di_dbm)) {
184 item = newsizedstringobject(key.dptr, key.dsize);
185 if (item == NULL) {
186 DECREF(v);
187 return NULL;
188 }
189 err = addlistitem(v, item);
190 DECREF(item);
191 if (err != 0) {
192 DECREF(v);
193 return NULL;
194 }
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000195 }
196 return v;
197}
198
199
200static object *
201dbm_has_key(dp, args)
202 register dbmobject *dp;
203 object *args;
204{
205 datum key, val;
206
207 if (!getargs(args, "s#", &key.dptr, &key.dsize))
208 return NULL;
209 val = dbm_fetch(dp->di_dbm, key);
210 return newintobject(val.dptr != NULL);
211}
212
213static struct methodlist dbm_methods[] = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000214 {"keys", (method)dbm_keys},
215 {"has_key", (method)dbm_has_key},
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000216 {NULL, NULL} /* sentinel */
217};
218
219static object *
220dbm_getattr(dp, name)
221 dbmobject *dp;
222 char *name;
223{
224 return findmethod(dbm_methods, (object *)dp, name);
225}
226
Guido van Rossumb6775db1994-08-01 11:34:53 +0000227static typeobject Dbmtype = {
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000228 OB_HEAD_INIT(&Typetype)
229 0,
230 "Dbm_dictionary",
231 sizeof(dbmobject),
232 0,
Guido van Rossumb6775db1994-08-01 11:34:53 +0000233 (destructor)dbm_dealloc, /*tp_dealloc*/
234 0, /*tp_print*/
235 (getattrfunc)dbm_getattr, /*tp_getattr*/
236 0, /*tp_setattr*/
237 0, /*tp_compare*/
238 0, /*tp_repr*/
239 0, /*tp_as_number*/
240 0, /*tp_as_sequence*/
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000241 &dbm_as_mapping, /*tp_as_mapping*/
242};
243
244/* ----------------------------------------------------------------- */
245
246static object *
247dbmopen(self, args)
248 object *self;
249 object *args;
250{
251 char *name, *flags;
252 int iflags, mode;
253
254 if ( !getargs(args, "(ssi)", &name, &flags, &mode) )
255 return 0;
256 if ( strcmp(flags, "r") == 0 )
257 iflags = O_RDONLY;
258 else if ( strcmp(flags, "w") == 0 )
259 iflags = O_WRONLY|O_CREAT;
260 else if ( strcmp(flags, "rw") == 0 )
261 iflags = O_RDWR|O_CREAT;
262 else {
263 err_setstr(DbmError,
264 "Flags should be one of 'r', 'w' or 'rw'");
265 return 0;
266 }
267 return newdbmobject(name, iflags, mode);
268}
269
270static struct methodlist dbmmodule_methods[] = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000271 { "open", (method)dbmopen },
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000272 { 0, 0 },
273};
274
275void
276initdbm() {
277 object *m, *d;
278
279 m = initmodule("dbm", dbmmodule_methods);
280 d = getmoduledict(m);
281 DbmError = newstringobject("dbm.error");
282 if ( DbmError == NULL || dictinsert(d, "error", DbmError) )
283 fatal("can't define dbm.error");
284}
285
286