blob: c8e3369f0751505eb2253697effca25532e2f931 [file] [log] [blame]
Guido van Rossum4b4c6641994-08-08 08:06:37 +00001/***********************************************************
Guido van Rossum524b5881995-01-04 19:10:35 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossum4b4c6641994-08-08 08:06:37 +00004
5 All Rights Reserved
6
Guido van Rossumd266eb41996-10-25 14:44:06 +00007Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
Guido van Rossum4b4c6641994-08-08 08:06:37 +00009provided that the above copyright notice appear in all copies and that
Guido van Rossumd266eb41996-10-25 14:44:06 +000010both that copyright notice and this permission notice appear in
Guido van Rossum4b4c6641994-08-08 08:06:37 +000011supporting documentation, and that the names of Stichting Mathematisch
Guido van Rossumd266eb41996-10-25 14:44:06 +000012Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
Guido van Rossum4b4c6641994-08-08 08:06:37 +000016
Guido van Rossumd266eb41996-10-25 14:44:06 +000017While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
Guido van Rossum4b4c6641994-08-08 08:06:37 +000029
30******************************************************************/
31
32/* DBM module using dictionary interface */
Guido van Rossumbfc49e81998-03-03 22:02:24 +000033/* Author: Anthony Baxter, after dbmmodule.c */
34/* Doc strings: Mitch Chapman */
Guido van Rossum4b4c6641994-08-08 08:06:37 +000035
36
Roger E. Masseb15bef81996-12-17 19:55:33 +000037#include "Python.h"
Guido van Rossum4b4c6641994-08-08 08:06:37 +000038
39#include <sys/types.h>
40#include <sys/stat.h>
41#include <fcntl.h>
42#include "gdbm.h"
43
Guido van Rossumb6e2a991998-10-03 05:13:27 +000044#ifdef WIN32
45#include "gdbmerrno.h"
46extern const char * gdbm_strerror(gdbm_error);
47#endif
48
Guido van Rossumbfc49e81998-03-03 22:02:24 +000049static char gdbmmodule__doc__[] = "\
50This module provides an interface to the GNU DBM (GDBM) library.\n\
51\n\
52This module is quite similar to the dbm module, but uses GDBM instead to\n\
53provide some additional functionality. Please note that the file formats\n\
54created by GDBM and dbm are incompatible. \n\
55\n\
56GDBM objects behave like mappings (dictionaries), except that keys and\n\
57values are always strings. Printing a GDBM object doesn't print the\n\
58keys and values, and the items() and values() methods are not\n\
59supported.";
60
Guido van Rossum4b4c6641994-08-08 08:06:37 +000061typedef struct {
Roger E. Masseb15bef81996-12-17 19:55:33 +000062 PyObject_HEAD
Guido van Rossum4b4c6641994-08-08 08:06:37 +000063 int di_size; /* -1 means recompute */
64 GDBM_FILE di_dbm;
65} dbmobject;
66
Roger E. Masseb15bef81996-12-17 19:55:33 +000067staticforward PyTypeObject Dbmtype;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000068
69#define is_dbmobject(v) ((v)->ob_type == &Dbmtype)
Guido van Rossum77eecfa1997-07-17 22:56:01 +000070#define check_dbmobject_open(v) if ((v)->di_dbm == NULL) \
71 { PyErr_SetString(DbmError, "GDBM object has already been closed"); \
72 return NULL; }
73
74
Guido van Rossum4b4c6641994-08-08 08:06:37 +000075
Roger E. Masseb15bef81996-12-17 19:55:33 +000076static PyObject *DbmError;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000077
Guido van Rossumbfc49e81998-03-03 22:02:24 +000078static char gdbm_object__doc__[] = "\
79This object represents a GDBM database.\n\
80GDBM objects behave like mappings (dictionaries), except that keys and\n\
81values are always strings. Printing a GDBM object doesn't print the\n\
82keys and values, and the items() and values() methods are not\n\
83supported.\n\
84\n\
85GDBM objects also support additional operations such as firstkey,\n\
86nextkey, reorganize, and sync.";
87
Roger E. Masseb15bef81996-12-17 19:55:33 +000088static PyObject *
Guido van Rossum4b4c6641994-08-08 08:06:37 +000089newdbmobject(file, flags, mode)
Roger E. Masseb15bef81996-12-17 19:55:33 +000090 char *file;
91int flags;
92int mode;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000093{
94 dbmobject *dp;
95
Roger E. Masseb15bef81996-12-17 19:55:33 +000096 dp = PyObject_NEW(dbmobject, &Dbmtype);
Guido van Rossum4b4c6641994-08-08 08:06:37 +000097 if (dp == NULL)
98 return NULL;
99 dp->di_size = -1;
Guido van Rossumb045afc1995-03-14 15:04:40 +0000100 errno = 0;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000101 if ( (dp->di_dbm = gdbm_open(file, 0, flags, mode, NULL)) == 0 ) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000102 if (errno != 0)
103 PyErr_SetFromErrno(DbmError);
104 else
105 PyErr_SetString(DbmError,
106 (char *) gdbm_strerror(gdbm_errno));
107 Py_DECREF(dp);
108 return NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000109 }
Roger E. Masseb15bef81996-12-17 19:55:33 +0000110 return (PyObject *)dp;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000111}
112
113/* Methods */
114
115static void
116dbm_dealloc(dp)
117 register dbmobject *dp;
118{
119 if ( dp->di_dbm )
Roger E. Masseb15bef81996-12-17 19:55:33 +0000120 gdbm_close(dp->di_dbm);
121 PyMem_DEL(dp);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000122}
123
124static int
125dbm_length(dp)
126 dbmobject *dp;
127{
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000128 if (dp->di_dbm == NULL) {
129 PyErr_SetString(DbmError, "GDBM object has already been closed");
130 return -1;
131 }
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000132 if ( dp->di_size < 0 ) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000133 datum key,okey;
134 int size;
135 okey.dsize=0;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000136
Roger E. Masseb15bef81996-12-17 19:55:33 +0000137 size = 0;
138 for ( key=gdbm_firstkey(dp->di_dbm); key.dptr;
139 key = gdbm_nextkey(dp->di_dbm,okey)) {
140 size++;
141 if(okey.dsize) free(okey.dptr);
142 okey=key;
143 }
144 dp->di_size = size;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000145 }
146 return dp->di_size;
147}
148
Roger E. Masseb15bef81996-12-17 19:55:33 +0000149static PyObject *
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000150dbm_subscript(dp, key)
151 dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000152register PyObject *key;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000153{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000154 PyObject *v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000155 datum drec, krec;
156
Roger E. Masseb15bef81996-12-17 19:55:33 +0000157 if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize) )
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000158 return NULL;
159
160 drec = gdbm_fetch(dp->di_dbm, krec);
161 if ( drec.dptr == 0 ) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000162 PyErr_SetString(PyExc_KeyError,
163 PyString_AS_STRING((PyStringObject *)key));
164 return NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000165 }
Roger E. Masseb15bef81996-12-17 19:55:33 +0000166 v = PyString_FromStringAndSize(drec.dptr, drec.dsize);
Guido van Rossumb045afc1995-03-14 15:04:40 +0000167 free(drec.dptr);
168 return v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000169}
170
171static int
172dbm_ass_sub(dp, v, w)
173 dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000174PyObject *v, *w;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000175{
176 datum krec, drec;
177
Roger E. Masseb15bef81996-12-17 19:55:33 +0000178 if ( !PyArg_Parse(v, "s#", &krec.dptr, &krec.dsize) ) {
179 PyErr_SetString(PyExc_TypeError,
180 "gdbm mappings have string indices only");
181 return -1;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000182 }
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000183 if (dp->di_dbm == NULL) {
184 PyErr_SetString(DbmError, "GDBM object has already been closed");
185 return -1;
186 }
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000187 dp->di_size = -1;
188 if (w == NULL) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000189 if ( gdbm_delete(dp->di_dbm, krec) < 0 ) {
190 PyErr_SetString(PyExc_KeyError,
191 PyString_AS_STRING((PyStringObject *)v));
192 return -1;
193 }
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000194 } else {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000195 if ( !PyArg_Parse(w, "s#", &drec.dptr, &drec.dsize) ) {
196 PyErr_SetString(PyExc_TypeError,
197 "gdbm mappings have string elements only");
198 return -1;
199 }
200 errno = 0;
201 if ( gdbm_store(dp->di_dbm, krec, drec, GDBM_REPLACE) < 0 ) {
202 if (errno != 0)
203 PyErr_SetFromErrno(DbmError);
204 else
205 PyErr_SetString(DbmError,
206 (char *) gdbm_strerror(gdbm_errno));
207 return -1;
208 }
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000209 }
210 return 0;
211}
212
Roger E. Masseb15bef81996-12-17 19:55:33 +0000213static PyMappingMethods dbm_as_mapping = {
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000214 (inquiry)dbm_length, /*mp_length*/
215 (binaryfunc)dbm_subscript, /*mp_subscript*/
216 (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
217};
218
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000219static char dbm_close__doc__[] = "\
220close() -> None\n\
Guido van Rossumcef113c1998-04-13 18:11:55 +0000221Closes the database.";
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000222
Roger E. Masseb15bef81996-12-17 19:55:33 +0000223static PyObject *
Guido van Rossum807b7be1995-07-07 22:37:11 +0000224dbm_close(dp, args)
225 register dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000226PyObject *args;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000227{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000228 if ( !PyArg_NoArgs(args) )
Guido van Rossum807b7be1995-07-07 22:37:11 +0000229 return NULL;
230 if ( dp->di_dbm )
231 gdbm_close(dp->di_dbm);
232 dp->di_dbm = NULL;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000233 Py_INCREF(Py_None);
234 return Py_None;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000235}
236
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000237static char dbm_keys__doc__[] = "\
238keys() -> list_of_keys\n\
239Get a list of all keys in the database.";
240
Roger E. Masseb15bef81996-12-17 19:55:33 +0000241static PyObject *
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000242dbm_keys(dp, args)
243 register dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000244PyObject *args;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000245{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000246 register PyObject *v, *item;
Guido van Rossum3be71401996-07-21 02:32:44 +0000247 datum key, nextkey;
Guido van Rossum66017aa1995-08-28 02:58:00 +0000248 int err;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000249
250 if (dp == NULL || !is_dbmobject(dp)) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000251 PyErr_BadInternalCall();
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000252 return NULL;
253 }
Guido van Rossum3be71401996-07-21 02:32:44 +0000254
Roger E. Masseb15bef81996-12-17 19:55:33 +0000255 if (!PyArg_NoArgs(args))
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000256 return NULL;
Guido van Rossum3be71401996-07-21 02:32:44 +0000257
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000258 check_dbmobject_open(dp);
259
Roger E. Masseb15bef81996-12-17 19:55:33 +0000260 v = PyList_New(0);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000261 if (v == NULL)
262 return NULL;
Guido van Rossum3be71401996-07-21 02:32:44 +0000263
264 key = gdbm_firstkey(dp->di_dbm);
265 while (key.dptr) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000266 item = PyString_FromStringAndSize(key.dptr, key.dsize);
267 if (item == NULL) {
268 free(key.dptr);
269 Py_DECREF(v);
270 return NULL;
271 }
272 err = PyList_Append(v, item);
273 Py_DECREF(item);
274 if (err != 0) {
275 free(key.dptr);
276 Py_DECREF(v);
277 return NULL;
278 }
279 nextkey = gdbm_nextkey(dp->di_dbm, key);
Guido van Rossum3be71401996-07-21 02:32:44 +0000280 free(key.dptr);
Roger E. Masseb15bef81996-12-17 19:55:33 +0000281 key = nextkey;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000282 }
Guido van Rossum3be71401996-07-21 02:32:44 +0000283
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000284 return v;
285}
286
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000287static char dbm_has_key__doc__[] = "\
288has_key(key) -> boolean\n\
289Find out whether or not the database contains a given key.";
290
Roger E. Masseb15bef81996-12-17 19:55:33 +0000291static PyObject *
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000292dbm_has_key(dp, args)
293 register dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000294PyObject *args;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000295{
Guido van Rossumb045afc1995-03-14 15:04:40 +0000296 datum key;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000297
Roger E. Masseb15bef81996-12-17 19:55:33 +0000298 if (!PyArg_Parse(args, "s#", &key.dptr, &key.dsize))
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000299 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000300 check_dbmobject_open(dp);
Roger E. Masseb15bef81996-12-17 19:55:33 +0000301 return PyInt_FromLong((long) gdbm_exists(dp->di_dbm, key));
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000302}
303
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000304static char dbm_firstkey__doc__[] = "\
305firstkey() -> key\n\
306It's possible to loop over every key in the database using this method\n\
307and the nextkey() method. The traversal is ordered by GDBM's internal\n\
308hash values, and won't be sorted by the key values. This method\n\
309returns the starting key.";
310
Roger E. Masseb15bef81996-12-17 19:55:33 +0000311static PyObject *
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000312dbm_firstkey(dp, args)
313 register dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000314PyObject *args;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000315{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000316 register PyObject *v;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000317 datum key;
318
Roger E. Masseb15bef81996-12-17 19:55:33 +0000319 if (!PyArg_NoArgs(args))
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000320 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000321 check_dbmobject_open(dp);
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000322 key = gdbm_firstkey(dp->di_dbm);
323 if (key.dptr) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000324 v = PyString_FromStringAndSize(key.dptr, key.dsize);
325 free(key.dptr);
326 return v;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000327 } else {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000328 Py_INCREF(Py_None);
329 return Py_None;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000330 }
331}
332
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000333static char dbm_nextkey__doc__[] = "\
334nextkey(key) -> next_key\n\
335Returns the key that follows key in the traversal.\n\
336The following code prints every key in the database db, without having\n\
337to create a list in memory that contains them all:\n\
338\n\
339 k = db.firstkey()\n\
340 while k != None:\n\
341 print k\n\
342 k = db.nextkey(k)";
343
Roger E. Masseb15bef81996-12-17 19:55:33 +0000344static PyObject *
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000345dbm_nextkey(dp, args)
346 register dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000347PyObject *args;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000348{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000349 register PyObject *v;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000350 datum key, nextkey;
351
Roger E. Masseb15bef81996-12-17 19:55:33 +0000352 if (!PyArg_Parse(args, "s#", &key.dptr, &key.dsize))
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000353 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000354 check_dbmobject_open(dp);
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000355 nextkey = gdbm_nextkey(dp->di_dbm, key);
356 if (nextkey.dptr) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000357 v = PyString_FromStringAndSize(nextkey.dptr, nextkey.dsize);
358 free(nextkey.dptr);
359 return v;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000360 } else {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000361 Py_INCREF(Py_None);
362 return Py_None;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000363 }
364}
365
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000366static char dbm_reorganize__doc__[] = "\
367reorganize() -> None\n\
368If you have carried out a lot of deletions and would like to shrink\n\
369the space used by the GDBM file, this routine will reorganize the\n\
370database. GDBM will not shorten the length of a database file except\n\
371by using this reorganization; otherwise, deleted file space will be\n\
372kept and reused as new (key,value) pairs are added.";
373
Roger E. Masseb15bef81996-12-17 19:55:33 +0000374static PyObject *
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000375dbm_reorganize(dp, args)
376 register dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000377PyObject *args;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000378{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000379 if (!PyArg_NoArgs(args))
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000380 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000381 check_dbmobject_open(dp);
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000382 errno = 0;
383 if (gdbm_reorganize(dp->di_dbm) < 0) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000384 if (errno != 0)
385 PyErr_SetFromErrno(DbmError);
386 else
387 PyErr_SetString(DbmError,
388 (char *) gdbm_strerror(gdbm_errno));
389 return NULL;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000390 }
Roger E. Masseb15bef81996-12-17 19:55:33 +0000391 Py_INCREF(Py_None);
392 return Py_None;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000393}
394
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000395static char dbm_sync__doc__[] = "\
396sync() -> None\n\
397When the database has been opened in fast mode, this method forces\n\
398any unwritten data to be written to the disk.";
399
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000400static PyObject *
401dbm_sync(dp, args)
402 register dbmobject *dp;
403 PyObject *args;
404{
405 if (!PyArg_NoArgs(args))
406 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000407 check_dbmobject_open(dp);
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000408 gdbm_sync(dp->di_dbm);
409 Py_INCREF(Py_None);
410 return Py_None;
411}
412
Roger E. Masseb15bef81996-12-17 19:55:33 +0000413static PyMethodDef dbm_methods[] = {
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000414 {"close", (PyCFunction)dbm_close, 0, dbm_close__doc__},
415 {"keys", (PyCFunction)dbm_keys, 0, dbm_keys__doc__},
416 {"has_key", (PyCFunction)dbm_has_key, 0, dbm_has_key__doc__},
417 {"firstkey", (PyCFunction)dbm_firstkey, 0, dbm_firstkey__doc__},
418 {"nextkey", (PyCFunction)dbm_nextkey, 0, dbm_nextkey__doc__},
419 {"reorganize", (PyCFunction)dbm_reorganize, 0, dbm_reorganize__doc__},
420 {"sync", (PyCFunction)dbm_sync, 0, dbm_sync__doc__},
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000421 {NULL, NULL} /* sentinel */
422};
423
Roger E. Masseb15bef81996-12-17 19:55:33 +0000424static PyObject *
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000425dbm_getattr(dp, name)
426 dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000427char *name;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000428{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000429 return Py_FindMethod(dbm_methods, (PyObject *)dp, name);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000430}
431
Roger E. Masseb15bef81996-12-17 19:55:33 +0000432static PyTypeObject Dbmtype = {
Guido van Rossumb6e2a991998-10-03 05:13:27 +0000433 PyObject_HEAD_INIT(0)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000434 0,
Guido van Rossum807b7be1995-07-07 22:37:11 +0000435 "gdbm",
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000436 sizeof(dbmobject),
437 0,
Roger E. Masseb15bef81996-12-17 19:55:33 +0000438 (destructor)dbm_dealloc, /*tp_dealloc*/
439 0, /*tp_print*/
440 (getattrfunc)dbm_getattr, /*tp_getattr*/
441 0, /*tp_setattr*/
442 0, /*tp_compare*/
443 0, /*tp_repr*/
444 0, /*tp_as_number*/
445 0, /*tp_as_sequence*/
446 &dbm_as_mapping, /*tp_as_mapping*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000447 0, /*tp_hash*/
448 0, /*tp_call*/
449 0, /*tp_str*/
450 0, /*tp_getattro*/
451 0, /*tp_setattro*/
452 0, /*tp_as_buffer*/
453 0, /*tp_xxx4*/
454 gdbm_object__doc__, /*tp_doc*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000455};
456
457/* ----------------------------------------------------------------- */
458
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000459static char dbmopen__doc__[] = "\
460open(filename, [flag, [mode]]) -> dbm_object\n\
461Open a dbm database and return a dbm object. The filename argument is\n\
462the name of the database file.\n\
463\n\
464The optional flag argument can be 'r' (to open an existing database\n\
465for reading only -- default), 'w' (to open an existing database for\n\
466reading and writing), 'c' (which creates the database if it doesn't\n\
467exist), or 'n' (which always creates a new empty database).\n\
468\n\
469Appending f to the flag opens the database in fast mode; altered\n\
470data will not automatically be written to the disk after every\n\
471change. This results in faster writes to the database, but may\n\
472result in an inconsistent database if the program crashes while the\n\
473database is still open. Use the sync() method to force any\n\
474unwritten data to be written to the disk.\n\
475\n\
476The optional mode argument is the Unix mode of the file, used only\n\
477when the database has to be created. It defaults to octal 0666. ";
478
Roger E. Masseb15bef81996-12-17 19:55:33 +0000479static PyObject *
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000480dbmopen(self, args)
Roger E. Masseb15bef81996-12-17 19:55:33 +0000481 PyObject *self;
482PyObject *args;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000483{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000484 char *name;
485 char *flags = "r ";
486 int iflags;
487 int mode = 0666;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000488
Roger E. Masseb15bef81996-12-17 19:55:33 +0000489 if ( !PyArg_ParseTuple(args, "s|si", &name, &flags, &mode) )
490 return NULL;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000491 switch (flags[0]) {
492 case 'r':
Roger E. Masseb15bef81996-12-17 19:55:33 +0000493 iflags = GDBM_READER;
494 break;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000495 case 'w':
Roger E. Masseb15bef81996-12-17 19:55:33 +0000496 iflags = GDBM_WRITER;
497 break;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000498 case 'c':
Roger E. Masseb15bef81996-12-17 19:55:33 +0000499 iflags = GDBM_WRCREAT;
500 break;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000501 case 'n':
Roger E. Masseb15bef81996-12-17 19:55:33 +0000502 iflags = GDBM_NEWDB;
503 break;
504 default:
505 PyErr_SetString(DbmError,
506 "Flags should be one of 'r', 'w', 'c' or 'n'");
507 return NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000508 }
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000509 if (flags[1] == 'f')
Roger E. Masseb15bef81996-12-17 19:55:33 +0000510 iflags |= GDBM_FAST;
511 return newdbmobject(name, iflags, mode);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000512}
513
Roger E. Masseb15bef81996-12-17 19:55:33 +0000514static PyMethodDef dbmmodule_methods[] = {
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000515 { "open", (PyCFunction)dbmopen, 1, dbmopen__doc__},
Roger E. Masseb15bef81996-12-17 19:55:33 +0000516 { 0, 0 },
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000517};
518
519void
520initgdbm() {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000521 PyObject *m, *d;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000522
Guido van Rossumb6e2a991998-10-03 05:13:27 +0000523 Dbmtype.ob_type = &PyType_Type;
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000524 m = Py_InitModule4("gdbm", dbmmodule_methods,
525 gdbmmodule__doc__, (PyObject *)NULL,
526 PYTHON_API_VERSION);
Roger E. Masseb15bef81996-12-17 19:55:33 +0000527 d = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +0000528 DbmError = PyErr_NewException("gdbm.error", NULL, NULL);
529 if (DbmError != NULL)
530 PyDict_SetItemString(d, "error", DbmError);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000531}