blob: 00b8c6335ba9aebe745da23b89cd568479ae6a87 [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 Rossumfd71b9e2000-06-30 23:50:40 +00007Copyright (c) 2000, BeOpen.com.
8Copyright (c) 1995-2000, Corporation for National Research Initiatives.
9Copyright (c) 1990-1995, Stichting Mathematisch Centrum.
10All rights reserved.
Guido van Rossum4b4c6641994-08-08 08:06:37 +000011
Guido van Rossumfd71b9e2000-06-30 23:50:40 +000012See the file "Misc/COPYRIGHT" for information on usage and
13redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
Guido van Rossum4b4c6641994-08-08 08:06:37 +000014
15******************************************************************/
16
17/* DBM module using dictionary interface */
Guido van Rossumbfc49e81998-03-03 22:02:24 +000018/* Author: Anthony Baxter, after dbmmodule.c */
19/* Doc strings: Mitch Chapman */
Guido van Rossum4b4c6641994-08-08 08:06:37 +000020
21
Roger E. Masseb15bef81996-12-17 19:55:33 +000022#include "Python.h"
Guido van Rossum4b4c6641994-08-08 08:06:37 +000023
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <fcntl.h>
27#include "gdbm.h"
28
Guido van Rossumb6e2a991998-10-03 05:13:27 +000029#ifdef WIN32
30#include "gdbmerrno.h"
31extern const char * gdbm_strerror(gdbm_error);
32#endif
33
Guido van Rossumbfc49e81998-03-03 22:02:24 +000034static char gdbmmodule__doc__[] = "\
35This module provides an interface to the GNU DBM (GDBM) library.\n\
36\n\
37This module is quite similar to the dbm module, but uses GDBM instead to\n\
38provide some additional functionality. Please note that the file formats\n\
39created by GDBM and dbm are incompatible. \n\
40\n\
41GDBM objects behave like mappings (dictionaries), except that keys and\n\
42values are always strings. Printing a GDBM object doesn't print the\n\
43keys and values, and the items() and values() methods are not\n\
44supported.";
45
Guido van Rossum4b4c6641994-08-08 08:06:37 +000046typedef struct {
Roger E. Masseb15bef81996-12-17 19:55:33 +000047 PyObject_HEAD
Guido van Rossum4b4c6641994-08-08 08:06:37 +000048 int di_size; /* -1 means recompute */
49 GDBM_FILE di_dbm;
50} dbmobject;
51
Roger E. Masseb15bef81996-12-17 19:55:33 +000052staticforward PyTypeObject Dbmtype;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000053
54#define is_dbmobject(v) ((v)->ob_type == &Dbmtype)
Guido van Rossum77eecfa1997-07-17 22:56:01 +000055#define check_dbmobject_open(v) if ((v)->di_dbm == NULL) \
56 { PyErr_SetString(DbmError, "GDBM object has already been closed"); \
57 return NULL; }
58
59
Guido van Rossum4b4c6641994-08-08 08:06:37 +000060
Roger E. Masseb15bef81996-12-17 19:55:33 +000061static PyObject *DbmError;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000062
Guido van Rossumbfc49e81998-03-03 22:02:24 +000063static char gdbm_object__doc__[] = "\
64This object represents a GDBM database.\n\
65GDBM objects behave like mappings (dictionaries), except that keys and\n\
66values are always strings. Printing a GDBM object doesn't print the\n\
67keys and values, and the items() and values() methods are not\n\
68supported.\n\
69\n\
70GDBM objects also support additional operations such as firstkey,\n\
71nextkey, reorganize, and sync.";
72
Roger E. Masseb15bef81996-12-17 19:55:33 +000073static PyObject *
Guido van Rossum4b4c6641994-08-08 08:06:37 +000074newdbmobject(file, flags, mode)
Roger E. Masseb15bef81996-12-17 19:55:33 +000075 char *file;
76int flags;
77int mode;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000078{
79 dbmobject *dp;
80
Guido van Rossumb18618d2000-05-03 23:44:39 +000081 dp = PyObject_New(dbmobject, &Dbmtype);
Guido van Rossum4b4c6641994-08-08 08:06:37 +000082 if (dp == NULL)
83 return NULL;
84 dp->di_size = -1;
Guido van Rossumb045afc1995-03-14 15:04:40 +000085 errno = 0;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000086 if ( (dp->di_dbm = gdbm_open(file, 0, flags, mode, NULL)) == 0 ) {
Roger E. Masseb15bef81996-12-17 19:55:33 +000087 if (errno != 0)
88 PyErr_SetFromErrno(DbmError);
89 else
Guido van Rossum573788e1998-10-03 05:15:07 +000090 PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
Roger E. Masseb15bef81996-12-17 19:55:33 +000091 Py_DECREF(dp);
92 return NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000093 }
Roger E. Masseb15bef81996-12-17 19:55:33 +000094 return (PyObject *)dp;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000095}
96
97/* Methods */
98
99static void
100dbm_dealloc(dp)
101 register dbmobject *dp;
102{
103 if ( dp->di_dbm )
Roger E. Masseb15bef81996-12-17 19:55:33 +0000104 gdbm_close(dp->di_dbm);
Guido van Rossumb18618d2000-05-03 23:44:39 +0000105 PyObject_Del(dp);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000106}
107
108static int
109dbm_length(dp)
110 dbmobject *dp;
111{
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000112 if (dp->di_dbm == NULL) {
113 PyErr_SetString(DbmError, "GDBM object has already been closed");
114 return -1;
115 }
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000116 if ( dp->di_size < 0 ) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000117 datum key,okey;
118 int size;
119 okey.dsize=0;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000120
Roger E. Masseb15bef81996-12-17 19:55:33 +0000121 size = 0;
122 for ( key=gdbm_firstkey(dp->di_dbm); key.dptr;
123 key = gdbm_nextkey(dp->di_dbm,okey)) {
124 size++;
125 if(okey.dsize) free(okey.dptr);
126 okey=key;
127 }
128 dp->di_size = size;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000129 }
130 return dp->di_size;
131}
132
Roger E. Masseb15bef81996-12-17 19:55:33 +0000133static PyObject *
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000134dbm_subscript(dp, key)
135 dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000136register PyObject *key;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000137{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000138 PyObject *v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000139 datum drec, krec;
140
Roger E. Masseb15bef81996-12-17 19:55:33 +0000141 if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize) )
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000142 return NULL;
Fred Drakeda8d2162000-02-07 17:19:41 +0000143
144 if (dp->di_dbm == NULL) {
145 PyErr_SetString(DbmError,
146 "GDBM object has already been closed");
147 return NULL;
148 }
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000149 drec = gdbm_fetch(dp->di_dbm, krec);
150 if ( drec.dptr == 0 ) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000151 PyErr_SetString(PyExc_KeyError,
152 PyString_AS_STRING((PyStringObject *)key));
153 return NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000154 }
Roger E. Masseb15bef81996-12-17 19:55:33 +0000155 v = PyString_FromStringAndSize(drec.dptr, drec.dsize);
Guido van Rossumb045afc1995-03-14 15:04:40 +0000156 free(drec.dptr);
157 return v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000158}
159
160static int
161dbm_ass_sub(dp, v, w)
162 dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000163PyObject *v, *w;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000164{
165 datum krec, drec;
166
Roger E. Masseb15bef81996-12-17 19:55:33 +0000167 if ( !PyArg_Parse(v, "s#", &krec.dptr, &krec.dsize) ) {
168 PyErr_SetString(PyExc_TypeError,
169 "gdbm mappings have string indices only");
170 return -1;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000171 }
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000172 if (dp->di_dbm == NULL) {
Fred Drakeda8d2162000-02-07 17:19:41 +0000173 PyErr_SetString(DbmError,
174 "GDBM object has already been closed");
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000175 return -1;
176 }
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000177 dp->di_size = -1;
178 if (w == NULL) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000179 if ( gdbm_delete(dp->di_dbm, krec) < 0 ) {
180 PyErr_SetString(PyExc_KeyError,
181 PyString_AS_STRING((PyStringObject *)v));
182 return -1;
183 }
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000184 } else {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000185 if ( !PyArg_Parse(w, "s#", &drec.dptr, &drec.dsize) ) {
186 PyErr_SetString(PyExc_TypeError,
187 "gdbm mappings have string elements only");
188 return -1;
189 }
190 errno = 0;
191 if ( gdbm_store(dp->di_dbm, krec, drec, GDBM_REPLACE) < 0 ) {
192 if (errno != 0)
193 PyErr_SetFromErrno(DbmError);
194 else
195 PyErr_SetString(DbmError,
Guido van Rossum573788e1998-10-03 05:15:07 +0000196 gdbm_strerror(gdbm_errno));
Roger E. Masseb15bef81996-12-17 19:55:33 +0000197 return -1;
198 }
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000199 }
200 return 0;
201}
202
Roger E. Masseb15bef81996-12-17 19:55:33 +0000203static PyMappingMethods dbm_as_mapping = {
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000204 (inquiry)dbm_length, /*mp_length*/
205 (binaryfunc)dbm_subscript, /*mp_subscript*/
206 (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
207};
208
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000209static char dbm_close__doc__[] = "\
210close() -> None\n\
Guido van Rossumcef113c1998-04-13 18:11:55 +0000211Closes the database.";
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000212
Roger E. Masseb15bef81996-12-17 19:55:33 +0000213static PyObject *
Guido van Rossum807b7be1995-07-07 22:37:11 +0000214dbm_close(dp, args)
215 register dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000216PyObject *args;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000217{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000218 if ( !PyArg_NoArgs(args) )
Guido van Rossum807b7be1995-07-07 22:37:11 +0000219 return NULL;
220 if ( dp->di_dbm )
221 gdbm_close(dp->di_dbm);
222 dp->di_dbm = NULL;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000223 Py_INCREF(Py_None);
224 return Py_None;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000225}
226
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000227static char dbm_keys__doc__[] = "\
228keys() -> list_of_keys\n\
229Get a list of all keys in the database.";
230
Roger E. Masseb15bef81996-12-17 19:55:33 +0000231static PyObject *
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000232dbm_keys(dp, args)
233 register dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000234PyObject *args;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000235{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000236 register PyObject *v, *item;
Guido van Rossum3be71401996-07-21 02:32:44 +0000237 datum key, nextkey;
Guido van Rossum66017aa1995-08-28 02:58:00 +0000238 int err;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000239
240 if (dp == NULL || !is_dbmobject(dp)) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000241 PyErr_BadInternalCall();
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000242 return NULL;
243 }
Guido van Rossum3be71401996-07-21 02:32:44 +0000244
Roger E. Masseb15bef81996-12-17 19:55:33 +0000245 if (!PyArg_NoArgs(args))
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000246 return NULL;
Guido van Rossum3be71401996-07-21 02:32:44 +0000247
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000248 check_dbmobject_open(dp);
249
Roger E. Masseb15bef81996-12-17 19:55:33 +0000250 v = PyList_New(0);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000251 if (v == NULL)
252 return NULL;
Guido van Rossum3be71401996-07-21 02:32:44 +0000253
254 key = gdbm_firstkey(dp->di_dbm);
255 while (key.dptr) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000256 item = PyString_FromStringAndSize(key.dptr, key.dsize);
257 if (item == NULL) {
258 free(key.dptr);
259 Py_DECREF(v);
260 return NULL;
261 }
262 err = PyList_Append(v, item);
263 Py_DECREF(item);
264 if (err != 0) {
265 free(key.dptr);
266 Py_DECREF(v);
267 return NULL;
268 }
269 nextkey = gdbm_nextkey(dp->di_dbm, key);
Guido van Rossum3be71401996-07-21 02:32:44 +0000270 free(key.dptr);
Roger E. Masseb15bef81996-12-17 19:55:33 +0000271 key = nextkey;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000272 }
Guido van Rossum3be71401996-07-21 02:32:44 +0000273
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000274 return v;
275}
276
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000277static char dbm_has_key__doc__[] = "\
278has_key(key) -> boolean\n\
279Find out whether or not the database contains a given key.";
280
Roger E. Masseb15bef81996-12-17 19:55:33 +0000281static PyObject *
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000282dbm_has_key(dp, args)
283 register dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000284PyObject *args;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000285{
Guido van Rossumb045afc1995-03-14 15:04:40 +0000286 datum key;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000287
Roger E. Masseb15bef81996-12-17 19:55:33 +0000288 if (!PyArg_Parse(args, "s#", &key.dptr, &key.dsize))
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000289 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000290 check_dbmobject_open(dp);
Roger E. Masseb15bef81996-12-17 19:55:33 +0000291 return PyInt_FromLong((long) gdbm_exists(dp->di_dbm, key));
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000292}
293
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000294static char dbm_firstkey__doc__[] = "\
295firstkey() -> key\n\
296It's possible to loop over every key in the database using this method\n\
297and the nextkey() method. The traversal is ordered by GDBM's internal\n\
298hash values, and won't be sorted by the key values. This method\n\
299returns the starting key.";
300
Roger E. Masseb15bef81996-12-17 19:55:33 +0000301static PyObject *
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000302dbm_firstkey(dp, args)
303 register dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000304PyObject *args;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000305{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000306 register PyObject *v;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000307 datum key;
308
Roger E. Masseb15bef81996-12-17 19:55:33 +0000309 if (!PyArg_NoArgs(args))
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000310 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000311 check_dbmobject_open(dp);
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000312 key = gdbm_firstkey(dp->di_dbm);
313 if (key.dptr) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000314 v = PyString_FromStringAndSize(key.dptr, key.dsize);
315 free(key.dptr);
316 return v;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000317 } else {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000318 Py_INCREF(Py_None);
319 return Py_None;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000320 }
321}
322
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000323static char dbm_nextkey__doc__[] = "\
324nextkey(key) -> next_key\n\
325Returns the key that follows key in the traversal.\n\
326The following code prints every key in the database db, without having\n\
327to create a list in memory that contains them all:\n\
328\n\
329 k = db.firstkey()\n\
330 while k != None:\n\
331 print k\n\
332 k = db.nextkey(k)";
333
Roger E. Masseb15bef81996-12-17 19:55:33 +0000334static PyObject *
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000335dbm_nextkey(dp, args)
336 register dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000337PyObject *args;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000338{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000339 register PyObject *v;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000340 datum key, nextkey;
341
Roger E. Masseb15bef81996-12-17 19:55:33 +0000342 if (!PyArg_Parse(args, "s#", &key.dptr, &key.dsize))
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000343 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000344 check_dbmobject_open(dp);
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000345 nextkey = gdbm_nextkey(dp->di_dbm, key);
346 if (nextkey.dptr) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000347 v = PyString_FromStringAndSize(nextkey.dptr, nextkey.dsize);
348 free(nextkey.dptr);
349 return v;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000350 } else {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000351 Py_INCREF(Py_None);
352 return Py_None;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000353 }
354}
355
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000356static char dbm_reorganize__doc__[] = "\
357reorganize() -> None\n\
358If you have carried out a lot of deletions and would like to shrink\n\
359the space used by the GDBM file, this routine will reorganize the\n\
360database. GDBM will not shorten the length of a database file except\n\
361by using this reorganization; otherwise, deleted file space will be\n\
362kept and reused as new (key,value) pairs are added.";
363
Roger E. Masseb15bef81996-12-17 19:55:33 +0000364static PyObject *
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000365dbm_reorganize(dp, args)
366 register dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000367PyObject *args;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000368{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000369 if (!PyArg_NoArgs(args))
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000370 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000371 check_dbmobject_open(dp);
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000372 errno = 0;
373 if (gdbm_reorganize(dp->di_dbm) < 0) {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000374 if (errno != 0)
375 PyErr_SetFromErrno(DbmError);
376 else
Guido van Rossum573788e1998-10-03 05:15:07 +0000377 PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
Roger E. Masseb15bef81996-12-17 19:55:33 +0000378 return NULL;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000379 }
Roger E. Masseb15bef81996-12-17 19:55:33 +0000380 Py_INCREF(Py_None);
381 return Py_None;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000382}
383
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000384static char dbm_sync__doc__[] = "\
385sync() -> None\n\
386When the database has been opened in fast mode, this method forces\n\
387any unwritten data to be written to the disk.";
388
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000389static PyObject *
390dbm_sync(dp, args)
391 register dbmobject *dp;
392 PyObject *args;
393{
394 if (!PyArg_NoArgs(args))
395 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000396 check_dbmobject_open(dp);
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000397 gdbm_sync(dp->di_dbm);
398 Py_INCREF(Py_None);
399 return Py_None;
400}
401
Roger E. Masseb15bef81996-12-17 19:55:33 +0000402static PyMethodDef dbm_methods[] = {
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000403 {"close", (PyCFunction)dbm_close, 0, dbm_close__doc__},
404 {"keys", (PyCFunction)dbm_keys, 0, dbm_keys__doc__},
405 {"has_key", (PyCFunction)dbm_has_key, 0, dbm_has_key__doc__},
406 {"firstkey", (PyCFunction)dbm_firstkey, 0, dbm_firstkey__doc__},
407 {"nextkey", (PyCFunction)dbm_nextkey, 0, dbm_nextkey__doc__},
408 {"reorganize", (PyCFunction)dbm_reorganize, 0, dbm_reorganize__doc__},
409 {"sync", (PyCFunction)dbm_sync, 0, dbm_sync__doc__},
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000410 {NULL, NULL} /* sentinel */
411};
412
Roger E. Masseb15bef81996-12-17 19:55:33 +0000413static PyObject *
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000414dbm_getattr(dp, name)
415 dbmobject *dp;
Roger E. Masseb15bef81996-12-17 19:55:33 +0000416char *name;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000417{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000418 return Py_FindMethod(dbm_methods, (PyObject *)dp, name);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000419}
420
Roger E. Masseb15bef81996-12-17 19:55:33 +0000421static PyTypeObject Dbmtype = {
Guido van Rossumb6e2a991998-10-03 05:13:27 +0000422 PyObject_HEAD_INIT(0)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000423 0,
Guido van Rossum807b7be1995-07-07 22:37:11 +0000424 "gdbm",
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000425 sizeof(dbmobject),
426 0,
Roger E. Masseb15bef81996-12-17 19:55:33 +0000427 (destructor)dbm_dealloc, /*tp_dealloc*/
428 0, /*tp_print*/
429 (getattrfunc)dbm_getattr, /*tp_getattr*/
430 0, /*tp_setattr*/
431 0, /*tp_compare*/
432 0, /*tp_repr*/
433 0, /*tp_as_number*/
434 0, /*tp_as_sequence*/
435 &dbm_as_mapping, /*tp_as_mapping*/
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000436 0, /*tp_hash*/
437 0, /*tp_call*/
438 0, /*tp_str*/
439 0, /*tp_getattro*/
440 0, /*tp_setattro*/
441 0, /*tp_as_buffer*/
442 0, /*tp_xxx4*/
443 gdbm_object__doc__, /*tp_doc*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000444};
445
446/* ----------------------------------------------------------------- */
447
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000448static char dbmopen__doc__[] = "\
449open(filename, [flag, [mode]]) -> dbm_object\n\
450Open a dbm database and return a dbm object. The filename argument is\n\
451the name of the database file.\n\
452\n\
453The optional flag argument can be 'r' (to open an existing database\n\
454for reading only -- default), 'w' (to open an existing database for\n\
455reading and writing), 'c' (which creates the database if it doesn't\n\
456exist), or 'n' (which always creates a new empty database).\n\
457\n\
458Appending f to the flag opens the database in fast mode; altered\n\
459data will not automatically be written to the disk after every\n\
460change. This results in faster writes to the database, but may\n\
461result in an inconsistent database if the program crashes while the\n\
462database is still open. Use the sync() method to force any\n\
463unwritten data to be written to the disk.\n\
464\n\
465The optional mode argument is the Unix mode of the file, used only\n\
466when the database has to be created. It defaults to octal 0666. ";
467
Roger E. Masseb15bef81996-12-17 19:55:33 +0000468static PyObject *
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000469dbmopen(self, args)
Roger E. Masseb15bef81996-12-17 19:55:33 +0000470 PyObject *self;
471PyObject *args;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000472{
Roger E. Masseb15bef81996-12-17 19:55:33 +0000473 char *name;
474 char *flags = "r ";
475 int iflags;
476 int mode = 0666;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000477
Guido van Rossum43713e52000-02-29 13:59:29 +0000478 if ( !PyArg_ParseTuple(args, "s|si:open", &name, &flags, &mode) )
Roger E. Masseb15bef81996-12-17 19:55:33 +0000479 return NULL;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000480 switch (flags[0]) {
481 case 'r':
Roger E. Masseb15bef81996-12-17 19:55:33 +0000482 iflags = GDBM_READER;
483 break;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000484 case 'w':
Roger E. Masseb15bef81996-12-17 19:55:33 +0000485 iflags = GDBM_WRITER;
486 break;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000487 case 'c':
Roger E. Masseb15bef81996-12-17 19:55:33 +0000488 iflags = GDBM_WRCREAT;
489 break;
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000490 case 'n':
Roger E. Masseb15bef81996-12-17 19:55:33 +0000491 iflags = GDBM_NEWDB;
492 break;
493 default:
494 PyErr_SetString(DbmError,
495 "Flags should be one of 'r', 'w', 'c' or 'n'");
496 return NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000497 }
Guido van Rossume36e1fe1996-01-26 21:08:01 +0000498 if (flags[1] == 'f')
Roger E. Masseb15bef81996-12-17 19:55:33 +0000499 iflags |= GDBM_FAST;
500 return newdbmobject(name, iflags, mode);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000501}
502
Roger E. Masseb15bef81996-12-17 19:55:33 +0000503static PyMethodDef dbmmodule_methods[] = {
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000504 { "open", (PyCFunction)dbmopen, 1, dbmopen__doc__},
Roger E. Masseb15bef81996-12-17 19:55:33 +0000505 { 0, 0 },
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000506};
507
Guido van Rossum3886bb61998-12-04 18:50:17 +0000508DL_EXPORT(void)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000509initgdbm() {
Roger E. Masseb15bef81996-12-17 19:55:33 +0000510 PyObject *m, *d;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000511
Guido van Rossumb6e2a991998-10-03 05:13:27 +0000512 Dbmtype.ob_type = &PyType_Type;
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000513 m = Py_InitModule4("gdbm", dbmmodule_methods,
514 gdbmmodule__doc__, (PyObject *)NULL,
515 PYTHON_API_VERSION);
Roger E. Masseb15bef81996-12-17 19:55:33 +0000516 d = PyModule_GetDict(m);
Guido van Rossum0cb96de1997-10-01 04:29:29 +0000517 DbmError = PyErr_NewException("gdbm.error", NULL, NULL);
518 if (DbmError != NULL)
519 PyDict_SetItemString(d, "error", DbmError);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000520}