Bump version to 0.9.1.
[python/dscho.git] / Modules / dbmmodule.c
blobb95c0ba8534335c940f263ce059fc5dae24aa014
1 /***********************************************************
2 Copyright (c) 2000, BeOpen.com.
3 Copyright (c) 1995-2000, Corporation for National Research Initiatives.
4 Copyright (c) 1990-1995, Stichting Mathematisch Centrum.
5 All rights reserved.
7 See the file "Misc/COPYRIGHT" for information on usage and
8 redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
9 ******************************************************************/
11 /* DBM module using dictionary interface */
14 #include "Python.h"
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <fcntl.h>
19 #include <ndbm.h>
21 typedef struct {
22 PyObject_HEAD
23 int di_size; /* -1 means recompute */
24 DBM *di_dbm;
25 } dbmobject;
27 staticforward PyTypeObject Dbmtype;
29 #define is_dbmobject(v) ((v)->ob_type == &Dbmtype)
30 #define check_dbmobject_open(v) if ((v)->di_dbm == NULL) \
31 { PyErr_SetString(DbmError, "DBM object has already been closed"); \
32 return NULL; }
34 static PyObject *DbmError;
36 static PyObject *
37 newdbmobject(char *file, int flags, int mode)
39 dbmobject *dp;
41 dp = PyObject_New(dbmobject, &Dbmtype);
42 if (dp == NULL)
43 return NULL;
44 dp->di_size = -1;
45 if ( (dp->di_dbm = dbm_open(file, flags, mode)) == 0 ) {
46 PyErr_SetFromErrno(DbmError);
47 Py_DECREF(dp);
48 return NULL;
50 return (PyObject *)dp;
53 /* Methods */
55 static void
56 dbm_dealloc(register dbmobject *dp)
58 if ( dp->di_dbm )
59 dbm_close(dp->di_dbm);
60 PyObject_Del(dp);
63 static int
64 dbm_length(dbmobject *dp)
66 if (dp->di_dbm == NULL) {
67 PyErr_SetString(DbmError, "DBM object has already been closed");
68 return -1;
70 if ( dp->di_size < 0 ) {
71 datum key;
72 int size;
74 size = 0;
75 for ( key=dbm_firstkey(dp->di_dbm); key.dptr;
76 key = dbm_nextkey(dp->di_dbm))
77 size++;
78 dp->di_size = size;
80 return dp->di_size;
83 static PyObject *
84 dbm_subscript(dbmobject *dp, register PyObject *key)
86 datum drec, krec;
88 if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize) )
89 return NULL;
91 check_dbmobject_open(dp);
92 drec = dbm_fetch(dp->di_dbm, krec);
93 if ( drec.dptr == 0 ) {
94 PyErr_SetString(PyExc_KeyError,
95 PyString_AS_STRING((PyStringObject *)key));
96 return NULL;
98 if ( dbm_error(dp->di_dbm) ) {
99 dbm_clearerr(dp->di_dbm);
100 PyErr_SetString(DbmError, "");
101 return NULL;
103 return PyString_FromStringAndSize(drec.dptr, drec.dsize);
106 static int
107 dbm_ass_sub(dbmobject *dp, PyObject *v, PyObject *w)
109 datum krec, drec;
111 if ( !PyArg_Parse(v, "s#", &krec.dptr, &krec.dsize) ) {
112 PyErr_SetString(PyExc_TypeError,
113 "dbm mappings have string indices only");
114 return -1;
116 if (dp->di_dbm == NULL) {
117 PyErr_SetString(DbmError, "DBM object has already been closed");
118 return -1;
120 dp->di_size = -1;
121 if (w == NULL) {
122 if ( dbm_delete(dp->di_dbm, krec) < 0 ) {
123 dbm_clearerr(dp->di_dbm);
124 PyErr_SetString(PyExc_KeyError,
125 PyString_AS_STRING((PyStringObject *)v));
126 return -1;
128 } else {
129 if ( !PyArg_Parse(w, "s#", &drec.dptr, &drec.dsize) ) {
130 PyErr_SetString(PyExc_TypeError,
131 "dbm mappings have string elements only");
132 return -1;
134 if ( dbm_store(dp->di_dbm, krec, drec, DBM_REPLACE) < 0 ) {
135 dbm_clearerr(dp->di_dbm);
136 PyErr_SetString(DbmError,
137 "Cannot add item to database");
138 return -1;
141 if ( dbm_error(dp->di_dbm) ) {
142 dbm_clearerr(dp->di_dbm);
143 PyErr_SetString(DbmError, "");
144 return -1;
146 return 0;
149 static PyMappingMethods dbm_as_mapping = {
150 (inquiry)dbm_length, /*mp_length*/
151 (binaryfunc)dbm_subscript, /*mp_subscript*/
152 (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
155 static PyObject *
156 dbm__close(register dbmobject *dp, PyObject *args)
158 if ( !PyArg_NoArgs(args) )
159 return NULL;
160 if ( dp->di_dbm )
161 dbm_close(dp->di_dbm);
162 dp->di_dbm = NULL;
163 Py_INCREF(Py_None);
164 return Py_None;
167 static PyObject *
168 dbm_keys(register dbmobject *dp, PyObject *args)
170 register PyObject *v, *item;
171 datum key;
172 int err;
174 if (!PyArg_NoArgs(args))
175 return NULL;
176 check_dbmobject_open(dp);
177 v = PyList_New(0);
178 if (v == NULL)
179 return NULL;
180 for (key = dbm_firstkey(dp->di_dbm); key.dptr;
181 key = dbm_nextkey(dp->di_dbm)) {
182 item = PyString_FromStringAndSize(key.dptr, key.dsize);
183 if (item == NULL) {
184 Py_DECREF(v);
185 return NULL;
187 err = PyList_Append(v, item);
188 Py_DECREF(item);
189 if (err != 0) {
190 Py_DECREF(v);
191 return NULL;
194 return v;
197 static PyObject *
198 dbm_has_key(register dbmobject *dp, PyObject *args)
200 datum key, val;
202 if (!PyArg_Parse(args, "s#", &key.dptr, &key.dsize))
203 return NULL;
204 check_dbmobject_open(dp);
205 val = dbm_fetch(dp->di_dbm, key);
206 return PyInt_FromLong(val.dptr != NULL);
209 static PyMethodDef dbm_methods[] = {
210 {"close", (PyCFunction)dbm__close},
211 {"keys", (PyCFunction)dbm_keys},
212 {"has_key", (PyCFunction)dbm_has_key},
213 {NULL, NULL} /* sentinel */
216 static PyObject *
217 dbm_getattr(dbmobject *dp, char *name)
219 return Py_FindMethod(dbm_methods, (PyObject *)dp, name);
222 static PyTypeObject Dbmtype = {
223 PyObject_HEAD_INIT(&PyType_Type)
225 "dbm",
226 sizeof(dbmobject),
228 (destructor)dbm_dealloc, /*tp_dealloc*/
229 0, /*tp_print*/
230 (getattrfunc)dbm_getattr, /*tp_getattr*/
231 0, /*tp_setattr*/
232 0, /*tp_compare*/
233 0, /*tp_repr*/
234 0, /*tp_as_number*/
235 0, /*tp_as_sequence*/
236 &dbm_as_mapping, /*tp_as_mapping*/
239 /* ----------------------------------------------------------------- */
241 static PyObject *
242 dbmopen(PyObject *self, PyObject *args)
244 char *name;
245 char *flags = "r";
246 int iflags;
247 int mode = 0666;
249 if ( !PyArg_ParseTuple(args, "s|si:open", &name, &flags, &mode) )
250 return NULL;
251 if ( strcmp(flags, "r") == 0 )
252 iflags = O_RDONLY;
253 else if ( strcmp(flags, "w") == 0 )
254 iflags = O_RDWR;
255 else if ( strcmp(flags, "rw") == 0 ) /* B/W compat */
256 iflags = O_RDWR|O_CREAT;
257 else if ( strcmp(flags, "c") == 0 )
258 iflags = O_RDWR|O_CREAT;
259 else if ( strcmp(flags, "n") == 0 )
260 iflags = O_RDWR|O_CREAT|O_TRUNC;
261 else {
262 PyErr_SetString(DbmError,
263 "Flags should be one of 'r', 'w', 'c' or 'n'");
264 return NULL;
266 return newdbmobject(name, iflags, mode);
269 static PyMethodDef dbmmodule_methods[] = {
270 { "open", (PyCFunction)dbmopen, 1 },
271 { 0, 0 },
274 DL_EXPORT(void)
275 initdbm(void) {
276 PyObject *m, *d;
278 m = Py_InitModule("dbm", dbmmodule_methods);
279 d = PyModule_GetDict(m);
280 DbmError = PyErr_NewException("dbm.error", NULL, NULL);
281 if (DbmError != NULL)
282 PyDict_SetItemString(d, "error", DbmError);