blob: 1e72988625131ab7d67dd8494d30ad6575b8108e [file] [log] [blame]
Guido van Rossum4b4c6641994-08-08 08:06:37 +00001/***********************************************************
Guido van Rossumfd71b9e2000-06-30 23:50:40 +00002Copyright (c) 2000, BeOpen.com.
3Copyright (c) 1995-2000, Corporation for National Research Initiatives.
4Copyright (c) 1990-1995, Stichting Mathematisch Centrum.
5All rights reserved.
Guido van Rossum4b4c6641994-08-08 08:06:37 +00006
Guido van Rossumfd71b9e2000-06-30 23:50:40 +00007See the file "Misc/COPYRIGHT" for information on usage and
8redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
Guido van Rossum4b4c6641994-08-08 08:06:37 +00009******************************************************************/
10
11/* DBM module using dictionary interface */
Guido van Rossumbfc49e81998-03-03 22:02:24 +000012/* Author: Anthony Baxter, after dbmmodule.c */
13/* Doc strings: Mitch Chapman */
Guido van Rossum4b4c6641994-08-08 08:06:37 +000014
15
Roger E. Masseb15bef81996-12-17 19:55:33 +000016#include "Python.h"
Guido van Rossum4b4c6641994-08-08 08:06:37 +000017
18#include <sys/types.h>
19#include <sys/stat.h>
20#include <fcntl.h>
21#include "gdbm.h"
22
Guido van Rossumb6e2a991998-10-03 05:13:27 +000023#ifdef WIN32
24#include "gdbmerrno.h"
25extern const char * gdbm_strerror(gdbm_error);
26#endif
27
Guido van Rossumbfc49e81998-03-03 22:02:24 +000028static char gdbmmodule__doc__[] = "\
29This module provides an interface to the GNU DBM (GDBM) library.\n\
30\n\
31This module is quite similar to the dbm module, but uses GDBM instead to\n\
32provide some additional functionality. Please note that the file formats\n\
33created by GDBM and dbm are incompatible. \n\
34\n\
35GDBM objects behave like mappings (dictionaries), except that keys and\n\
36values are always strings. Printing a GDBM object doesn't print the\n\
37keys and values, and the items() and values() methods are not\n\
38supported.";
39
Guido van Rossum4b4c6641994-08-08 08:06:37 +000040typedef struct {
Roger E. Masseb15bef81996-12-17 19:55:33 +000041 PyObject_HEAD
Guido van Rossum4b4c6641994-08-08 08:06:37 +000042 int di_size; /* -1 means recompute */
43 GDBM_FILE di_dbm;
44} dbmobject;
45
Roger E. Masseb15bef81996-12-17 19:55:33 +000046staticforward PyTypeObject Dbmtype;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000047
48#define is_dbmobject(v) ((v)->ob_type == &Dbmtype)
Guido van Rossum77eecfa1997-07-17 22:56:01 +000049#define check_dbmobject_open(v) if ((v)->di_dbm == NULL) \
50 { PyErr_SetString(DbmError, "GDBM object has already been closed"); \
51 return NULL; }
52
53
Guido van Rossum4b4c6641994-08-08 08:06:37 +000054
Roger E. Masseb15bef81996-12-17 19:55:33 +000055static PyObject *DbmError;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000056
Guido van Rossumbfc49e81998-03-03 22:02:24 +000057static char gdbm_object__doc__[] = "\
58This object represents a GDBM database.\n\
59GDBM objects behave like mappings (dictionaries), except that keys and\n\
60values are always strings. Printing a GDBM object doesn't print the\n\
61keys and values, and the items() and values() methods are not\n\
62supported.\n\
63\n\
64GDBM objects also support additional operations such as firstkey,\n\
65nextkey, reorganize, and sync.";
66
Roger E. Masseb15bef81996-12-17 19:55:33 +000067static PyObject *
Guido van Rossum4b4c6641994-08-08 08:06:37 +000068newdbmobject(file, flags, mode)
Roger E. Masseb15bef81996-12-17 19:55:33 +000069 char *file;
70int flags;
71int mode;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000072{
73 dbmobject *dp;
74
Guido van Rossumb18618d2000-05-03 23:44:39 +000075 dp = PyObject_New(dbmobject, &Dbmtype);
Guido van Rossum4b4c6641994-08-08 08:06:37 +000076 if (dp == NULL)
77 return NULL;
78 dp->di_size = -1;
Guido van Rossumb045afc1995-03-14 15:04:40 +000079 errno = 0;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000080 if ( (dp->di_dbm = gdbm_open(file, 0, flags, mode, NULL)) == 0 ) {
Roger E. Masseb15bef81996-12-17 19:55:33 +000081 if (errno != 0)
82 PyErr_SetFromErrno(DbmError);
83 else
Guido van Rossum573788e1998-10-03 05:15:07 +000084 PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
Roger E. Masseb15bef81996-12-17 19:55:33 +000085 Py_DECREF(dp);
86 return NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000087 }
Roger E. Masseb15bef81996-12-17 19:55:33 +000088 return (PyObject *)dp;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000089}
90
91/* Methods */
92
93static void
94dbm_dealloc(dp)
95 register dbmobject *dp;
96{
97 if ( dp->di_dbm )
Roger E. Masseb15bef81996-12-17 19:55:33 +000098 gdbm_close(dp->di_dbm);
Guido van Rossumb18618d2000-05-03 23:44:39 +000099 PyObject_Del(dp);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000100}
101
102static int
103dbm_length(dp)
104 dbmobject *dp;
105{
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000106 if (dp->di_dbm == NULL) {
107 PyErr_SetString(DbmError, "GDBM object has already been closed");
108 return -1;
109 }
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000110 if ( dp->di_size < 0 ) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000111 datum key,okey;
112 int size;
113 okey.dsize=0;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000114
Roger E. Masseb15bef81996-12-17 19:55:33 +0000115 size = 0;
116 for ( key=gdbm_firstkey(dp->di_dbm); key.dptr;
117 key = gdbm_nextkey(dp->di_dbm,okey)) {
118 size++;
119 if(okey.dsize) free(okey.dptr);
120 okey=key;
121 }
122 dp->di_size = size;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000123 }
124 return dp->di_size;
125}
126
Roger E. Masseb15bef81996-12-17 19:55:33 +0000127static PyObject *
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000128dbm_subscript(dp, key)
129 dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000130register PyObject *key;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000131{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000132 PyObject *v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000133 datum drec, krec;
134
Roger E. Masseb15bef81996-12-17 19:55:33 +0000135 if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize) )
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000136 return NULL;
Fred Drakeda8d2162000-02-07 17:19:41 +0000137
138 if (dp->di_dbm == NULL) {
139 PyErr_SetString(DbmError,
140 "GDBM object has already been closed");
141 return NULL;
142 }
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000143 drec = gdbm_fetch(dp->di_dbm, krec);
144 if ( drec.dptr == 0 ) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000145 PyErr_SetString(PyExc_KeyError,
146 PyString_AS_STRING((PyStringObject *)key));
147 return NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000148 }
Roger E. Masseb15bef81996-12-17 19:55:33 +0000149 v = PyString_FromStringAndSize(drec.dptr, drec.dsize);
Guido van Rossumb045afc1995-03-14 15:04:40 +0000150 free(drec.dptr);
151 return v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000152}
153
154static int
155dbm_ass_sub(dp, v, w)
156 dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000157PyObject *v, *w;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000158{
159 datum krec, drec;
160
Roger E. Masseb15bef81996-12-17 19:55:33 +0000161 if ( !PyArg_Parse(v, "s#", &krec.dptr, &krec.dsize) ) {
162 PyErr_SetString(PyExc_TypeError,
163 "gdbm mappings have string indices only");
164 return -1;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000165 }
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000166 if (dp->di_dbm == NULL) {
Fred Drakeda8d2162000-02-07 17:19:41 +0000167 PyErr_SetString(DbmError,
168 "GDBM object has already been closed");
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000169 return -1;
170 }
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000171 dp->di_size = -1;
172 if (w == NULL) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000173 if ( gdbm_delete(dp->di_dbm, krec) < 0 ) {
174 PyErr_SetString(PyExc_KeyError,
175 PyString_AS_STRING((PyStringObject *)v));
176 return -1;
177 }
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000178 } else {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000179 if ( !PyArg_Parse(w, "s#", &drec.dptr, &drec.dsize) ) {
180 PyErr_SetString(PyExc_TypeError,
181 "gdbm mappings have string elements only");
182 return -1;
183 }
184 errno = 0;
185 if ( gdbm_store(dp->di_dbm, krec, drec, GDBM_REPLACE) < 0 ) {
186 if (errno != 0)
187 PyErr_SetFromErrno(DbmError);
188 else
189 PyErr_SetString(DbmError,
Guido van Rossum573788e1998-10-03 05:15:07 +0000190 gdbm_strerror(gdbm_errno));
Roger E. Masseb15bef81996-12-17 19:55:33 +0000191 return -1;
192 }
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000193 }
194 return 0;
195}
196
Roger E. Masseb15bef81996-12-17 19:55:33 +0000197static PyMappingMethods dbm_as_mapping = {
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000198 (inquiry)dbm_length, /*mp_length*/
199 (binaryfunc)dbm_subscript, /*mp_subscript*/
200 (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
201};
202
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000203static char dbm_close__doc__[] = "\
204close() -> None\n\
Guido van Rossumcef113c1998-04-13 18:11:55 +0000205Closes the database.";
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000206
Roger E. Masseb15bef81996-12-17 19:55:33 +0000207static PyObject *
Guido van Rossum807b7be1995-07-07 22:37:11 +0000208dbm_close(dp, args)
209 register dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000210PyObject *args;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000211{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000212 if ( !PyArg_NoArgs(args) )
Guido van Rossum807b7be1995-07-07 22:37:11 +0000213 return NULL;
214 if ( dp->di_dbm )
215 gdbm_close(dp->di_dbm);
216 dp->di_dbm = NULL;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000217 Py_INCREF(Py_None);
218 return Py_None;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000219}
220
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000221static char dbm_keys__doc__[] = "\
222keys() -> list_of_keys\n\
223Get a list of all keys in the database.";
224
Roger E. Masseb15bef81996-12-17 19:55:33 +0000225static PyObject *
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000226dbm_keys(dp, args)
227 register dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000228PyObject *args;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000229{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000230 register PyObject *v, *item;
Guido van Rossum3be71401996-07-21 02:32:44 +0000231 datum key, nextkey;
Guido van Rossum66017aa1995-08-28 02:58:00 +0000232 int err;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000233
234 if (dp == NULL || !is_dbmobject(dp)) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000235 PyErr_BadInternalCall();
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000236 return NULL;
237 }
Guido van Rossum3be71401996-07-21 02:32:44 +0000238
Roger E. Masseb15bef81996-12-17 19:55:33 +0000239 if (!PyArg_NoArgs(args))
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000240 return NULL;
Guido van Rossum3be71401996-07-21 02:32:44 +0000241
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000242 check_dbmobject_open(dp);
243
Roger E. Masseb15bef81996-12-17 19:55:33 +0000244 v = PyList_New(0);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000245 if (v == NULL)
246 return NULL;
Guido van Rossum3be71401996-07-21 02:32:44 +0000247
248 key = gdbm_firstkey(dp->di_dbm);
249 while (key.dptr) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000250 item = PyString_FromStringAndSize(key.dptr, key.dsize);
251 if (item == NULL) {
252 free(key.dptr);
253 Py_DECREF(v);
254 return NULL;
255 }
256 err = PyList_Append(v, item);
257 Py_DECREF(item);
258 if (err != 0) {
259 free(key.dptr);
260 Py_DECREF(v);
261 return NULL;
262 }
263 nextkey = gdbm_nextkey(dp->di_dbm, key);
Guido van Rossum3be71401996-07-21 02:32:44 +0000264 free(key.dptr);
Roger E. Masseb15bef81996-12-17 19:55:33 +0000265 key = nextkey;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000266 }
Guido van Rossum3be71401996-07-21 02:32:44 +0000267
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000268 return v;
269}
270
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000271static char dbm_has_key__doc__[] = "\
272has_key(key) -> boolean\n\
273Find out whether or not the database contains a given key.";
274
Roger E. Masseb15bef81996-12-17 19:55:33 +0000275static PyObject *
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000276dbm_has_key(dp, args)
277 register dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000278PyObject *args;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000279{
Guido van Rossumb045afc1995-03-14 15:04:40 +0000280 datum key;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000281
Roger E. Masseb15bef81996-12-17 19:55:33 +0000282 if (!PyArg_Parse(args, "s#", &key.dptr, &key.dsize))
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000283 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000284 check_dbmobject_open(dp);
Roger E. Masseb15bef81996-12-17 19:55:33 +0000285 return PyInt_FromLong((long) gdbm_exists(dp->di_dbm, key));
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000286}
287
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000288static char dbm_firstkey__doc__[] = "\
289firstkey() -> key\n\
290It's possible to loop over every key in the database using this method\n\
291and the nextkey() method. The traversal is ordered by GDBM's internal\n\
292hash values, and won't be sorted by the key values. This method\n\
293returns the starting key.";
294
Roger E. Masseb15bef81996-12-17 19:55:33 +0000295static PyObject *
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000296dbm_firstkey(dp, args)
297 register dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000298PyObject *args;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000299{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000300 register PyObject *v;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000301 datum key;
302
Roger E. Masseb15bef81996-12-17 19:55:33 +0000303 if (!PyArg_NoArgs(args))
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000304 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000305 check_dbmobject_open(dp);
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000306 key = gdbm_firstkey(dp->di_dbm);
307 if (key.dptr) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000308 v = PyString_FromStringAndSize(key.dptr, key.dsize);
309 free(key.dptr);
310 return v;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000311 } else {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000312 Py_INCREF(Py_None);
313 return Py_None;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000314 }
315}
316
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000317static char dbm_nextkey__doc__[] = "\
318nextkey(key) -> next_key\n\
319Returns the key that follows key in the traversal.\n\
320The following code prints every key in the database db, without having\n\
321to create a list in memory that contains them all:\n\
322\n\
323 k = db.firstkey()\n\
324 while k != None:\n\
325 print k\n\
326 k = db.nextkey(k)";
327
Roger E. Masseb15bef81996-12-17 19:55:33 +0000328static PyObject *
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000329dbm_nextkey(dp, args)
330 register dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000331PyObject *args;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000332{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000333 register PyObject *v;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000334 datum key, nextkey;
335
Roger E. Masseb15bef81996-12-17 19:55:33 +0000336 if (!PyArg_Parse(args, "s#", &key.dptr, &key.dsize))
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000337 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000338 check_dbmobject_open(dp);
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000339 nextkey = gdbm_nextkey(dp->di_dbm, key);
340 if (nextkey.dptr) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000341 v = PyString_FromStringAndSize(nextkey.dptr, nextkey.dsize);
342 free(nextkey.dptr);
343 return v;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000344 } else {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000345 Py_INCREF(Py_None);
346 return Py_None;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000347 }
348}
349
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000350static char dbm_reorganize__doc__[] = "\
351reorganize() -> None\n\
352If you have carried out a lot of deletions and would like to shrink\n\
353the space used by the GDBM file, this routine will reorganize the\n\
354database. GDBM will not shorten the length of a database file except\n\
355by using this reorganization; otherwise, deleted file space will be\n\
356kept and reused as new (key,value) pairs are added.";
357
Roger E. Masseb15bef81996-12-17 19:55:33 +0000358static PyObject *
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000359dbm_reorganize(dp, args)
360 register dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000361PyObject *args;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000362{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000363 if (!PyArg_NoArgs(args))
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000364 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000365 check_dbmobject_open(dp);
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000366 errno = 0;
367 if (gdbm_reorganize(dp->di_dbm) < 0) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000368 if (errno != 0)
369 PyErr_SetFromErrno(DbmError);
370 else
Guido van Rossum573788e1998-10-03 05:15:07 +0000371 PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
Roger E. Masseb15bef81996-12-17 19:55:33 +0000372 return NULL;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000373 }
Roger E. Masseb15bef81996-12-17 19:55:33 +0000374 Py_INCREF(Py_None);
375 return Py_None;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000376}
377
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000378static char dbm_sync__doc__[] = "\
379sync() -> None\n\
380When the database has been opened in fast mode, this method forces\n\
381any unwritten data to be written to the disk.";
382
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000383static PyObject *
384dbm_sync(dp, args)
385 register dbmobject *dp;
386 PyObject *args;
387{
388 if (!PyArg_NoArgs(args))
389 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000390 check_dbmobject_open(dp);
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000391 gdbm_sync(dp->di_dbm);
392 Py_INCREF(Py_None);
393 return Py_None;
394}
395
Roger E. Masseb15bef81996-12-17 19:55:33 +0000396static PyMethodDef dbm_methods[] = {
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000397 {"close", (PyCFunction)dbm_close, 0, dbm_close__doc__},
398 {"keys", (PyCFunction)dbm_keys, 0, dbm_keys__doc__},
399 {"has_key", (PyCFunction)dbm_has_key, 0, dbm_has_key__doc__},
400 {"firstkey", (PyCFunction)dbm_firstkey, 0, dbm_firstkey__doc__},
401 {"nextkey", (PyCFunction)dbm_nextkey, 0, dbm_nextkey__doc__},
402 {"reorganize", (PyCFunction)dbm_reorganize, 0, dbm_reorganize__doc__},
403 {"sync", (PyCFunction)dbm_sync, 0, dbm_sync__doc__},
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000404 {NULL, NULL} /* sentinel */
405};
406
Roger E. Masseb15bef81996-12-17 19:55:33 +0000407static PyObject *
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000408dbm_getattr(dp, name)
409 dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000410char *name;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000411{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000412 return Py_FindMethod(dbm_methods, (PyObject *)dp, name);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000413}
414
Roger E. Masseb15bef81996-12-17 19:55:33 +0000415static PyTypeObject Dbmtype = {
Guido van Rossumb6e2a991998-10-03 05:13:27 +0000416 PyObject_HEAD_INIT(0)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000417 0,
Guido van Rossum807b7be1995-07-07 22:37:11 +0000418 "gdbm",
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000419 sizeof(dbmobject),
420 0,
Roger E. Masseb15bef81996-12-17 19:55:33 +0000421 (destructor)dbm_dealloc, /*tp_dealloc*/
422 0, /*tp_print*/
423 (getattrfunc)dbm_getattr, /*tp_getattr*/
424 0, /*tp_setattr*/
425 0, /*tp_compare*/
426 0, /*tp_repr*/
427 0, /*tp_as_number*/
428 0, /*tp_as_sequence*/
429 &dbm_as_mapping, /*tp_as_mapping*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000430 0, /*tp_hash*/
431 0, /*tp_call*/
432 0, /*tp_str*/
433 0, /*tp_getattro*/
434 0, /*tp_setattro*/
435 0, /*tp_as_buffer*/
436 0, /*tp_xxx4*/
437 gdbm_object__doc__, /*tp_doc*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000438};
439
440/* ----------------------------------------------------------------- */
441
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000442static char dbmopen__doc__[] = "\
443open(filename, [flag, [mode]]) -> dbm_object\n\
444Open a dbm database and return a dbm object. The filename argument is\n\
445the name of the database file.\n\
446\n\
447The optional flag argument can be 'r' (to open an existing database\n\
448for reading only -- default), 'w' (to open an existing database for\n\
449reading and writing), 'c' (which creates the database if it doesn't\n\
450exist), or 'n' (which always creates a new empty database).\n\
451\n\
452Appending f to the flag opens the database in fast mode; altered\n\
453data will not automatically be written to the disk after every\n\
454change. This results in faster writes to the database, but may\n\
455result in an inconsistent database if the program crashes while the\n\
456database is still open. Use the sync() method to force any\n\
457unwritten data to be written to the disk.\n\
458\n\
459The optional mode argument is the Unix mode of the file, used only\n\
460when the database has to be created. It defaults to octal 0666. ";
461
Roger E. Masseb15bef81996-12-17 19:55:33 +0000462static PyObject *
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000463dbmopen(self, args)
Roger E. Masseb15bef81996-12-17 19:55:33 +0000464 PyObject *self;
465PyObject *args;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000466{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000467 char *name;
468 char *flags = "r ";
469 int iflags;
470 int mode = 0666;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000471
Guido van Rossum43713e52000-02-29 13:59:29 +0000472 if ( !PyArg_ParseTuple(args, "s|si:open", &name, &flags, &mode) )
Roger E. Masseb15bef81996-12-17 19:55:33 +0000473 return NULL;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000474 switch (flags[0]) {
475 case 'r':
Roger E. Masseb15bef81996-12-17 19:55:33 +0000476 iflags = GDBM_READER;
477 break;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000478 case 'w':
Roger E. Masseb15bef81996-12-17 19:55:33 +0000479 iflags = GDBM_WRITER;
480 break;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000481 case 'c':
Roger E. Masseb15bef81996-12-17 19:55:33 +0000482 iflags = GDBM_WRCREAT;
483 break;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000484 case 'n':
Roger E. Masseb15bef81996-12-17 19:55:33 +0000485 iflags = GDBM_NEWDB;
486 break;
487 default:
488 PyErr_SetString(DbmError,
489 "Flags should be one of 'r', 'w', 'c' or 'n'");
490 return NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000491 }
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000492 if (flags[1] == 'f')
Roger E. Masseb15bef81996-12-17 19:55:33 +0000493 iflags |= GDBM_FAST;
494 return newdbmobject(name, iflags, mode);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000495}
496
Roger E. Masseb15bef81996-12-17 19:55:33 +0000497static PyMethodDef dbmmodule_methods[] = {
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000498 { "open", (PyCFunction)dbmopen, 1, dbmopen__doc__},
Roger E. Masseb15bef81996-12-17 19:55:33 +0000499 { 0, 0 },
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000500};
501
Guido van Rossum3886bb61998-12-04 18:50:17 +0000502DL_EXPORT(void)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000503initgdbm() {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000504 PyObject *m, *d;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000505
Guido van Rossumb6e2a991998-10-03 05:13:27 +0000506 Dbmtype.ob_type = &PyType_Type;
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000507 m = Py_InitModule4("gdbm", dbmmodule_methods,
508 gdbmmodule__doc__, (PyObject *)NULL,
509 PYTHON_API_VERSION);
Roger E. Masseb15bef81996-12-17 19:55:33 +0000510 d = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +0000511 DbmError = PyErr_NewException("gdbm.error", NULL, NULL);
512 if (DbmError != NULL)
513 PyDict_SetItemString(d, "error", DbmError);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000514}