blob: 474561b235f28f805ae2bc1655fda85ec8dc9ccf [file] [log] [blame]
Guido van Rossum4b4c6641994-08-08 08:06:37 +00001
2/* DBM module using dictionary interface */
Guido van Rossumbfc49e81998-03-03 22:02:24 +00003/* Author: Anthony Baxter, after dbmmodule.c */
4/* Doc strings: Mitch Chapman */
Guido van Rossum4b4c6641994-08-08 08:06:37 +00005
6
Roger E. Masseb15bef81996-12-17 19:55:33 +00007#include "Python.h"
Guido van Rossum4b4c6641994-08-08 08:06:37 +00008
9#include <sys/types.h>
10#include <sys/stat.h>
11#include <fcntl.h>
12#include "gdbm.h"
13
Tim Peters5687ffe2001-02-28 16:44:18 +000014#if defined(WIN32) && !defined(__CYGWIN__)
Guido van Rossumb6e2a991998-10-03 05:13:27 +000015#include "gdbmerrno.h"
16extern const char * gdbm_strerror(gdbm_error);
17#endif
18
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000019PyDoc_STRVAR(gdbmmodule__doc__,
20"This module provides an interface to the GNU DBM (GDBM) library.\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +000021\n\
22This module is quite similar to the dbm module, but uses GDBM instead to\n\
23provide some additional functionality. Please note that the file formats\n\
24created by GDBM and dbm are incompatible. \n\
25\n\
26GDBM objects behave like mappings (dictionaries), except that keys and\n\
27values are always strings. Printing a GDBM object doesn't print the\n\
28keys and values, and the items() and values() methods are not\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000029supported.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +000030
Guido van Rossum4b4c6641994-08-08 08:06:37 +000031typedef struct {
Fred Drakee3a41c62000-07-08 05:00:07 +000032 PyObject_HEAD
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000033 int di_size; /* -1 means recompute */
Fred Drakee3a41c62000-07-08 05:00:07 +000034 GDBM_FILE di_dbm;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000035} dbmobject;
36
Jeremy Hylton938ace62002-07-17 16:30:39 +000037static PyTypeObject Dbmtype;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000038
Christian Heimes90aa7642007-12-19 02:45:37 +000039#define is_dbmobject(v) (Py_TYPE(v) == &Dbmtype)
Guido van Rossum77eecfa1997-07-17 22:56:01 +000040#define check_dbmobject_open(v) if ((v)->di_dbm == NULL) \
Fred Drakee3a41c62000-07-08 05:00:07 +000041 { PyErr_SetString(DbmError, "GDBM object has already been closed"); \
42 return NULL; }
Guido van Rossum77eecfa1997-07-17 22:56:01 +000043
44
Guido van Rossum4b4c6641994-08-08 08:06:37 +000045
Roger E. Masseb15bef81996-12-17 19:55:33 +000046static PyObject *DbmError;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000047
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000048PyDoc_STRVAR(gdbm_object__doc__,
49"This object represents a GDBM database.\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +000050GDBM objects behave like mappings (dictionaries), except that keys and\n\
51values are always strings. Printing a GDBM object doesn't print the\n\
52keys and values, and the items() and values() methods are not\n\
53supported.\n\
54\n\
55GDBM objects also support additional operations such as firstkey,\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000056nextkey, reorganize, and sync.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +000057
Roger E. Masseb15bef81996-12-17 19:55:33 +000058static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +000059newdbmobject(char *file, int flags, int mode)
Guido van Rossum4b4c6641994-08-08 08:06:37 +000060{
Fred Drakee3a41c62000-07-08 05:00:07 +000061 dbmobject *dp;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000062
Fred Drakee3a41c62000-07-08 05:00:07 +000063 dp = PyObject_New(dbmobject, &Dbmtype);
64 if (dp == NULL)
65 return NULL;
66 dp->di_size = -1;
67 errno = 0;
68 if ((dp->di_dbm = gdbm_open(file, 0, flags, mode, NULL)) == 0) {
69 if (errno != 0)
70 PyErr_SetFromErrno(DbmError);
71 else
72 PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
73 Py_DECREF(dp);
74 return NULL;
75 }
76 return (PyObject *)dp;
Guido van Rossum4b4c6641994-08-08 08:06:37 +000077}
78
79/* Methods */
80
81static void
Fred Drakee3a41c62000-07-08 05:00:07 +000082dbm_dealloc(register dbmobject *dp)
Guido van Rossum4b4c6641994-08-08 08:06:37 +000083{
Fred Drakee3a41c62000-07-08 05:00:07 +000084 if (dp->di_dbm)
85 gdbm_close(dp->di_dbm);
86 PyObject_Del(dp);
Guido van Rossum4b4c6641994-08-08 08:06:37 +000087}
88
Martin v. Löwis18e16552006-02-15 17:27:45 +000089static Py_ssize_t
Fred Drakee3a41c62000-07-08 05:00:07 +000090dbm_length(dbmobject *dp)
Guido van Rossum4b4c6641994-08-08 08:06:37 +000091{
Fred Drakee3a41c62000-07-08 05:00:07 +000092 if (dp->di_dbm == NULL) {
Guido van Rossum6252e102007-05-23 20:51:02 +000093 PyErr_SetString(DbmError, "GDBM object has already been closed");
94 return -1;
Fred Drakee3a41c62000-07-08 05:00:07 +000095 }
96 if (dp->di_size < 0) {
97 datum key,okey;
98 int size;
99 okey.dsize=0;
Thomas Woutersa5fa2a82006-03-01 22:54:36 +0000100 okey.dptr=NULL;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000101
Fred Drakee3a41c62000-07-08 05:00:07 +0000102 size = 0;
103 for (key=gdbm_firstkey(dp->di_dbm); key.dptr;
104 key = gdbm_nextkey(dp->di_dbm,okey)) {
105 size++;
106 if(okey.dsize) free(okey.dptr);
107 okey=key;
108 }
109 dp->di_size = size;
110 }
111 return dp->di_size;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000112}
113
Roger E. Masseb15bef81996-12-17 19:55:33 +0000114static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000115dbm_subscript(dbmobject *dp, register PyObject *key)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000116{
Fred Drakee3a41c62000-07-08 05:00:07 +0000117 PyObject *v;
118 datum drec, krec;
Fred Drakeda8d2162000-02-07 17:19:41 +0000119
Fred Drakee3a41c62000-07-08 05:00:07 +0000120 if (!PyArg_Parse(key, "s#", &krec.dptr, &krec.dsize) )
121 return NULL;
122
123 if (dp->di_dbm == NULL) {
124 PyErr_SetString(DbmError,
125 "GDBM object has already been closed");
126 return NULL;
127 }
128 drec = gdbm_fetch(dp->di_dbm, krec);
129 if (drec.dptr == 0) {
Guido van Rossum6252e102007-05-23 20:51:02 +0000130 PyErr_SetObject(PyExc_KeyError, key);
Fred Drakee3a41c62000-07-08 05:00:07 +0000131 return NULL;
132 }
Christian Heimes72b710a2008-05-26 13:28:38 +0000133 v = PyBytes_FromStringAndSize(drec.dptr, drec.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000134 free(drec.dptr);
135 return v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000136}
137
Georg Brandld9e833c2010-12-04 09:14:36 +0000138PyDoc_STRVAR(dbm_get__doc__,
139"get(key[, default]) -> value\n\
140Get the value for key, or default if not present; if not given,\n\
141default is None.");
142
143static PyObject *
144dbm_get(dbmobject *dp, PyObject *args)
145{
146 PyObject *v, *res;
147 PyObject *def = Py_None;
148
149 if (!PyArg_UnpackTuple(args, "get", 1, 2, &v, &def))
150 return NULL;
151 res = dbm_subscript(dp, v);
152 if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) {
153 PyErr_Clear();
154 Py_INCREF(def);
155 return def;
156 }
157 return res;
158}
159
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000160static int
Fred Drakee3a41c62000-07-08 05:00:07 +0000161dbm_ass_sub(dbmobject *dp, PyObject *v, PyObject *w)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000162{
Fred Drakee3a41c62000-07-08 05:00:07 +0000163 datum krec, drec;
164
165 if (!PyArg_Parse(v, "s#", &krec.dptr, &krec.dsize) ) {
166 PyErr_SetString(PyExc_TypeError,
Brett Cannon7317c1e2008-11-25 19:19:17 +0000167 "gdbm mappings have bytes or string indices only");
Fred Drakee3a41c62000-07-08 05:00:07 +0000168 return -1;
169 }
170 if (dp->di_dbm == NULL) {
171 PyErr_SetString(DbmError,
Guido van Rossum6252e102007-05-23 20:51:02 +0000172 "GDBM object has already been closed");
173 return -1;
Fred Drakee3a41c62000-07-08 05:00:07 +0000174 }
175 dp->di_size = -1;
176 if (w == NULL) {
177 if (gdbm_delete(dp->di_dbm, krec) < 0) {
Guido van Rossum6252e102007-05-23 20:51:02 +0000178 PyErr_SetObject(PyExc_KeyError, v);
Fred Drakee3a41c62000-07-08 05:00:07 +0000179 return -1;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000180 }
Fred Drakee3a41c62000-07-08 05:00:07 +0000181 }
182 else {
183 if (!PyArg_Parse(w, "s#", &drec.dptr, &drec.dsize)) {
184 PyErr_SetString(PyExc_TypeError,
Brett Cannon7317c1e2008-11-25 19:19:17 +0000185 "gdbm mappings have byte or string elements only");
Fred Drakee3a41c62000-07-08 05:00:07 +0000186 return -1;
187 }
188 errno = 0;
189 if (gdbm_store(dp->di_dbm, krec, drec, GDBM_REPLACE) < 0) {
190 if (errno != 0)
191 PyErr_SetFromErrno(DbmError);
192 else
193 PyErr_SetString(DbmError,
194 gdbm_strerror(gdbm_errno));
195 return -1;
196 }
197 }
198 return 0;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000199}
200
Georg Brandld9e833c2010-12-04 09:14:36 +0000201PyDoc_STRVAR(dbm_setdefault__doc__,
202"setdefault(key[, default]) -> value\n\
203Get value for key, or set it to default and return default if not present;\n\
204if not given, default is None.");
205
206static PyObject *
207dbm_setdefault(dbmobject *dp, PyObject *args)
208{
209 PyObject *v, *res;
210 PyObject *def = Py_None;
211
212 if (!PyArg_UnpackTuple(args, "setdefault", 1, 2, &v, &def))
213 return NULL;
214 res = dbm_subscript(dp, v);
215 if (res == NULL && PyErr_ExceptionMatches(PyExc_KeyError)) {
216 PyErr_Clear();
217 if (dbm_ass_sub(dp, v, def) < 0)
218 return NULL;
219 return dbm_subscript(dp, v);
220 }
221 return res;
222}
223
Roger E. Masseb15bef81996-12-17 19:55:33 +0000224static PyMappingMethods dbm_as_mapping = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000225 (lenfunc)dbm_length, /*mp_length*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000226 (binaryfunc)dbm_subscript, /*mp_subscript*/
227 (objobjargproc)dbm_ass_sub, /*mp_ass_subscript*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000228};
229
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000230PyDoc_STRVAR(dbm_close__doc__,
231"close() -> None\n\
232Closes the database.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000233
Roger E. Masseb15bef81996-12-17 19:55:33 +0000234static PyObject *
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000235dbm_close(register dbmobject *dp, PyObject *unused)
Guido van Rossum807b7be1995-07-07 22:37:11 +0000236{
Fred Drakee3a41c62000-07-08 05:00:07 +0000237 if (dp->di_dbm)
238 gdbm_close(dp->di_dbm);
239 dp->di_dbm = NULL;
240 Py_INCREF(Py_None);
241 return Py_None;
Guido van Rossum807b7be1995-07-07 22:37:11 +0000242}
243
Guido van Rossum6252e102007-05-23 20:51:02 +0000244/* XXX Should return a set or a set view */
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000245PyDoc_STRVAR(dbm_keys__doc__,
246"keys() -> list_of_keys\n\
247Get a list of all keys in the database.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000248
Roger E. Masseb15bef81996-12-17 19:55:33 +0000249static PyObject *
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000250dbm_keys(register dbmobject *dp, PyObject *unused)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000251{
Fred Drakee3a41c62000-07-08 05:00:07 +0000252 register PyObject *v, *item;
253 datum key, nextkey;
254 int err;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000255
Fred Drakee3a41c62000-07-08 05:00:07 +0000256 if (dp == NULL || !is_dbmobject(dp)) {
257 PyErr_BadInternalCall();
258 return NULL;
259 }
Fred Drakee3a41c62000-07-08 05:00:07 +0000260 check_dbmobject_open(dp);
Guido van Rossum3be71401996-07-21 02:32:44 +0000261
Fred Drakee3a41c62000-07-08 05:00:07 +0000262 v = PyList_New(0);
263 if (v == NULL)
264 return NULL;
Guido van Rossum77eecfa1997-07-17 22:56:01 +0000265
Fred Drakee3a41c62000-07-08 05:00:07 +0000266 key = gdbm_firstkey(dp->di_dbm);
267 while (key.dptr) {
Christian Heimes72b710a2008-05-26 13:28:38 +0000268 item = PyBytes_FromStringAndSize(key.dptr, key.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000269 if (item == NULL) {
270 free(key.dptr);
271 Py_DECREF(v);
272 return NULL;
273 }
274 err = PyList_Append(v, item);
275 Py_DECREF(item);
276 if (err != 0) {
277 free(key.dptr);
278 Py_DECREF(v);
279 return NULL;
280 }
281 nextkey = gdbm_nextkey(dp->di_dbm, key);
282 free(key.dptr);
283 key = nextkey;
284 }
285 return v;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000286}
287
Guido van Rossum0da7e032006-08-19 23:18:48 +0000288static int
289dbm_contains(PyObject *self, PyObject *arg)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000290{
Guido van Rossum0da7e032006-08-19 23:18:48 +0000291 dbmobject *dp = (dbmobject *)self;
Fred Drakee3a41c62000-07-08 05:00:07 +0000292 datum key;
293
Guido van Rossum0da7e032006-08-19 23:18:48 +0000294 if ((dp)->di_dbm == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000295 PyErr_SetString(DbmError,
296 "GDBM object has already been closed");
297 return -1;
Guido van Rossum0da7e032006-08-19 23:18:48 +0000298 }
Christian Heimes72b710a2008-05-26 13:28:38 +0000299 if (!PyBytes_Check(arg)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000300 PyErr_Format(PyExc_TypeError,
301 "gdbm key must be bytes, not %.100s",
302 arg->ob_type->tp_name);
303 return -1;
Guido van Rossum0da7e032006-08-19 23:18:48 +0000304 }
Christian Heimes72b710a2008-05-26 13:28:38 +0000305 key.dptr = PyBytes_AS_STRING(arg);
306 key.dsize = PyBytes_GET_SIZE(arg);
Guido van Rossum0da7e032006-08-19 23:18:48 +0000307 return gdbm_exists(dp->di_dbm, key);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000308}
309
Guido van Rossum0da7e032006-08-19 23:18:48 +0000310static PySequenceMethods dbm_as_sequence = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000311 0, /* sq_length */
312 0, /* sq_concat */
313 0, /* sq_repeat */
314 0, /* sq_item */
315 0, /* sq_slice */
316 0, /* sq_ass_item */
317 0, /* sq_ass_slice */
318 dbm_contains, /* sq_contains */
319 0, /* sq_inplace_concat */
320 0, /* sq_inplace_repeat */
Guido van Rossum0da7e032006-08-19 23:18:48 +0000321};
322
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000323PyDoc_STRVAR(dbm_firstkey__doc__,
324"firstkey() -> key\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000325It's possible to loop over every key in the database using this method\n\
326and the nextkey() method. The traversal is ordered by GDBM's internal\n\
327hash values, and won't be sorted by the key values. This method\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000328returns the starting key.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000329
Roger E. Masseb15bef81996-12-17 19:55:33 +0000330static PyObject *
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000331dbm_firstkey(register dbmobject *dp, PyObject *unused)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000332{
Fred Drakee3a41c62000-07-08 05:00:07 +0000333 register PyObject *v;
334 datum key;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000335
Fred Drakee3a41c62000-07-08 05:00:07 +0000336 check_dbmobject_open(dp);
337 key = gdbm_firstkey(dp->di_dbm);
338 if (key.dptr) {
Christian Heimes72b710a2008-05-26 13:28:38 +0000339 v = PyBytes_FromStringAndSize(key.dptr, key.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000340 free(key.dptr);
341 return v;
342 }
343 else {
344 Py_INCREF(Py_None);
345 return Py_None;
346 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000347}
348
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000349PyDoc_STRVAR(dbm_nextkey__doc__,
350"nextkey(key) -> next_key\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000351Returns the key that follows key in the traversal.\n\
352The following code prints every key in the database db, without having\n\
353to create a list in memory that contains them all:\n\
354\n\
355 k = db.firstkey()\n\
356 while k != None:\n\
357 print k\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000358 k = db.nextkey(k)");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000359
Roger E. Masseb15bef81996-12-17 19:55:33 +0000360static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000361dbm_nextkey(register dbmobject *dp, PyObject *args)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000362{
Fred Drakee3a41c62000-07-08 05:00:07 +0000363 register PyObject *v;
364 datum key, nextkey;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000365
Fred Drakee3a41c62000-07-08 05:00:07 +0000366 if (!PyArg_ParseTuple(args, "s#:nextkey", &key.dptr, &key.dsize))
367 return NULL;
368 check_dbmobject_open(dp);
369 nextkey = gdbm_nextkey(dp->di_dbm, key);
370 if (nextkey.dptr) {
Christian Heimes72b710a2008-05-26 13:28:38 +0000371 v = PyBytes_FromStringAndSize(nextkey.dptr, nextkey.dsize);
Fred Drakee3a41c62000-07-08 05:00:07 +0000372 free(nextkey.dptr);
373 return v;
374 }
375 else {
376 Py_INCREF(Py_None);
377 return Py_None;
378 }
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000379}
380
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000381PyDoc_STRVAR(dbm_reorganize__doc__,
382"reorganize() -> None\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000383If you have carried out a lot of deletions and would like to shrink\n\
384the space used by the GDBM file, this routine will reorganize the\n\
385database. GDBM will not shorten the length of a database file except\n\
386by using this reorganization; otherwise, deleted file space will be\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000387kept and reused as new (key,value) pairs are added.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000388
Roger E. Masseb15bef81996-12-17 19:55:33 +0000389static PyObject *
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000390dbm_reorganize(register dbmobject *dp, PyObject *unused)
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000391{
Fred Drakee3a41c62000-07-08 05:00:07 +0000392 check_dbmobject_open(dp);
393 errno = 0;
394 if (gdbm_reorganize(dp->di_dbm) < 0) {
395 if (errno != 0)
396 PyErr_SetFromErrno(DbmError);
397 else
398 PyErr_SetString(DbmError, gdbm_strerror(gdbm_errno));
399 return NULL;
400 }
401 Py_INCREF(Py_None);
402 return Py_None;
Guido van Rossumfbd30e91995-03-16 16:07:34 +0000403}
404
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000405PyDoc_STRVAR(dbm_sync__doc__,
406"sync() -> None\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000407When the database has been opened in fast mode, this method forces\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000408any unwritten data to be written to the disk.");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000409
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000410static PyObject *
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000411dbm_sync(register dbmobject *dp, PyObject *unused)
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000412{
Fred Drakee3a41c62000-07-08 05:00:07 +0000413 check_dbmobject_open(dp);
414 gdbm_sync(dp->di_dbm);
415 Py_INCREF(Py_None);
416 return Py_None;
Roger E. Massee5a9c8f1997-03-25 17:39:56 +0000417}
418
Roger E. Masseb15bef81996-12-17 19:55:33 +0000419static PyMethodDef dbm_methods[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000420 {"close", (PyCFunction)dbm_close, METH_NOARGS, dbm_close__doc__},
421 {"keys", (PyCFunction)dbm_keys, METH_NOARGS, dbm_keys__doc__},
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000422 {"firstkey", (PyCFunction)dbm_firstkey,METH_NOARGS, dbm_firstkey__doc__},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000423 {"nextkey", (PyCFunction)dbm_nextkey, METH_VARARGS, dbm_nextkey__doc__},
Thomas Wouters4d70c3d2006-06-08 14:42:34 +0000424 {"reorganize",(PyCFunction)dbm_reorganize,METH_NOARGS, dbm_reorganize__doc__},
425 {"sync", (PyCFunction)dbm_sync, METH_NOARGS, dbm_sync__doc__},
Georg Brandld9e833c2010-12-04 09:14:36 +0000426 {"get", (PyCFunction)dbm_get, METH_VARARGS, dbm_get__doc__},
427 {"setdefault",(PyCFunction)dbm_setdefault,METH_VARARGS, dbm_setdefault__doc__},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000428 {NULL, NULL} /* sentinel */
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000429};
430
Roger E. Masseb15bef81996-12-17 19:55:33 +0000431static PyTypeObject Dbmtype = {
Martin v. Löwis9f2e3462007-07-21 17:22:18 +0000432 PyVarObject_HEAD_INIT(0, 0)
Georg Brandl0a7ac7d2008-05-26 10:29:35 +0000433 "_gdbm.gdbm",
Fred Drakee3a41c62000-07-08 05:00:07 +0000434 sizeof(dbmobject),
435 0,
436 (destructor)dbm_dealloc, /*tp_dealloc*/
437 0, /*tp_print*/
Amaury Forgeot d'Arc1f900f12008-07-02 22:38:47 +0000438 0, /*tp_getattr*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000439 0, /*tp_setattr*/
Mark Dickinsone94c6792009-02-02 20:36:42 +0000440 0, /*tp_reserved*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000441 0, /*tp_repr*/
442 0, /*tp_as_number*/
Guido van Rossum0da7e032006-08-19 23:18:48 +0000443 &dbm_as_sequence, /*tp_as_sequence*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000444 &dbm_as_mapping, /*tp_as_mapping*/
445 0, /*tp_hash*/
446 0, /*tp_call*/
447 0, /*tp_str*/
448 0, /*tp_getattro*/
449 0, /*tp_setattro*/
450 0, /*tp_as_buffer*/
Christian Heimes836baa52008-02-26 08:18:30 +0000451 Py_TPFLAGS_DEFAULT, /*tp_xxx4*/
Fred Drakee3a41c62000-07-08 05:00:07 +0000452 gdbm_object__doc__, /*tp_doc*/
Amaury Forgeot d'Arc1f900f12008-07-02 22:38:47 +0000453 0, /*tp_traverse*/
454 0, /*tp_clear*/
455 0, /*tp_richcompare*/
456 0, /*tp_weaklistoffset*/
457 0, /*tp_iter*/
458 0, /*tp_iternext*/
459 dbm_methods, /*tp_methods*/
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000460};
461
462/* ----------------------------------------------------------------- */
463
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000464PyDoc_STRVAR(dbmopen__doc__,
465"open(filename, [flags, [mode]]) -> dbm_object\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000466Open a dbm database and return a dbm object. The filename argument is\n\
467the name of the database file.\n\
468\n\
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000469The optional flags argument can be 'r' (to open an existing database\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000470for reading only -- default), 'w' (to open an existing database for\n\
471reading and writing), 'c' (which creates the database if it doesn't\n\
472exist), or 'n' (which always creates a new empty database).\n\
473\n\
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000474Some versions of gdbm support additional flags which must be\n\
475appended to one of the flags described above. The module constant\n\
476'open_flags' is a string of valid additional flags. The 'f' flag\n\
477opens the database in fast mode; altered data will not automatically\n\
478be written to the disk after every change. This results in faster\n\
479writes to the database, but may result in an inconsistent database\n\
480if the program crashes while the database is still open. Use the\n\
481sync() method to force any unwritten data to be written to the disk.\n\
482The 's' flag causes all database operations to be synchronized to\n\
483disk. The 'u' flag disables locking of the database file.\n\
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000484\n\
485The optional mode argument is the Unix mode of the file, used only\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000486when the database has to be created. It defaults to octal 0666. ");
Guido van Rossumbfc49e81998-03-03 22:02:24 +0000487
Roger E. Masseb15bef81996-12-17 19:55:33 +0000488static PyObject *
Fred Drakee3a41c62000-07-08 05:00:07 +0000489dbmopen(PyObject *self, PyObject *args)
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000490{
Fred Drakee3a41c62000-07-08 05:00:07 +0000491 char *name;
Andrew M. Kuchlingea271f22004-07-07 14:19:09 +0000492 char *flags = "r";
Fred Drakee3a41c62000-07-08 05:00:07 +0000493 int iflags;
494 int mode = 0666;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000495
Fred Drakee3a41c62000-07-08 05:00:07 +0000496 if (!PyArg_ParseTuple(args, "s|si:open", &name, &flags, &mode))
497 return NULL;
498 switch (flags[0]) {
499 case 'r':
500 iflags = GDBM_READER;
501 break;
502 case 'w':
503 iflags = GDBM_WRITER;
504 break;
505 case 'c':
506 iflags = GDBM_WRCREAT;
507 break;
508 case 'n':
509 iflags = GDBM_NEWDB;
510 break;
511 default:
512 PyErr_SetString(DbmError,
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000513 "First flag must be one of 'r', 'w', 'c' or 'n'");
Fred Drakee3a41c62000-07-08 05:00:07 +0000514 return NULL;
515 }
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000516 for (flags++; *flags != '\0'; flags++) {
517 char buf[40];
518 switch (*flags) {
519#ifdef GDBM_FAST
520 case 'f':
521 iflags |= GDBM_FAST;
522 break;
523#endif
524#ifdef GDBM_SYNC
525 case 's':
526 iflags |= GDBM_SYNC;
527 break;
528#endif
529#ifdef GDBM_NOLOCK
530 case 'u':
531 iflags |= GDBM_NOLOCK;
532 break;
533#endif
534 default:
Tim Peters885d4572001-11-28 20:27:42 +0000535 PyOS_snprintf(buf, sizeof(buf), "Flag '%c' is not supported.",
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000536 *flags);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000537 PyErr_SetString(DbmError, buf);
538 return NULL;
539 }
540 }
541
Fred Drakee3a41c62000-07-08 05:00:07 +0000542 return newdbmobject(name, iflags, mode);
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000543}
544
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000545static char dbmmodule_open_flags[] = "rwcn"
546#ifdef GDBM_FAST
547 "f"
548#endif
549#ifdef GDBM_SYNC
550 "s"
551#endif
552#ifdef GDBM_NOLOCK
553 "u"
554#endif
555 ;
556
Roger E. Masseb15bef81996-12-17 19:55:33 +0000557static PyMethodDef dbmmodule_methods[] = {
Fred Drakee3a41c62000-07-08 05:00:07 +0000558 { "open", (PyCFunction)dbmopen, METH_VARARGS, dbmopen__doc__},
559 { 0, 0 },
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000560};
561
Martin v. Löwis1a214512008-06-11 05:26:20 +0000562
563static struct PyModuleDef _gdbmmodule = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000564 PyModuleDef_HEAD_INIT,
565 "_gdbm",
566 gdbmmodule__doc__,
567 -1,
568 dbmmodule_methods,
569 NULL,
570 NULL,
571 NULL,
572 NULL
Martin v. Löwis1a214512008-06-11 05:26:20 +0000573};
574
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000575PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000576PyInit__gdbm(void) {
Martin v. Löwis00ff10c2001-11-11 14:24:05 +0000577 PyObject *m, *d, *s;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000578
Guido van Rossum0da7e032006-08-19 23:18:48 +0000579 if (PyType_Ready(&Dbmtype) < 0)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000580 return NULL;
Martin v. Löwis1a214512008-06-11 05:26:20 +0000581 m = PyModule_Create(&_gdbmmodule);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000582 if (m == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000583 return NULL;
Fred Drakee3a41c62000-07-08 05:00:07 +0000584 d = PyModule_GetDict(m);
Georg Brandlb17acad2008-05-28 08:43:17 +0000585 DbmError = PyErr_NewException("_gdbm.error", PyExc_IOError, NULL);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000586 if (DbmError != NULL) {
Fred Drakee3a41c62000-07-08 05:00:07 +0000587 PyDict_SetItemString(d, "error", DbmError);
Martin v. Löwis7ac97122007-08-11 19:28:53 +0000588 s = PyUnicode_FromString(dbmmodule_open_flags);
Martin v. Löwis00ff10c2001-11-11 14:24:05 +0000589 PyDict_SetItemString(d, "open_flags", s);
590 Py_DECREF(s);
Neil Schemenauere9e860f2000-12-17 07:14:13 +0000591 }
Martin v. Löwis1a214512008-06-11 05:26:20 +0000592 return m;
Guido van Rossum4b4c6641994-08-08 08:06:37 +0000593}