2
/* DBM module using dictionary interface */
11
/* Some Linux systems install gdbm/ndbm.h, but not ndbm.h. This supports
12
* whichever configure was able to locate.
14
#if defined(HAVE_NDBM_H)
16
#if defined(PYOS_OS2) && !defined(PYCC_GCC)
17
static char *which_dbm = "ndbm";
19
static char *which_dbm = "GNU gdbm"; /* EMX port of GDBM */
21
#elif defined(HAVE_GDBM_NDBM_H)
22
#include <gdbm/ndbm.h>
23
static char *which_dbm = "GNU gdbm";
24
#elif defined(HAVE_BERKDB_H)
26
static char *which_dbm = "Berkeley DB";
28
#error "No ndbm.h available!"
33
int di_size; /* -1 means recompute */
37
static PyTypeObject Dbmtype;
39
#define is_dbmobject(v) (Py_TYPE(v) == &Dbmtype)
40
#define check_dbmobject_open(v) if ((v)->di_dbm == NULL) \
41
{ PyErr_SetString(DbmError, "DBM object has already been closed"); \
44
static PyObject *DbmError;
47
newdbmobject(char *file, int flags, int mode)
51
dp = PyObject_New(dbmobject, &Dbmtype);
55
if ( (dp->di_dbm = dbm_open(file, flags, mode)) == 0 ) {
56
PyErr_SetFromErrno(DbmError);
60
return (PyObject *)dp;
66
dbm_dealloc(register dbmobject *dp)
69
dbm_close(dp->di_dbm);
74
dbm_length(dbmobject *dp)
76
if (dp->di_dbm == NULL) {
77
PyErr_SetString(DbmError, "DBM object has already been closed");
80
if ( dp->di_size < 0 ) {
85
for ( key=dbm_firstkey(dp->di_dbm); key.dptr;
86
key = dbm_nextkey(dp->di_dbm))
94
dbm_subscript(dbmobject *dp, register PyObject *key)
99
if (!PyArg_Parse(key, "s#", &krec.dptr, &tmp_size) )
102
krec.dsize = tmp_size;
103
check_dbmobject_open(dp);
104
drec = dbm_fetch(dp->di_dbm, krec);
105
if ( drec.dptr == 0 ) {
106
PyErr_SetString(PyExc_KeyError,
107
PyString_AS_STRING((PyStringObject *)key));
110
if ( dbm_error(dp->di_dbm) ) {
111
dbm_clearerr(dp->di_dbm);
112
PyErr_SetString(DbmError, "");
115
return PyString_FromStringAndSize(drec.dptr, drec.dsize);
119
dbm_ass_sub(dbmobject *dp, PyObject *v, PyObject *w)
124
if ( !PyArg_Parse(v, "s#", &krec.dptr, &tmp_size) ) {
125
PyErr_SetString(PyExc_TypeError,
126
"dbm mappings have string indices only");
129
krec.dsize = tmp_size;
130
if (dp->di_dbm == NULL) {
131
PyErr_SetString(DbmError, "DBM object has already been closed");
136
if ( dbm_delete(dp->di_dbm, krec) < 0 ) {
137
dbm_clearerr(dp->di_dbm);
138
PyErr_SetString(PyExc_KeyError,
139
PyString_AS_STRING((PyStringObject *)v));
143
if ( !PyArg_Parse(w, "s#", &drec.dptr, &tmp_size) ) {
144
PyErr_SetString(PyExc_TypeError,
145
"dbm mappings have string elements only");
148
drec.dsize = tmp_size;
149
if ( dbm_store(dp->di_dbm, krec, drec, DBM_REPLACE) < 0 ) {
150
dbm_clearerr(dp->di_dbm);
151
PyErr_SetString(DbmError,
152
"cannot add item to database");
156
if ( dbm_error(dp->di_dbm) ) {
157
dbm_clearerr(dp->di_dbm);
158
PyErr_SetString(DbmError, "");
165
dbm_contains(register dbmobject *dp, PyObject *v)
169
if (PyString_AsStringAndSize(v, (char **)&key.dptr,
170
(Py_ssize_t *)&key.dsize)) {
174
/* Expand check_dbmobject_open to return -1 */
175
if (dp->di_dbm == NULL) {
176
PyErr_SetString(DbmError, "DBM object has already been closed");
179
val = dbm_fetch(dp->di_dbm, key);
180
return val.dptr != NULL;
183
static PySequenceMethods dbm_as_sequence = {
184
(lenfunc)dbm_length, /*_length*/
191
(objobjproc)dbm_contains, /*sq_contains*/
192
0, /*sq_inplace_concat*/
193
0 /*sq_inplace_repeat*/
196
static PyMappingMethods dbm_as_mapping = {
197
(lenfunc)dbm_length, /*mp_length*/
198
(binaryfunc)dbm_subscript, /*mp_subscript*/
199
(objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
203
dbm__close(register dbmobject *dp, PyObject *unused)
206
dbm_close(dp->di_dbm);
213
dbm_keys(register dbmobject *dp, PyObject *unused)
215
register PyObject *v, *item;
219
check_dbmobject_open(dp);
223
for (key = dbm_firstkey(dp->di_dbm); key.dptr;
224
key = dbm_nextkey(dp->di_dbm)) {
225
item = PyString_FromStringAndSize(key.dptr, key.dsize);
230
err = PyList_Append(v, item);
241
dbm_has_key(register dbmobject *dp, PyObject *args)
247
if (!PyArg_ParseTuple(args, "s#:has_key", &tmp_ptr, &tmp_size))
250
key.dsize = tmp_size;
251
check_dbmobject_open(dp);
252
val = dbm_fetch(dp->di_dbm, key);
253
return PyInt_FromLong(val.dptr != NULL);
257
dbm_get(register dbmobject *dp, PyObject *args)
260
PyObject *defvalue = Py_None;
264
if (!PyArg_ParseTuple(args, "s#|O:get",
265
&tmp_ptr, &tmp_size, &defvalue))
268
key.dsize = tmp_size;
269
check_dbmobject_open(dp);
270
val = dbm_fetch(dp->di_dbm, key);
271
if (val.dptr != NULL)
272
return PyString_FromStringAndSize(val.dptr, val.dsize);
280
dbm_setdefault(register dbmobject *dp, PyObject *args)
283
PyObject *defvalue = NULL;
287
if (!PyArg_ParseTuple(args, "s#|S:setdefault",
288
&tmp_ptr, &tmp_size, &defvalue))
291
key.dsize = tmp_size;
292
check_dbmobject_open(dp);
293
val = dbm_fetch(dp->di_dbm, key);
294
if (val.dptr != NULL)
295
return PyString_FromStringAndSize(val.dptr, val.dsize);
296
if (defvalue == NULL) {
297
defvalue = PyString_FromStringAndSize(NULL, 0);
298
if (defvalue == NULL)
303
val.dptr = PyString_AS_STRING(defvalue);
304
val.dsize = PyString_GET_SIZE(defvalue);
305
if (dbm_store(dp->di_dbm, key, val, DBM_INSERT) < 0) {
306
dbm_clearerr(dp->di_dbm);
307
PyErr_SetString(DbmError, "cannot add item to database");
313
static PyMethodDef dbm_methods[] = {
314
{"close", (PyCFunction)dbm__close, METH_NOARGS,
315
"close()\nClose the database."},
316
{"keys", (PyCFunction)dbm_keys, METH_NOARGS,
317
"keys() -> list\nReturn a list of all keys in the database."},
318
{"has_key", (PyCFunction)dbm_has_key, METH_VARARGS,
319
"has_key(key} -> boolean\nReturn true iff key is in the database."},
320
{"get", (PyCFunction)dbm_get, METH_VARARGS,
321
"get(key[, default]) -> value\n"
322
"Return the value for key if present, otherwise default."},
323
{"setdefault", (PyCFunction)dbm_setdefault, METH_VARARGS,
324
"setdefault(key[, default]) -> value\n"
325
"Return the value for key if present, otherwise default. If key\n"
326
"is not in the database, it is inserted with default as the value."},
327
{NULL, NULL} /* sentinel */
331
dbm_getattr(dbmobject *dp, char *name)
333
return Py_FindMethod(dbm_methods, (PyObject *)dp, name);
336
static PyTypeObject Dbmtype = {
337
PyVarObject_HEAD_INIT(NULL, 0)
341
(destructor)dbm_dealloc, /*tp_dealloc*/
343
(getattrfunc)dbm_getattr, /*tp_getattr*/
348
&dbm_as_sequence, /*tp_as_sequence*/
349
&dbm_as_mapping, /*tp_as_mapping*/
356
Py_TPFLAGS_DEFAULT, /*tp_xxx4*/
359
/* ----------------------------------------------------------------- */
362
dbmopen(PyObject *self, PyObject *args)
369
if ( !PyArg_ParseTuple(args, "s|si:open", &name, &flags, &mode) )
371
if ( strcmp(flags, "r") == 0 )
373
else if ( strcmp(flags, "w") == 0 )
375
else if ( strcmp(flags, "rw") == 0 ) /* B/W compat */
376
iflags = O_RDWR|O_CREAT;
377
else if ( strcmp(flags, "c") == 0 )
378
iflags = O_RDWR|O_CREAT;
379
else if ( strcmp(flags, "n") == 0 )
380
iflags = O_RDWR|O_CREAT|O_TRUNC;
382
PyErr_SetString(DbmError,
383
"arg 2 to open should be 'r', 'w', 'c', or 'n'");
386
return newdbmobject(name, iflags, mode);
389
static PyMethodDef dbmmodule_methods[] = {
390
{ "open", (PyCFunction)dbmopen, METH_VARARGS,
391
"open(path[, flag[, mode]]) -> mapping\n"
392
"Return a database object."},
400
Dbmtype.ob_type = &PyType_Type;
401
m = Py_InitModule("dbm", dbmmodule_methods);
404
d = PyModule_GetDict(m);
405
if (DbmError == NULL)
406
DbmError = PyErr_NewException("dbm.error", NULL, NULL);
407
s = PyString_FromString(which_dbm);
409
PyDict_SetItemString(d, "library", s);
412
if (DbmError != NULL)
413
PyDict_SetItemString(d, "error", DbmError);