blob: 60b45fa3e9742a25a621d4a9b72419ee17f4a97f [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);
71 return 0;
72 }
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));
122 return 0;
123 }
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 *
171dbm_keys(dp, args)
172 register dbmobject *dp;
173 object *args;
174{
175 register object *v, *item;
176 datum key, okey={ (char *)NULL, 0};
177
178 if (dp == NULL || !is_dbmobject(dp)) {
179 err_badcall();
180 return NULL;
181 }
182 if (!getnoarg(args))
183 return NULL;
184 v = newlistobject(0);
185 if (v == NULL)
186 return NULL;
187 for (key = gdbm_firstkey(dp->di_dbm); key.dptr;
188 key = gdbm_nextkey(dp->di_dbm,okey) ) {
189 item = newsizedstringobject(key.dptr, key.dsize);
190 if ( item == 0 )
191 return NULL;
192 addlistitem(v, item);
Sjoerd Mullender2abc4941994-10-13 09:11:13 +0000193 if(okey.dsize) free(okey.dptr);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000194 okey=key;
195 }
196 return v;
197}
198
199
200static object *
201dbm_has_key(dp, args)
202 register dbmobject *dp;
203 object *args;
204{
Guido van Rossumb045afc1995-03-14 15:04:40 +0000205 datum key;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000206
207 if (!getargs(args, "s#", &key.dptr, &key.dsize))
208 return NULL;
Guido van Rossumb045afc1995-03-14 15:04:40 +0000209 return newintobject((long) gdbm_exists(dp->di_dbm, key));
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000210}
211
212static struct methodlist dbm_methods[] = {
213 {"keys", (method)dbm_keys},
214 {"has_key", (method)dbm_has_key},
215 {NULL, NULL} /* sentinel */
216};
217
218static object *
219dbm_getattr(dp, name)
220 dbmobject *dp;
221 char *name;
222{
223 return findmethod(dbm_methods, (object *)dp, name);
224}
225
226static typeobject Dbmtype = {
227 OB_HEAD_INIT(&Typetype)
228 0,
229 "Gdbm_dictionary",
230 sizeof(dbmobject),
231 0,
232 (destructor)dbm_dealloc, /*tp_dealloc*/
233 0, /*tp_print*/
234 (getattrfunc)dbm_getattr, /*tp_getattr*/
235 0, /*tp_setattr*/
236 0, /*tp_compare*/
237 0, /*tp_repr*/
238 0, /*tp_as_number*/
239 0, /*tp_as_sequence*/
240 &dbm_as_mapping, /*tp_as_mapping*/
241};
242
243/* ----------------------------------------------------------------- */
244
245static object *
246dbmopen(self, args)
247 object *self;
248 object *args;
249{
250 char *name, *flags;
251 int iflags, mode;
252
253/* XXXX add other flags */
254 if ( !getargs(args, "(ssi)", &name, &flags, &mode) )
255 return 0;
256 if ( strcmp(flags, "r") == 0 )
257 iflags = GDBM_READER;
258 else if ( strcmp(flags, "w") == 0 )
259 iflags = GDBM_WRITER;
260 else if ( strcmp(flags, "c") == 0 )
261 iflags = GDBM_WRCREAT;
262 else if ( strcmp(flags, "n") == 0 )
263 iflags = GDBM_NEWDB;
264 else {
265 err_setstr(DbmError,
Guido van Rossumb045afc1995-03-14 15:04:40 +0000266 "Flags should be one of 'r', 'w', 'c' or 'n'");
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000267 return 0;
268 }
269 return newdbmobject(name, iflags, mode);
270}
271
272static struct methodlist dbmmodule_methods[] = {
273 { "open", (method)dbmopen },
274 { 0, 0 },
275};
276
277void
278initgdbm() {
279 object *m, *d;
280
281 m = initmodule("gdbm", dbmmodule_methods);
282 d = getmoduledict(m);
283 DbmError = newstringobject("gdbm.error");
284 if ( DbmError == NULL || dictinsert(d, "error", DbmError) )
285 fatal("can't define gdbm.error");
286}