1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
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
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 */
33 /* Author: Anthony Baxter, after dbmmodule.c */
34 /* Doc strings: Mitch Chapman */
39 #include <sys/types.h>
45 #include "gdbmerrno.h"
46 extern const char * gdbm_strerror(gdbm_error
);
49 static char gdbmmodule__doc__
[] = "\
50 This module provides an interface to the GNU DBM (GDBM) library.\n\
52 This module is quite similar to the dbm module, but uses GDBM instead to\n\
53 provide some additional functionality. Please note that the file formats\n\
54 created by GDBM and dbm are incompatible. \n\
56 GDBM objects behave like mappings (dictionaries), except that keys and\n\
57 values are always strings. Printing a GDBM object doesn't print the\n\
58 keys and values, and the items() and values() methods are not\n\
63 int di_size
; /* -1 means recompute */
67 staticforward PyTypeObject Dbmtype
;
69 #define is_dbmobject(v) ((v)->ob_type == &Dbmtype)
70 #define check_dbmobject_open(v) if ((v)->di_dbm == NULL) \
71 { PyErr_SetString(DbmError, "GDBM object has already been closed"); \
76 static PyObject
*DbmError
;
78 static char gdbm_object__doc__
[] = "\
79 This object represents a GDBM database.\n\
80 GDBM objects behave like mappings (dictionaries), except that keys and\n\
81 values are always strings. Printing a GDBM object doesn't print the\n\
82 keys and values, and the items() and values() methods are not\n\
85 GDBM objects also support additional operations such as firstkey,\n\
86 nextkey, reorganize, and sync.";
89 newdbmobject(file
, flags
, mode
)
96 dp
= PyObject_NEW(dbmobject
, &Dbmtype
);
101 if ( (dp
->di_dbm
= gdbm_open(file
, 0, flags
, mode
, NULL
)) == 0 ) {
103 PyErr_SetFromErrno(DbmError
);
105 PyErr_SetString(DbmError
, gdbm_strerror(gdbm_errno
));
109 return (PyObject
*)dp
;
116 register dbmobject
*dp
;
119 gdbm_close(dp
->di_dbm
);
127 if (dp
->di_dbm
== NULL
) {
128 PyErr_SetString(DbmError
, "GDBM object has already been closed");
131 if ( dp
->di_size
< 0 ) {
137 for ( key
=gdbm_firstkey(dp
->di_dbm
); key
.dptr
;
138 key
= gdbm_nextkey(dp
->di_dbm
,okey
)) {
140 if(okey
.dsize
) free(okey
.dptr
);
149 dbm_subscript(dp
, key
)
151 register PyObject
*key
;
156 if (!PyArg_Parse(key
, "s#", &krec
.dptr
, &krec
.dsize
) )
159 if (dp
->di_dbm
== NULL
) {
160 PyErr_SetString(DbmError
,
161 "GDBM object has already been closed");
164 drec
= gdbm_fetch(dp
->di_dbm
, krec
);
165 if ( drec
.dptr
== 0 ) {
166 PyErr_SetString(PyExc_KeyError
,
167 PyString_AS_STRING((PyStringObject
*)key
));
170 v
= PyString_FromStringAndSize(drec
.dptr
, drec
.dsize
);
176 dbm_ass_sub(dp
, v
, w
)
182 if ( !PyArg_Parse(v
, "s#", &krec
.dptr
, &krec
.dsize
) ) {
183 PyErr_SetString(PyExc_TypeError
,
184 "gdbm mappings have string indices only");
187 if (dp
->di_dbm
== NULL
) {
188 PyErr_SetString(DbmError
,
189 "GDBM object has already been closed");
194 if ( gdbm_delete(dp
->di_dbm
, krec
) < 0 ) {
195 PyErr_SetString(PyExc_KeyError
,
196 PyString_AS_STRING((PyStringObject
*)v
));
200 if ( !PyArg_Parse(w
, "s#", &drec
.dptr
, &drec
.dsize
) ) {
201 PyErr_SetString(PyExc_TypeError
,
202 "gdbm mappings have string elements only");
206 if ( gdbm_store(dp
->di_dbm
, krec
, drec
, GDBM_REPLACE
) < 0 ) {
208 PyErr_SetFromErrno(DbmError
);
210 PyErr_SetString(DbmError
,
211 gdbm_strerror(gdbm_errno
));
218 static PyMappingMethods dbm_as_mapping
= {
219 (inquiry
)dbm_length
, /*mp_length*/
220 (binaryfunc
)dbm_subscript
, /*mp_subscript*/
221 (objobjargproc
)dbm_ass_sub
, /*mp_ass_subscript*/
224 static char dbm_close__doc__
[] = "\
226 Closes the database.";
230 register dbmobject
*dp
;
233 if ( !PyArg_NoArgs(args
) )
236 gdbm_close(dp
->di_dbm
);
242 static char dbm_keys__doc__
[] = "\
243 keys() -> list_of_keys\n\
244 Get a list of all keys in the database.";
248 register dbmobject
*dp
;
251 register PyObject
*v
, *item
;
255 if (dp
== NULL
|| !is_dbmobject(dp
)) {
256 PyErr_BadInternalCall();
260 if (!PyArg_NoArgs(args
))
263 check_dbmobject_open(dp
);
269 key
= gdbm_firstkey(dp
->di_dbm
);
271 item
= PyString_FromStringAndSize(key
.dptr
, key
.dsize
);
277 err
= PyList_Append(v
, item
);
284 nextkey
= gdbm_nextkey(dp
->di_dbm
, key
);
292 static char dbm_has_key__doc__
[] = "\
293 has_key(key) -> boolean\n\
294 Find out whether or not the database contains a given key.";
297 dbm_has_key(dp
, args
)
298 register dbmobject
*dp
;
303 if (!PyArg_Parse(args
, "s#", &key
.dptr
, &key
.dsize
))
305 check_dbmobject_open(dp
);
306 return PyInt_FromLong((long) gdbm_exists(dp
->di_dbm
, key
));
309 static char dbm_firstkey__doc__
[] = "\
311 It's possible to loop over every key in the database using this method\n\
312 and the nextkey() method. The traversal is ordered by GDBM's internal\n\
313 hash values, and won't be sorted by the key values. This method\n\
314 returns the starting key.";
317 dbm_firstkey(dp
, args
)
318 register dbmobject
*dp
;
321 register PyObject
*v
;
324 if (!PyArg_NoArgs(args
))
326 check_dbmobject_open(dp
);
327 key
= gdbm_firstkey(dp
->di_dbm
);
329 v
= PyString_FromStringAndSize(key
.dptr
, key
.dsize
);
338 static char dbm_nextkey__doc__
[] = "\
339 nextkey(key) -> next_key\n\
340 Returns the key that follows key in the traversal.\n\
341 The following code prints every key in the database db, without having\n\
342 to create a list in memory that contains them all:\n\
350 dbm_nextkey(dp
, args
)
351 register dbmobject
*dp
;
354 register PyObject
*v
;
357 if (!PyArg_Parse(args
, "s#", &key
.dptr
, &key
.dsize
))
359 check_dbmobject_open(dp
);
360 nextkey
= gdbm_nextkey(dp
->di_dbm
, key
);
362 v
= PyString_FromStringAndSize(nextkey
.dptr
, nextkey
.dsize
);
371 static char dbm_reorganize__doc__
[] = "\
372 reorganize() -> None\n\
373 If you have carried out a lot of deletions and would like to shrink\n\
374 the space used by the GDBM file, this routine will reorganize the\n\
375 database. GDBM will not shorten the length of a database file except\n\
376 by using this reorganization; otherwise, deleted file space will be\n\
377 kept and reused as new (key,value) pairs are added.";
380 dbm_reorganize(dp
, args
)
381 register dbmobject
*dp
;
384 if (!PyArg_NoArgs(args
))
386 check_dbmobject_open(dp
);
388 if (gdbm_reorganize(dp
->di_dbm
) < 0) {
390 PyErr_SetFromErrno(DbmError
);
392 PyErr_SetString(DbmError
, gdbm_strerror(gdbm_errno
));
399 static char dbm_sync__doc__
[] = "\
401 When the database has been opened in fast mode, this method forces\n\
402 any unwritten data to be written to the disk.";
406 register dbmobject
*dp
;
409 if (!PyArg_NoArgs(args
))
411 check_dbmobject_open(dp
);
412 gdbm_sync(dp
->di_dbm
);
417 static PyMethodDef dbm_methods
[] = {
418 {"close", (PyCFunction
)dbm_close
, 0, dbm_close__doc__
},
419 {"keys", (PyCFunction
)dbm_keys
, 0, dbm_keys__doc__
},
420 {"has_key", (PyCFunction
)dbm_has_key
, 0, dbm_has_key__doc__
},
421 {"firstkey", (PyCFunction
)dbm_firstkey
, 0, dbm_firstkey__doc__
},
422 {"nextkey", (PyCFunction
)dbm_nextkey
, 0, dbm_nextkey__doc__
},
423 {"reorganize", (PyCFunction
)dbm_reorganize
, 0, dbm_reorganize__doc__
},
424 {"sync", (PyCFunction
)dbm_sync
, 0, dbm_sync__doc__
},
425 {NULL
, NULL
} /* sentinel */
429 dbm_getattr(dp
, name
)
433 return Py_FindMethod(dbm_methods
, (PyObject
*)dp
, name
);
436 static PyTypeObject Dbmtype
= {
437 PyObject_HEAD_INIT(0)
442 (destructor
)dbm_dealloc
, /*tp_dealloc*/
444 (getattrfunc
)dbm_getattr
, /*tp_getattr*/
449 0, /*tp_as_sequence*/
450 &dbm_as_mapping
, /*tp_as_mapping*/
458 gdbm_object__doc__
, /*tp_doc*/
461 /* ----------------------------------------------------------------- */
463 static char dbmopen__doc__
[] = "\
464 open(filename, [flag, [mode]]) -> dbm_object\n\
465 Open a dbm database and return a dbm object. The filename argument is\n\
466 the name of the database file.\n\
468 The optional flag argument can be 'r' (to open an existing database\n\
469 for reading only -- default), 'w' (to open an existing database for\n\
470 reading and writing), 'c' (which creates the database if it doesn't\n\
471 exist), or 'n' (which always creates a new empty database).\n\
473 Appending f to the flag opens the database in fast mode; altered\n\
474 data will not automatically be written to the disk after every\n\
475 change. This results in faster writes to the database, but may\n\
476 result in an inconsistent database if the program crashes while the\n\
477 database is still open. Use the sync() method to force any\n\
478 unwritten data to be written to the disk.\n\
480 The optional mode argument is the Unix mode of the file, used only\n\
481 when the database has to be created. It defaults to octal 0666. ";
493 if ( !PyArg_ParseTuple(args
, "s|si", &name
, &flags
, &mode
) )
497 iflags
= GDBM_READER
;
500 iflags
= GDBM_WRITER
;
503 iflags
= GDBM_WRCREAT
;
509 PyErr_SetString(DbmError
,
510 "Flags should be one of 'r', 'w', 'c' or 'n'");
515 return newdbmobject(name
, iflags
, mode
);
518 static PyMethodDef dbmmodule_methods
[] = {
519 { "open", (PyCFunction
)dbmopen
, 1, dbmopen__doc__
},
527 Dbmtype
.ob_type
= &PyType_Type
;
528 m
= Py_InitModule4("gdbm", dbmmodule_methods
,
529 gdbmmodule__doc__
, (PyObject
*)NULL
,
531 d
= PyModule_GetDict(m
);
532 DbmError
= PyErr_NewException("gdbm.error", NULL
, NULL
);
533 if (DbmError
!= NULL
)
534 PyDict_SetItemString(d
, "error", DbmError
);