Minor fix for currentframe (SF #1652788).
[python.git] / Modules / gdbmmodule.c
blobcfc6abc37f5f885eb6441e59648cb683473e22ef
2 /* DBM module using dictionary interface */
3 /* Author: Anthony Baxter, after dbmmodule.c */
4 /* Doc strings: Mitch Chapman */
7 #include "Python.h"
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <fcntl.h>
12 #include "gdbm.h"
14 #if defined(WIN32) && !defined(__CYGWIN__)
15 #include "gdbmerrno.h"
16 extern const char * gdbm_strerror(gdbm_error);
17 #endif
19 PyDoc_STRVAR(gdbmmodule__doc__,
20 "This module provides an interface to the GNU DBM (GDBM) library.\n\
21 \n\
22 This module is quite similar to the dbm module, but uses GDBM instead to\n\
23 provide some additional functionality. Please note that the file formats\n\
24 created by GDBM and dbm are incompatible. \n\
25 \n\
26 GDBM objects behave like mappings (dictionaries), except that keys and\n\
27 values are always strings. Printing a GDBM object doesn't print the\n\
28 keys and values, and the items() and values() methods are not\n\
29 supported.");
31 typedef struct {
32 PyObject_HEAD
33 int di_size; /* -1 means recompute */
34 GDBM_FILE di_dbm;
35 } dbmobject;
37 static PyTypeObject Dbmtype;
39 #define is_dbmobject(v) ((v)->ob_type == &Dbmtype)
40 #define check_dbmobject_open(v) if ((v)->di_dbm == NULL) \
41 { PyErr_SetString(DbmError, "GDBM object has already been closed"); \
42 return NULL; }
46 static PyObject *DbmError;
48 PyDoc_STRVAR(gdbm_object__doc__,
49 "This object represents a GDBM database.\n\
50 GDBM objects behave like mappings (dictionaries), except that keys and\n\
51 values are always strings. Printing a GDBM object doesn't print the\n\
52 keys and values, and the items() and values() methods are not\n\
53 supported.\n\
54 \n\
55 GDBM objects also support additional operations such as firstkey,\n\
56 nextkey, reorganize, and sync.");
58 static PyObject *
59 newdbmobject(char *file, int flags, int mode)
61 dbmobject *dp;
63 dp = PyObject_New(dbmobject, &Dbmtype);
64 if (dp == NULL)
65 return NULL;
66 dp->di_size = -1;
67 errno = 0;
68 if ((dp->di_dbm = gdbm_open(file, 0, flags, mode, NULL)) == 0) {
69 if (errno != 0)
70 PyErr_SetFromErrno(DbmError);
71 else
72 PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
73 Py_DECREF(dp);
74 return NULL;
76 return (PyObject *)dp;
79 /* Methods */
81 static void
82 dbm_dealloc(register dbmobject *dp)
84 if (dp->di_dbm)
85 gdbm_close(dp->di_dbm);
86 PyObject_Del(dp);
89 static Py_ssize_t
90 dbm_length(dbmobject *dp)
92 if (dp->di_dbm == NULL) {
93 PyErr_SetString(DbmError, "GDBM object has already been closed");
94 return -1;
96 if (dp->di_size < 0) {
97 datum key,okey;
98 int size;
99 okey.dsize=0;
100 okey.dptr=NULL;
102 size = 0;
103 for (key=gdbm_firstkey(dp->di_dbm); key.dptr;
104 key = gdbm_nextkey(dp->di_dbm,okey)) {
105 size++;
106 if(okey.dsize) free(okey.dptr);
107 okey=key;
109 dp->di_size = size;
111 return dp->di_size;
114 static PyObject *
115 dbm_subscript(dbmobject *dp, register PyObject *key)
117 PyObject *v;
118 datum drec, krec;
120 if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize) )
121 return NULL;
123 if (dp->di_dbm == NULL) {
124 PyErr_SetString(DbmError,
125 "GDBM object has already been closed");
126 return NULL;
128 drec = gdbm_fetch(dp->di_dbm, krec);
129 if (drec.dptr == 0) {
130 PyErr_SetString(PyExc_KeyError,
131 PyString_AS_STRING((PyStringObject *)key));
132 return NULL;
134 v = PyString_FromStringAndSize(drec.dptr, drec.dsize);
135 free(drec.dptr);
136 return v;
139 static int
140 dbm_ass_sub(dbmobject *dp, PyObject *v, PyObject *w)
142 datum krec, drec;
144 if (!PyArg_Parse(v, "s#", &krec.dptr, &krec.dsize) ) {
145 PyErr_SetString(PyExc_TypeError,
146 "gdbm mappings have string indices only");
147 return -1;
149 if (dp->di_dbm == NULL) {
150 PyErr_SetString(DbmError,
151 "GDBM object has already been closed");
152 return -1;
154 dp->di_size = -1;
155 if (w == NULL) {
156 if (gdbm_delete(dp->di_dbm, krec) < 0) {
157 PyErr_SetString(PyExc_KeyError,
158 PyString_AS_STRING((PyStringObject *)v));
159 return -1;
162 else {
163 if (!PyArg_Parse(w, "s#", &drec.dptr, &drec.dsize)) {
164 PyErr_SetString(PyExc_TypeError,
165 "gdbm mappings have string elements only");
166 return -1;
168 errno = 0;
169 if (gdbm_store(dp->di_dbm, krec, drec, GDBM_REPLACE) < 0) {
170 if (errno != 0)
171 PyErr_SetFromErrno(DbmError);
172 else
173 PyErr_SetString(DbmError,
174 gdbm_strerror(gdbm_errno));
175 return -1;
178 return 0;
181 static PyMappingMethods dbm_as_mapping = {
182 (lenfunc)dbm_length, /*mp_length*/
183 (binaryfunc)dbm_subscript, /*mp_subscript*/
184 (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
187 PyDoc_STRVAR(dbm_close__doc__,
188 "close() -> None\n\
189 Closes the database.");
191 static PyObject *
192 dbm_close(register dbmobject *dp, PyObject *unused)
194 if (dp->di_dbm)
195 gdbm_close(dp->di_dbm);
196 dp->di_dbm = NULL;
197 Py_INCREF(Py_None);
198 return Py_None;
201 PyDoc_STRVAR(dbm_keys__doc__,
202 "keys() -> list_of_keys\n\
203 Get a list of all keys in the database.");
205 static PyObject *
206 dbm_keys(register dbmobject *dp, PyObject *unused)
208 register PyObject *v, *item;
209 datum key, nextkey;
210 int err;
212 if (dp == NULL || !is_dbmobject(dp)) {
213 PyErr_BadInternalCall();
214 return NULL;
216 check_dbmobject_open(dp);
218 v = PyList_New(0);
219 if (v == NULL)
220 return NULL;
222 key = gdbm_firstkey(dp->di_dbm);
223 while (key.dptr) {
224 item = PyString_FromStringAndSize(key.dptr, key.dsize);
225 if (item == NULL) {
226 free(key.dptr);
227 Py_DECREF(v);
228 return NULL;
230 err = PyList_Append(v, item);
231 Py_DECREF(item);
232 if (err != 0) {
233 free(key.dptr);
234 Py_DECREF(v);
235 return NULL;
237 nextkey = gdbm_nextkey(dp->di_dbm, key);
238 free(key.dptr);
239 key = nextkey;
241 return v;
244 PyDoc_STRVAR(dbm_has_key__doc__,
245 "has_key(key) -> boolean\n\
246 Find out whether or not the database contains a given key.");
248 static PyObject *
249 dbm_has_key(register dbmobject *dp, PyObject *args)
251 datum key;
253 if (!PyArg_ParseTuple(args, "s#:has_key", &key.dptr, &key.dsize))
254 return NULL;
255 check_dbmobject_open(dp);
256 return PyInt_FromLong((long) gdbm_exists(dp->di_dbm, key));
259 PyDoc_STRVAR(dbm_firstkey__doc__,
260 "firstkey() -> key\n\
261 It's possible to loop over every key in the database using this method\n\
262 and the nextkey() method. The traversal is ordered by GDBM's internal\n\
263 hash values, and won't be sorted by the key values. This method\n\
264 returns the starting key.");
266 static PyObject *
267 dbm_firstkey(register dbmobject *dp, PyObject *unused)
269 register PyObject *v;
270 datum key;
272 check_dbmobject_open(dp);
273 key = gdbm_firstkey(dp->di_dbm);
274 if (key.dptr) {
275 v = PyString_FromStringAndSize(key.dptr, key.dsize);
276 free(key.dptr);
277 return v;
279 else {
280 Py_INCREF(Py_None);
281 return Py_None;
285 PyDoc_STRVAR(dbm_nextkey__doc__,
286 "nextkey(key) -> next_key\n\
287 Returns the key that follows key in the traversal.\n\
288 The following code prints every key in the database db, without having\n\
289 to create a list in memory that contains them all:\n\
291 k = db.firstkey()\n\
292 while k != None:\n\
293 print k\n\
294 k = db.nextkey(k)");
296 static PyObject *
297 dbm_nextkey(register dbmobject *dp, PyObject *args)
299 register PyObject *v;
300 datum key, nextkey;
302 if (!PyArg_ParseTuple(args, "s#:nextkey", &key.dptr, &key.dsize))
303 return NULL;
304 check_dbmobject_open(dp);
305 nextkey = gdbm_nextkey(dp->di_dbm, key);
306 if (nextkey.dptr) {
307 v = PyString_FromStringAndSize(nextkey.dptr, nextkey.dsize);
308 free(nextkey.dptr);
309 return v;
311 else {
312 Py_INCREF(Py_None);
313 return Py_None;
317 PyDoc_STRVAR(dbm_reorganize__doc__,
318 "reorganize() -> None\n\
319 If you have carried out a lot of deletions and would like to shrink\n\
320 the space used by the GDBM file, this routine will reorganize the\n\
321 database. GDBM will not shorten the length of a database file except\n\
322 by using this reorganization; otherwise, deleted file space will be\n\
323 kept and reused as new (key,value) pairs are added.");
325 static PyObject *
326 dbm_reorganize(register dbmobject *dp, PyObject *unused)
328 check_dbmobject_open(dp);
329 errno = 0;
330 if (gdbm_reorganize(dp->di_dbm) < 0) {
331 if (errno != 0)
332 PyErr_SetFromErrno(DbmError);
333 else
334 PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
335 return NULL;
337 Py_INCREF(Py_None);
338 return Py_None;
341 PyDoc_STRVAR(dbm_sync__doc__,
342 "sync() -> None\n\
343 When the database has been opened in fast mode, this method forces\n\
344 any unwritten data to be written to the disk.");
346 static PyObject *
347 dbm_sync(register dbmobject *dp, PyObject *unused)
349 check_dbmobject_open(dp);
350 gdbm_sync(dp->di_dbm);
351 Py_INCREF(Py_None);
352 return Py_None;
355 static PyMethodDef dbm_methods[] = {
356 {"close", (PyCFunction)dbm_close, METH_NOARGS, dbm_close__doc__},
357 {"keys", (PyCFunction)dbm_keys, METH_NOARGS, dbm_keys__doc__},
358 {"has_key", (PyCFunction)dbm_has_key, METH_VARARGS, dbm_has_key__doc__},
359 {"firstkey", (PyCFunction)dbm_firstkey,METH_NOARGS, dbm_firstkey__doc__},
360 {"nextkey", (PyCFunction)dbm_nextkey, METH_VARARGS, dbm_nextkey__doc__},
361 {"reorganize",(PyCFunction)dbm_reorganize,METH_NOARGS, dbm_reorganize__doc__},
362 {"sync", (PyCFunction)dbm_sync, METH_NOARGS, dbm_sync__doc__},
363 {NULL, NULL} /* sentinel */
366 static PyObject *
367 dbm_getattr(dbmobject *dp, char *name)
369 return Py_FindMethod(dbm_methods, (PyObject *)dp, name);
372 static PyTypeObject Dbmtype = {
373 PyObject_HEAD_INIT(0)
375 "gdbm.gdbm",
376 sizeof(dbmobject),
378 (destructor)dbm_dealloc, /*tp_dealloc*/
379 0, /*tp_print*/
380 (getattrfunc)dbm_getattr, /*tp_getattr*/
381 0, /*tp_setattr*/
382 0, /*tp_compare*/
383 0, /*tp_repr*/
384 0, /*tp_as_number*/
385 0, /*tp_as_sequence*/
386 &dbm_as_mapping, /*tp_as_mapping*/
387 0, /*tp_hash*/
388 0, /*tp_call*/
389 0, /*tp_str*/
390 0, /*tp_getattro*/
391 0, /*tp_setattro*/
392 0, /*tp_as_buffer*/
393 0, /*tp_xxx4*/
394 gdbm_object__doc__, /*tp_doc*/
397 /* ----------------------------------------------------------------- */
399 PyDoc_STRVAR(dbmopen__doc__,
400 "open(filename, [flags, [mode]]) -> dbm_object\n\
401 Open a dbm database and return a dbm object. The filename argument is\n\
402 the name of the database file.\n\
404 The optional flags argument can be 'r' (to open an existing database\n\
405 for reading only -- default), 'w' (to open an existing database for\n\
406 reading and writing), 'c' (which creates the database if it doesn't\n\
407 exist), or 'n' (which always creates a new empty database).\n\
409 Some versions of gdbm support additional flags which must be\n\
410 appended to one of the flags described above. The module constant\n\
411 'open_flags' is a string of valid additional flags. The 'f' flag\n\
412 opens the database in fast mode; altered data will not automatically\n\
413 be written to the disk after every change. This results in faster\n\
414 writes to the database, but may result in an inconsistent database\n\
415 if the program crashes while the database is still open. Use the\n\
416 sync() method to force any unwritten data to be written to the disk.\n\
417 The 's' flag causes all database operations to be synchronized to\n\
418 disk. The 'u' flag disables locking of the database file.\n\
420 The optional mode argument is the Unix mode of the file, used only\n\
421 when the database has to be created. It defaults to octal 0666. ");
423 static PyObject *
424 dbmopen(PyObject *self, PyObject *args)
426 char *name;
427 char *flags = "r";
428 int iflags;
429 int mode = 0666;
431 if (!PyArg_ParseTuple(args, "s|si:open", &name, &flags, &mode))
432 return NULL;
433 switch (flags[0]) {
434 case 'r':
435 iflags = GDBM_READER;
436 break;
437 case 'w':
438 iflags = GDBM_WRITER;
439 break;
440 case 'c':
441 iflags = GDBM_WRCREAT;
442 break;
443 case 'n':
444 iflags = GDBM_NEWDB;
445 break;
446 default:
447 PyErr_SetString(DbmError,
448 "First flag must be one of 'r', 'w', 'c' or 'n'");
449 return NULL;
451 for (flags++; *flags != '\0'; flags++) {
452 char buf[40];
453 switch (*flags) {
454 #ifdef GDBM_FAST
455 case 'f':
456 iflags |= GDBM_FAST;
457 break;
458 #endif
459 #ifdef GDBM_SYNC
460 case 's':
461 iflags |= GDBM_SYNC;
462 break;
463 #endif
464 #ifdef GDBM_NOLOCK
465 case 'u':
466 iflags |= GDBM_NOLOCK;
467 break;
468 #endif
469 default:
470 PyOS_snprintf(buf, sizeof(buf), "Flag '%c' is not supported.",
471 *flags);
472 PyErr_SetString(DbmError, buf);
473 return NULL;
477 return newdbmobject(name, iflags, mode);
480 static char dbmmodule_open_flags[] = "rwcn"
481 #ifdef GDBM_FAST
483 #endif
484 #ifdef GDBM_SYNC
486 #endif
487 #ifdef GDBM_NOLOCK
489 #endif
492 static PyMethodDef dbmmodule_methods[] = {
493 { "open", (PyCFunction)dbmopen, METH_VARARGS, dbmopen__doc__},
494 { 0, 0 },
497 PyMODINIT_FUNC
498 initgdbm(void) {
499 PyObject *m, *d, *s;
501 Dbmtype.ob_type = &PyType_Type;
502 m = Py_InitModule4("gdbm", dbmmodule_methods,
503 gdbmmodule__doc__, (PyObject *)NULL,
504 PYTHON_API_VERSION);
505 if (m == NULL)
506 return;
507 d = PyModule_GetDict(m);
508 DbmError = PyErr_NewException("gdbm.error", NULL, NULL);
509 if (DbmError != NULL) {
510 PyDict_SetItemString(d, "error", DbmError);
511 s = PyString_FromString(dbmmodule_open_flags);
512 PyDict_SetItemString(d, "open_flags", s);
513 Py_DECREF(s);