Class around PixMap objects that allows more python-like access. By Joe Strout.
[python/dscho.git] / Modules / dbmmodule.c
blob7a234a2cd4115b5e57c4166e5ddf44f0c8b08831
1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI or Corporation for National Research Initiatives or
13 CNRI not be used in advertising or publicity pertaining to
14 distribution of the software without specific, written prior
15 permission.
17 While CWI is the initial source for this software, a modified version
18 is made available by the Corporation for National Research Initiatives
19 (CNRI) at the Internet address ftp://ftp.python.org.
21 STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22 REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23 MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24 CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25 DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26 PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28 PERFORMANCE OF THIS SOFTWARE.
30 ******************************************************************/
32 /* DBM module using dictionary interface */
35 #include "Python.h"
37 #include <sys/types.h>
38 #include <sys/stat.h>
39 #include <fcntl.h>
40 #include <ndbm.h>
42 typedef struct {
43 PyObject_HEAD
44 int di_size; /* -1 means recompute */
45 DBM *di_dbm;
46 } dbmobject;
48 staticforward PyTypeObject Dbmtype;
50 #define is_dbmobject(v) ((v)->ob_type == &Dbmtype)
51 #define check_dbmobject_open(v) if ((v)->di_dbm == NULL) \
52 { PyErr_SetString(DbmError, "DBM object has already been closed"); \
53 return NULL; }
55 static PyObject *DbmError;
57 static PyObject *
58 newdbmobject(file, flags, mode)
59 char *file;
60 int flags;
61 int mode;
63 dbmobject *dp;
65 dp = PyObject_NEW(dbmobject, &Dbmtype);
66 if (dp == NULL)
67 return NULL;
68 dp->di_size = -1;
69 if ( (dp->di_dbm = dbm_open(file, flags, mode)) == 0 ) {
70 PyErr_SetFromErrno(DbmError);
71 Py_DECREF(dp);
72 return NULL;
74 return (PyObject *)dp;
77 /* Methods */
79 static void
80 dbm_dealloc(dp)
81 register dbmobject *dp;
83 if ( dp->di_dbm )
84 dbm_close(dp->di_dbm);
85 PyMem_DEL(dp);
88 static int
89 dbm_length(dp)
90 dbmobject *dp;
92 if (dp->di_dbm == NULL) {
93 PyErr_SetString(DbmError, "DBM object has already been closed");
94 return -1;
96 if ( dp->di_size < 0 ) {
97 datum key;
98 int size;
100 size = 0;
101 for ( key=dbm_firstkey(dp->di_dbm); key.dptr;
102 key = dbm_nextkey(dp->di_dbm))
103 size++;
104 dp->di_size = size;
106 return dp->di_size;
109 static PyObject *
110 dbm_subscript(dp, key)
111 dbmobject *dp;
112 register PyObject *key;
114 datum drec, krec;
116 if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize) )
117 return NULL;
119 check_dbmobject_open(dp);
120 drec = dbm_fetch(dp->di_dbm, krec);
121 if ( drec.dptr == 0 ) {
122 PyErr_SetString(PyExc_KeyError,
123 PyString_AS_STRING((PyStringObject *)key));
124 return NULL;
126 if ( dbm_error(dp->di_dbm) ) {
127 dbm_clearerr(dp->di_dbm);
128 PyErr_SetString(DbmError, "");
129 return NULL;
131 return PyString_FromStringAndSize(drec.dptr, drec.dsize);
134 static int
135 dbm_ass_sub(dp, v, w)
136 dbmobject *dp;
137 PyObject *v, *w;
139 datum krec, drec;
141 if ( !PyArg_Parse(v, "s#", &krec.dptr, &krec.dsize) ) {
142 PyErr_SetString(PyExc_TypeError,
143 "dbm mappings have string indices only");
144 return -1;
146 if (dp->di_dbm == NULL) {
147 PyErr_SetString(DbmError, "DBM object has already been closed");
148 return -1;
150 dp->di_size = -1;
151 if (w == NULL) {
152 if ( dbm_delete(dp->di_dbm, krec) < 0 ) {
153 dbm_clearerr(dp->di_dbm);
154 PyErr_SetString(PyExc_KeyError,
155 PyString_AS_STRING((PyStringObject *)v));
156 return -1;
158 } else {
159 if ( !PyArg_Parse(w, "s#", &drec.dptr, &drec.dsize) ) {
160 PyErr_SetString(PyExc_TypeError,
161 "dbm mappings have string elements only");
162 return -1;
164 if ( dbm_store(dp->di_dbm, krec, drec, DBM_REPLACE) < 0 ) {
165 dbm_clearerr(dp->di_dbm);
166 PyErr_SetString(DbmError,
167 "Cannot add item to database");
168 return -1;
171 if ( dbm_error(dp->di_dbm) ) {
172 dbm_clearerr(dp->di_dbm);
173 PyErr_SetString(DbmError, "");
174 return -1;
176 return 0;
179 static PyMappingMethods dbm_as_mapping = {
180 (inquiry)dbm_length, /*mp_length*/
181 (binaryfunc)dbm_subscript, /*mp_subscript*/
182 (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
185 static PyObject *
186 dbm__close(dp, args)
187 register dbmobject *dp;
188 PyObject *args;
190 if ( !PyArg_NoArgs(args) )
191 return NULL;
192 if ( dp->di_dbm )
193 dbm_close(dp->di_dbm);
194 dp->di_dbm = NULL;
195 Py_INCREF(Py_None);
196 return Py_None;
199 static PyObject *
200 dbm_keys(dp, args)
201 register dbmobject *dp;
202 PyObject *args;
204 register PyObject *v, *item;
205 datum key;
206 int err;
208 if (!PyArg_NoArgs(args))
209 return NULL;
210 check_dbmobject_open(dp);
211 v = PyList_New(0);
212 if (v == NULL)
213 return NULL;
214 for (key = dbm_firstkey(dp->di_dbm); key.dptr;
215 key = dbm_nextkey(dp->di_dbm)) {
216 item = PyString_FromStringAndSize(key.dptr, key.dsize);
217 if (item == NULL) {
218 Py_DECREF(v);
219 return NULL;
221 err = PyList_Append(v, item);
222 Py_DECREF(item);
223 if (err != 0) {
224 Py_DECREF(v);
225 return NULL;
228 return v;
231 static PyObject *
232 dbm_has_key(dp, args)
233 register dbmobject *dp;
234 PyObject *args;
236 datum key, val;
238 if (!PyArg_Parse(args, "s#", &key.dptr, &key.dsize))
239 return NULL;
240 check_dbmobject_open(dp);
241 val = dbm_fetch(dp->di_dbm, key);
242 return PyInt_FromLong(val.dptr != NULL);
245 static PyMethodDef dbm_methods[] = {
246 {"close", (PyCFunction)dbm__close},
247 {"keys", (PyCFunction)dbm_keys},
248 {"has_key", (PyCFunction)dbm_has_key},
249 {NULL, NULL} /* sentinel */
252 static PyObject *
253 dbm_getattr(dp, name)
254 dbmobject *dp;
255 char *name;
257 return Py_FindMethod(dbm_methods, (PyObject *)dp, name);
260 static PyTypeObject Dbmtype = {
261 PyObject_HEAD_INIT(&PyType_Type)
263 "dbm",
264 sizeof(dbmobject),
266 (destructor)dbm_dealloc, /*tp_dealloc*/
267 0, /*tp_print*/
268 (getattrfunc)dbm_getattr, /*tp_getattr*/
269 0, /*tp_setattr*/
270 0, /*tp_compare*/
271 0, /*tp_repr*/
272 0, /*tp_as_number*/
273 0, /*tp_as_sequence*/
274 &dbm_as_mapping, /*tp_as_mapping*/
277 /* ----------------------------------------------------------------- */
279 static PyObject *
280 dbmopen(self, args)
281 PyObject *self;
282 PyObject *args;
284 char *name;
285 char *flags = "r";
286 int iflags;
287 int mode = 0666;
289 if ( !PyArg_ParseTuple(args, "s|si", &name, &flags, &mode) )
290 return NULL;
291 if ( strcmp(flags, "r") == 0 )
292 iflags = O_RDONLY;
293 else if ( strcmp(flags, "w") == 0 )
294 iflags = O_RDWR;
295 else if ( strcmp(flags, "rw") == 0 ) /* B/W compat */
296 iflags = O_RDWR|O_CREAT;
297 else if ( strcmp(flags, "c") == 0 )
298 iflags = O_RDWR|O_CREAT;
299 else if ( strcmp(flags, "n") == 0 )
300 iflags = O_RDWR|O_CREAT|O_TRUNC;
301 else {
302 PyErr_SetString(DbmError,
303 "Flags should be one of 'r', 'w', 'c' or 'n'");
304 return NULL;
306 return newdbmobject(name, iflags, mode);
309 static PyMethodDef dbmmodule_methods[] = {
310 { "open", (PyCFunction)dbmopen, 1 },
311 { 0, 0 },
314 DL_EXPORT(void)
315 initdbm() {
316 PyObject *m, *d;
318 m = Py_InitModule("dbm", dbmmodule_methods);
319 d = PyModule_GetDict(m);
320 DbmError = PyErr_NewException("dbm.error", NULL, NULL);
321 if (DbmError != NULL)
322 PyDict_SetItemString(d, "error", DbmError);