blob: b4849178124eabfc415099373d7eae0141ba4b11 [file] [log] [blame]
Guido van Rossumdd9ed831992-06-29 17:10:40 +00001/***********************************************************
Guido van Rossumb6775db1994-08-01 11:34:53 +00002Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
Guido van Rossum9bfef441993-03-29 10:43:31 +00003Amsterdam, The 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;
171
172 if (dp == NULL || !is_dbmobject(dp)) {
173 err_badcall();
174 return NULL;
175 }
176 if (!getnoarg(args))
177 return NULL;
178 v = newlistobject(0);
179 if (v == NULL)
180 return NULL;
181 for (key = dbm_firstkey(dp->di_dbm); key.dptr;
182 key = dbm_nextkey(dp->di_dbm) ) {
183 item = newsizedstringobject(key.dptr, key.dsize);
184 if ( item == 0 )
185 return NULL;
186 addlistitem(v, item);
187 }
188 return v;
189}
190
191
192static object *
193dbm_has_key(dp, args)
194 register dbmobject *dp;
195 object *args;
196{
197 datum key, val;
198
199 if (!getargs(args, "s#", &key.dptr, &key.dsize))
200 return NULL;
201 val = dbm_fetch(dp->di_dbm, key);
202 return newintobject(val.dptr != NULL);
203}
204
205static struct methodlist dbm_methods[] = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000206 {"keys", (method)dbm_keys},
207 {"has_key", (method)dbm_has_key},
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000208 {NULL, NULL} /* sentinel */
209};
210
211static object *
212dbm_getattr(dp, name)
213 dbmobject *dp;
214 char *name;
215{
216 return findmethod(dbm_methods, (object *)dp, name);
217}
218
Guido van Rossumb6775db1994-08-01 11:34:53 +0000219static typeobject Dbmtype = {
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000220 OB_HEAD_INIT(&Typetype)
221 0,
222 "Dbm_dictionary",
223 sizeof(dbmobject),
224 0,
Guido van Rossumb6775db1994-08-01 11:34:53 +0000225 (destructor)dbm_dealloc, /*tp_dealloc*/
226 0, /*tp_print*/
227 (getattrfunc)dbm_getattr, /*tp_getattr*/
228 0, /*tp_setattr*/
229 0, /*tp_compare*/
230 0, /*tp_repr*/
231 0, /*tp_as_number*/
232 0, /*tp_as_sequence*/
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000233 &dbm_as_mapping, /*tp_as_mapping*/
234};
235
236/* ----------------------------------------------------------------- */
237
238static object *
239dbmopen(self, args)
240 object *self;
241 object *args;
242{
243 char *name, *flags;
244 int iflags, mode;
245
246 if ( !getargs(args, "(ssi)", &name, &flags, &mode) )
247 return 0;
248 if ( strcmp(flags, "r") == 0 )
249 iflags = O_RDONLY;
250 else if ( strcmp(flags, "w") == 0 )
251 iflags = O_WRONLY|O_CREAT;
252 else if ( strcmp(flags, "rw") == 0 )
253 iflags = O_RDWR|O_CREAT;
254 else {
255 err_setstr(DbmError,
256 "Flags should be one of 'r', 'w' or 'rw'");
257 return 0;
258 }
259 return newdbmobject(name, iflags, mode);
260}
261
262static struct methodlist dbmmodule_methods[] = {
Guido van Rossumb6775db1994-08-01 11:34:53 +0000263 { "open", (method)dbmopen },
Guido van Rossumdd9ed831992-06-29 17:10:40 +0000264 { 0, 0 },
265};
266
267void
268initdbm() {
269 object *m, *d;
270
271 m = initmodule("dbm", dbmmodule_methods);
272 d = getmoduledict(m);
273 DbmError = newstringobject("dbm.error");
274 if ( DbmError == NULL || dictinsert(d, "error", DbmError) )
275 fatal("can't define dbm.error");
276}
277
278