The 0.5 release happened on 2/15, not on 2/14. :-)
[python/dscho.git] / Modules / gdbmmodule.c
blob31855f5e72e175f6e3b8c09241d95db6dc9587e0
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 */
33 /* Author: Anthony Baxter, after dbmmodule.c */
34 /* Doc strings: Mitch Chapman */
37 #include "Python.h"
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <fcntl.h>
42 #include "gdbm.h"
44 #ifdef WIN32
45 #include "gdbmerrno.h"
46 extern const char * gdbm_strerror(gdbm_error);
47 #endif
49 static char gdbmmodule__doc__[] = "\
50 This module provides an interface to the GNU DBM (GDBM) library.\n\
51 \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\
55 \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\
59 supported.";
61 typedef struct {
62 PyObject_HEAD
63 int di_size; /* -1 means recompute */
64 GDBM_FILE di_dbm;
65 } dbmobject;
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"); \
72 return NULL; }
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\
83 supported.\n\
84 \n\
85 GDBM objects also support additional operations such as firstkey,\n\
86 nextkey, reorganize, and sync.";
88 static PyObject *
89 newdbmobject(file, flags, mode)
90 char *file;
91 int flags;
92 int mode;
94 dbmobject *dp;
96 dp = PyObject_NEW(dbmobject, &Dbmtype);
97 if (dp == NULL)
98 return NULL;
99 dp->di_size = -1;
100 errno = 0;
101 if ( (dp->di_dbm = gdbm_open(file, 0, flags, mode, NULL)) == 0 ) {
102 if (errno != 0)
103 PyErr_SetFromErrno(DbmError);
104 else
105 PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
106 Py_DECREF(dp);
107 return NULL;
109 return (PyObject *)dp;
112 /* Methods */
114 static void
115 dbm_dealloc(dp)
116 register dbmobject *dp;
118 if ( dp->di_dbm )
119 gdbm_close(dp->di_dbm);
120 PyMem_DEL(dp);
123 static int
124 dbm_length(dp)
125 dbmobject *dp;
127 if (dp->di_dbm == NULL) {
128 PyErr_SetString(DbmError, "GDBM object has already been closed");
129 return -1;
131 if ( dp->di_size < 0 ) {
132 datum key,okey;
133 int size;
134 okey.dsize=0;
136 size = 0;
137 for ( key=gdbm_firstkey(dp->di_dbm); key.dptr;
138 key = gdbm_nextkey(dp->di_dbm,okey)) {
139 size++;
140 if(okey.dsize) free(okey.dptr);
141 okey=key;
143 dp->di_size = size;
145 return dp->di_size;
148 static PyObject *
149 dbm_subscript(dp, key)
150 dbmobject *dp;
151 register PyObject *key;
153 PyObject *v;
154 datum drec, krec;
156 if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize) )
157 return NULL;
159 if (dp->di_dbm == NULL) {
160 PyErr_SetString(DbmError,
161 "GDBM object has already been closed");
162 return NULL;
164 drec = gdbm_fetch(dp->di_dbm, krec);
165 if ( drec.dptr == 0 ) {
166 PyErr_SetString(PyExc_KeyError,
167 PyString_AS_STRING((PyStringObject *)key));
168 return NULL;
170 v = PyString_FromStringAndSize(drec.dptr, drec.dsize);
171 free(drec.dptr);
172 return v;
175 static int
176 dbm_ass_sub(dp, v, w)
177 dbmobject *dp;
178 PyObject *v, *w;
180 datum krec, drec;
182 if ( !PyArg_Parse(v, "s#", &krec.dptr, &krec.dsize) ) {
183 PyErr_SetString(PyExc_TypeError,
184 "gdbm mappings have string indices only");
185 return -1;
187 if (dp->di_dbm == NULL) {
188 PyErr_SetString(DbmError,
189 "GDBM object has already been closed");
190 return -1;
192 dp->di_size = -1;
193 if (w == NULL) {
194 if ( gdbm_delete(dp->di_dbm, krec) < 0 ) {
195 PyErr_SetString(PyExc_KeyError,
196 PyString_AS_STRING((PyStringObject *)v));
197 return -1;
199 } else {
200 if ( !PyArg_Parse(w, "s#", &drec.dptr, &drec.dsize) ) {
201 PyErr_SetString(PyExc_TypeError,
202 "gdbm mappings have string elements only");
203 return -1;
205 errno = 0;
206 if ( gdbm_store(dp->di_dbm, krec, drec, GDBM_REPLACE) < 0 ) {
207 if (errno != 0)
208 PyErr_SetFromErrno(DbmError);
209 else
210 PyErr_SetString(DbmError,
211 gdbm_strerror(gdbm_errno));
212 return -1;
215 return 0;
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__[] = "\
225 close() -> None\n\
226 Closes the database.";
228 static PyObject *
229 dbm_close(dp, args)
230 register dbmobject *dp;
231 PyObject *args;
233 if ( !PyArg_NoArgs(args) )
234 return NULL;
235 if ( dp->di_dbm )
236 gdbm_close(dp->di_dbm);
237 dp->di_dbm = NULL;
238 Py_INCREF(Py_None);
239 return Py_None;
242 static char dbm_keys__doc__[] = "\
243 keys() -> list_of_keys\n\
244 Get a list of all keys in the database.";
246 static PyObject *
247 dbm_keys(dp, args)
248 register dbmobject *dp;
249 PyObject *args;
251 register PyObject *v, *item;
252 datum key, nextkey;
253 int err;
255 if (dp == NULL || !is_dbmobject(dp)) {
256 PyErr_BadInternalCall();
257 return NULL;
260 if (!PyArg_NoArgs(args))
261 return NULL;
263 check_dbmobject_open(dp);
265 v = PyList_New(0);
266 if (v == NULL)
267 return NULL;
269 key = gdbm_firstkey(dp->di_dbm);
270 while (key.dptr) {
271 item = PyString_FromStringAndSize(key.dptr, key.dsize);
272 if (item == NULL) {
273 free(key.dptr);
274 Py_DECREF(v);
275 return NULL;
277 err = PyList_Append(v, item);
278 Py_DECREF(item);
279 if (err != 0) {
280 free(key.dptr);
281 Py_DECREF(v);
282 return NULL;
284 nextkey = gdbm_nextkey(dp->di_dbm, key);
285 free(key.dptr);
286 key = nextkey;
289 return v;
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.";
296 static PyObject *
297 dbm_has_key(dp, args)
298 register dbmobject *dp;
299 PyObject *args;
301 datum key;
303 if (!PyArg_Parse(args, "s#", &key.dptr, &key.dsize))
304 return NULL;
305 check_dbmobject_open(dp);
306 return PyInt_FromLong((long) gdbm_exists(dp->di_dbm, key));
309 static char dbm_firstkey__doc__[] = "\
310 firstkey() -> key\n\
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.";
316 static PyObject *
317 dbm_firstkey(dp, args)
318 register dbmobject *dp;
319 PyObject *args;
321 register PyObject *v;
322 datum key;
324 if (!PyArg_NoArgs(args))
325 return NULL;
326 check_dbmobject_open(dp);
327 key = gdbm_firstkey(dp->di_dbm);
328 if (key.dptr) {
329 v = PyString_FromStringAndSize(key.dptr, key.dsize);
330 free(key.dptr);
331 return v;
332 } else {
333 Py_INCREF(Py_None);
334 return Py_None;
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\
344 k = db.firstkey()\n\
345 while k != None:\n\
346 print k\n\
347 k = db.nextkey(k)";
349 static PyObject *
350 dbm_nextkey(dp, args)
351 register dbmobject *dp;
352 PyObject *args;
354 register PyObject *v;
355 datum key, nextkey;
357 if (!PyArg_Parse(args, "s#", &key.dptr, &key.dsize))
358 return NULL;
359 check_dbmobject_open(dp);
360 nextkey = gdbm_nextkey(dp->di_dbm, key);
361 if (nextkey.dptr) {
362 v = PyString_FromStringAndSize(nextkey.dptr, nextkey.dsize);
363 free(nextkey.dptr);
364 return v;
365 } else {
366 Py_INCREF(Py_None);
367 return Py_None;
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.";
379 static PyObject *
380 dbm_reorganize(dp, args)
381 register dbmobject *dp;
382 PyObject *args;
384 if (!PyArg_NoArgs(args))
385 return NULL;
386 check_dbmobject_open(dp);
387 errno = 0;
388 if (gdbm_reorganize(dp->di_dbm) < 0) {
389 if (errno != 0)
390 PyErr_SetFromErrno(DbmError);
391 else
392 PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
393 return NULL;
395 Py_INCREF(Py_None);
396 return Py_None;
399 static char dbm_sync__doc__[] = "\
400 sync() -> None\n\
401 When the database has been opened in fast mode, this method forces\n\
402 any unwritten data to be written to the disk.";
404 static PyObject *
405 dbm_sync(dp, args)
406 register dbmobject *dp;
407 PyObject *args;
409 if (!PyArg_NoArgs(args))
410 return NULL;
411 check_dbmobject_open(dp);
412 gdbm_sync(dp->di_dbm);
413 Py_INCREF(Py_None);
414 return Py_None;
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 */
428 static PyObject *
429 dbm_getattr(dp, name)
430 dbmobject *dp;
431 char *name;
433 return Py_FindMethod(dbm_methods, (PyObject *)dp, name);
436 static PyTypeObject Dbmtype = {
437 PyObject_HEAD_INIT(0)
439 "gdbm",
440 sizeof(dbmobject),
442 (destructor)dbm_dealloc, /*tp_dealloc*/
443 0, /*tp_print*/
444 (getattrfunc)dbm_getattr, /*tp_getattr*/
445 0, /*tp_setattr*/
446 0, /*tp_compare*/
447 0, /*tp_repr*/
448 0, /*tp_as_number*/
449 0, /*tp_as_sequence*/
450 &dbm_as_mapping, /*tp_as_mapping*/
451 0, /*tp_hash*/
452 0, /*tp_call*/
453 0, /*tp_str*/
454 0, /*tp_getattro*/
455 0, /*tp_setattro*/
456 0, /*tp_as_buffer*/
457 0, /*tp_xxx4*/
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. ";
483 static PyObject *
484 dbmopen(self, args)
485 PyObject *self;
486 PyObject *args;
488 char *name;
489 char *flags = "r ";
490 int iflags;
491 int mode = 0666;
493 if ( !PyArg_ParseTuple(args, "s|si", &name, &flags, &mode) )
494 return NULL;
495 switch (flags[0]) {
496 case 'r':
497 iflags = GDBM_READER;
498 break;
499 case 'w':
500 iflags = GDBM_WRITER;
501 break;
502 case 'c':
503 iflags = GDBM_WRCREAT;
504 break;
505 case 'n':
506 iflags = GDBM_NEWDB;
507 break;
508 default:
509 PyErr_SetString(DbmError,
510 "Flags should be one of 'r', 'w', 'c' or 'n'");
511 return NULL;
513 if (flags[1] == 'f')
514 iflags |= GDBM_FAST;
515 return newdbmobject(name, iflags, mode);
518 static PyMethodDef dbmmodule_methods[] = {
519 { "open", (PyCFunction)dbmopen, 1, dbmopen__doc__},
520 { 0, 0 },
523 DL_EXPORT(void)
524 initgdbm() {
525 PyObject *m, *d;
527 Dbmtype.ob_type = &PyType_Type;
528 m = Py_InitModule4("gdbm", dbmmodule_methods,
529 gdbmmodule__doc__, (PyObject *)NULL,
530 PYTHON_API_VERSION);
531 d = PyModule_GetDict(m);
532 DbmError = PyErr_NewException("gdbm.error", NULL, NULL);
533 if (DbmError != NULL)
534 PyDict_SetItemString(d, "error", DbmError);