(py-indent-right, py-outdent-left): new commands, bound to C-c C-r and
[python/dscho.git] / Modules / gdbmmodule.c
blob60b45fa3e9742a25a621d4a9b72419ee17f4a97f
1 /* 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 /***********************************************************
6 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
7 The Netherlands.
9 All Rights Reserved
11 Permission to use, copy, modify, and distribute this software and its
12 documentation for any purpose and without fee is hereby granted,
13 provided that the above copyright notice appear in all copies and that
14 both that copyright notice and this permission notice appear in
15 supporting documentation, and that the names of Stichting Mathematisch
16 Centrum or CWI not be used in advertising or publicity pertaining to
17 distribution of the software without specific, written prior permission.
19 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
20 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
22 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
23 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
24 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
25 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
27 ******************************************************************/
29 /* DBM module using dictionary interface */
32 #include "allobjects.h"
33 #include "modsupport.h"
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <fcntl.h>
38 #include "gdbm.h"
40 typedef struct {
41 OB_HEAD
42 int di_size; /* -1 means recompute */
43 GDBM_FILE di_dbm;
44 } dbmobject;
46 staticforward typeobject Dbmtype;
48 #define is_dbmobject(v) ((v)->ob_type == &Dbmtype)
50 static object *DbmError;
52 static object *
53 newdbmobject(file, flags, mode)
54 char *file;
55 int flags;
56 int mode;
58 dbmobject *dp;
60 dp = NEWOBJ(dbmobject, &Dbmtype);
61 if (dp == NULL)
62 return NULL;
63 dp->di_size = -1;
64 errno = 0;
65 if ( (dp->di_dbm = gdbm_open(file, 0, flags, mode, NULL)) == 0 ) {
66 if (errno != 0)
67 err_errno(DbmError);
68 else
69 err_setstr(DbmError, (char *) gdbm_strerror(gdbm_errno));
70 DECREF(dp);
71 return 0;
73 return (object *)dp;
76 /* Methods */
78 static void
79 dbm_dealloc(dp)
80 register dbmobject *dp;
82 if ( dp->di_dbm )
83 gdbm_close(dp->di_dbm);
84 DEL(dp);
87 static int
88 dbm_length(dp)
89 dbmobject *dp;
91 if ( dp->di_size < 0 ) {
92 datum key,okey;
93 int size;
94 okey.dsize=0;
96 size = 0;
97 for ( key=gdbm_firstkey(dp->di_dbm); key.dptr;
98 key = gdbm_nextkey(dp->di_dbm,okey)) {
99 size++;
100 if(okey.dsize) free(okey.dptr);
101 okey=key;
103 dp->di_size = size;
105 return dp->di_size;
108 static object *
109 dbm_subscript(dp, key)
110 dbmobject *dp;
111 register object *key;
113 object *v;
114 datum drec, krec;
116 if (!getargs(key, "s#", &krec.dptr, &krec.dsize) )
117 return NULL;
119 drec = gdbm_fetch(dp->di_dbm, krec);
120 if ( drec.dptr == 0 ) {
121 err_setstr(KeyError, GETSTRINGVALUE((stringobject *)key));
122 return 0;
124 v = newsizedstringobject(drec.dptr, drec.dsize);
125 free(drec.dptr);
126 return v;
129 static int
130 dbm_ass_sub(dp, v, w)
131 dbmobject *dp;
132 object *v, *w;
134 datum krec, drec;
136 if ( !getargs(v, "s#", &krec.dptr, &krec.dsize) ) {
137 err_setstr(TypeError, "gdbm mappings have string indices only");
138 return -1;
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;
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;
152 errno = 0;
153 if ( gdbm_store(dp->di_dbm, krec, drec, GDBM_REPLACE) < 0 ) {
154 if (errno != 0)
155 err_errno(DbmError);
156 else
157 err_setstr(DbmError, (char *) gdbm_strerror(gdbm_errno));
158 return -1;
161 return 0;
164 static 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*/
170 static object *
171 dbm_keys(dp, args)
172 register dbmobject *dp;
173 object *args;
175 register object *v, *item;
176 datum key, okey={ (char *)NULL, 0};
178 if (dp == NULL || !is_dbmobject(dp)) {
179 err_badcall();
180 return NULL;
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);
193 if(okey.dsize) free(okey.dptr);
194 okey=key;
196 return v;
200 static object *
201 dbm_has_key(dp, args)
202 register dbmobject *dp;
203 object *args;
205 datum key;
207 if (!getargs(args, "s#", &key.dptr, &key.dsize))
208 return NULL;
209 return newintobject((long) gdbm_exists(dp->di_dbm, key));
212 static struct methodlist dbm_methods[] = {
213 {"keys", (method)dbm_keys},
214 {"has_key", (method)dbm_has_key},
215 {NULL, NULL} /* sentinel */
218 static object *
219 dbm_getattr(dp, name)
220 dbmobject *dp;
221 char *name;
223 return findmethod(dbm_methods, (object *)dp, name);
226 static typeobject Dbmtype = {
227 OB_HEAD_INIT(&Typetype)
229 "Gdbm_dictionary",
230 sizeof(dbmobject),
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*/
243 /* ----------------------------------------------------------------- */
245 static object *
246 dbmopen(self, args)
247 object *self;
248 object *args;
250 char *name, *flags;
251 int iflags, mode;
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,
266 "Flags should be one of 'r', 'w', 'c' or 'n'");
267 return 0;
269 return newdbmobject(name, iflags, mode);
272 static struct methodlist dbmmodule_methods[] = {
273 { "open", (method)dbmopen },
274 { 0, 0 },
277 void
278 initgdbm() {
279 object *m, *d;
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");