~malept/ubuntu/lucid/python2.6/dev-dependency-fix

« back to all changes in this revision

Viewing changes to Modules/dbmmodule.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-02-13 12:51:00 UTC
  • Revision ID: james.westby@ubuntu.com-20090213125100-uufgcb9yeqzujpqw
Tags: upstream-2.6.1
ImportĀ upstreamĀ versionĀ 2.6.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/* DBM module using dictionary interface */
 
3
 
 
4
 
 
5
#include "Python.h"
 
6
 
 
7
#include <sys/types.h>
 
8
#include <sys/stat.h>
 
9
#include <fcntl.h>
 
10
 
 
11
/* Some Linux systems install gdbm/ndbm.h, but not ndbm.h.  This supports
 
12
 * whichever configure was able to locate.
 
13
 */
 
14
#if defined(HAVE_NDBM_H)
 
15
#include <ndbm.h>
 
16
#if defined(PYOS_OS2) && !defined(PYCC_GCC)
 
17
static char *which_dbm = "ndbm";
 
18
#else
 
19
static char *which_dbm = "GNU gdbm";  /* EMX port of GDBM */
 
20
#endif
 
21
#elif defined(HAVE_GDBM_NDBM_H)
 
22
#include <gdbm/ndbm.h>
 
23
static char *which_dbm = "GNU gdbm";
 
24
#elif defined(HAVE_BERKDB_H)
 
25
#include <db.h>
 
26
static char *which_dbm = "Berkeley DB";
 
27
#else
 
28
#error "No ndbm.h available!"
 
29
#endif
 
30
 
 
31
typedef struct {
 
32
        PyObject_HEAD
 
33
        int di_size;    /* -1 means recompute */
 
34
        DBM *di_dbm;
 
35
} dbmobject;
 
36
 
 
37
static PyTypeObject Dbmtype;
 
38
 
 
39
#define is_dbmobject(v) (Py_TYPE(v) == &Dbmtype)
 
40
#define check_dbmobject_open(v) if ((v)->di_dbm == NULL) \
 
41
               { PyErr_SetString(DbmError, "DBM object has already been closed"); \
 
42
                 return NULL; }
 
43
 
 
44
static PyObject *DbmError;
 
45
 
 
46
static PyObject *
 
47
newdbmobject(char *file, int flags, int mode)
 
48
{
 
49
        dbmobject *dp;
 
50
 
 
51
        dp = PyObject_New(dbmobject, &Dbmtype);
 
52
        if (dp == NULL)
 
53
                return NULL;
 
54
        dp->di_size = -1;
 
55
        if ( (dp->di_dbm = dbm_open(file, flags, mode)) == 0 ) {
 
56
                PyErr_SetFromErrno(DbmError);
 
57
                Py_DECREF(dp);
 
58
                return NULL;
 
59
        }
 
60
        return (PyObject *)dp;
 
61
}
 
62
 
 
63
/* Methods */
 
64
 
 
65
static void
 
66
dbm_dealloc(register dbmobject *dp)
 
67
{
 
68
        if ( dp->di_dbm )
 
69
                dbm_close(dp->di_dbm);
 
70
        PyObject_Del(dp);
 
71
}
 
72
 
 
73
static Py_ssize_t
 
74
dbm_length(dbmobject *dp)
 
75
{
 
76
        if (dp->di_dbm == NULL) {
 
77
                 PyErr_SetString(DbmError, "DBM object has already been closed"); 
 
78
                 return -1; 
 
79
        }
 
80
        if ( dp->di_size < 0 ) {
 
81
                datum key;
 
82
                int size;
 
83
 
 
84
                size = 0;
 
85
                for ( key=dbm_firstkey(dp->di_dbm); key.dptr;
 
86
                      key = dbm_nextkey(dp->di_dbm))
 
87
                        size++;
 
88
                dp->di_size = size;
 
89
        }
 
90
        return dp->di_size;
 
91
}
 
92
 
 
93
static PyObject *
 
94
dbm_subscript(dbmobject *dp, register PyObject *key)
 
95
{
 
96
        datum drec, krec;
 
97
        int tmp_size;
 
98
        
 
99
        if (!PyArg_Parse(key, "s#", &krec.dptr, &tmp_size) )
 
100
                return NULL;
 
101
        
 
102
        krec.dsize = tmp_size;
 
103
        check_dbmobject_open(dp);
 
104
        drec = dbm_fetch(dp->di_dbm, krec);
 
105
        if ( drec.dptr == 0 ) {
 
106
                PyErr_SetString(PyExc_KeyError,
 
107
                                PyString_AS_STRING((PyStringObject *)key));
 
108
                return NULL;
 
109
        }
 
110
        if ( dbm_error(dp->di_dbm) ) {
 
111
                dbm_clearerr(dp->di_dbm);
 
112
                PyErr_SetString(DbmError, "");
 
113
                return NULL;
 
114
        }
 
115
        return PyString_FromStringAndSize(drec.dptr, drec.dsize);
 
116
}
 
117
 
 
118
static int
 
119
dbm_ass_sub(dbmobject *dp, PyObject *v, PyObject *w)
 
120
{
 
121
        datum krec, drec;
 
122
        int tmp_size;
 
123
        
 
124
        if ( !PyArg_Parse(v, "s#", &krec.dptr, &tmp_size) ) {
 
125
                PyErr_SetString(PyExc_TypeError,
 
126
                                "dbm mappings have string indices only");
 
127
                return -1;
 
128
        }
 
129
        krec.dsize = tmp_size;
 
130
        if (dp->di_dbm == NULL) {
 
131
                 PyErr_SetString(DbmError, "DBM object has already been closed"); 
 
132
                 return -1;
 
133
        }
 
134
        dp->di_size = -1;
 
135
        if (w == NULL) {
 
136
                if ( dbm_delete(dp->di_dbm, krec) < 0 ) {
 
137
                        dbm_clearerr(dp->di_dbm);
 
138
                        PyErr_SetString(PyExc_KeyError,
 
139
                                      PyString_AS_STRING((PyStringObject *)v));
 
140
                        return -1;
 
141
                }
 
142
        } else {
 
143
                if ( !PyArg_Parse(w, "s#", &drec.dptr, &tmp_size) ) {
 
144
                        PyErr_SetString(PyExc_TypeError,
 
145
                                     "dbm mappings have string elements only");
 
146
                        return -1;
 
147
                }
 
148
                drec.dsize = tmp_size;
 
149
                if ( dbm_store(dp->di_dbm, krec, drec, DBM_REPLACE) < 0 ) {
 
150
                        dbm_clearerr(dp->di_dbm);
 
151
                        PyErr_SetString(DbmError,
 
152
                                        "cannot add item to database");
 
153
                        return -1;
 
154
                }
 
155
        }
 
156
        if ( dbm_error(dp->di_dbm) ) {
 
157
                dbm_clearerr(dp->di_dbm);
 
158
                PyErr_SetString(DbmError, "");
 
159
                return -1;
 
160
        }
 
161
        return 0;
 
162
}
 
163
 
 
164
static int
 
165
dbm_contains(register dbmobject *dp, PyObject *v)
 
166
{
 
167
        datum key, val;
 
168
 
 
169
        if (PyString_AsStringAndSize(v, (char **)&key.dptr,
 
170
                                     (Py_ssize_t *)&key.dsize)) {
 
171
                return -1;
 
172
        }
 
173
 
 
174
        /* Expand check_dbmobject_open to return -1 */
 
175
        if (dp->di_dbm == NULL) {
 
176
                PyErr_SetString(DbmError, "DBM object has already been closed");
 
177
                return -1;
 
178
        }
 
179
        val = dbm_fetch(dp->di_dbm, key);
 
180
        return val.dptr != NULL;
 
181
}
 
182
 
 
183
static PySequenceMethods dbm_as_sequence = {
 
184
    (lenfunc)dbm_length,        /*_length*/
 
185
    0,                          /*sq_concat*/
 
186
    0,                          /*sq_repeat*/
 
187
    0,                          /*sq_item*/
 
188
    0,                          /*sq_slice*/
 
189
    0,                          /*sq_ass_item*/
 
190
    0,                          /*sq_ass_slice*/
 
191
    (objobjproc)dbm_contains,   /*sq_contains*/
 
192
    0,                          /*sq_inplace_concat*/
 
193
    0                           /*sq_inplace_repeat*/
 
194
};
 
195
 
 
196
static PyMappingMethods dbm_as_mapping = {
 
197
        (lenfunc)dbm_length,            /*mp_length*/
 
198
        (binaryfunc)dbm_subscript,      /*mp_subscript*/
 
199
        (objobjargproc)dbm_ass_sub,     /*mp_ass_subscript*/
 
200
};
 
201
 
 
202
static PyObject *
 
203
dbm__close(register dbmobject *dp, PyObject *unused)
 
204
{
 
205
        if (dp->di_dbm)
 
206
                dbm_close(dp->di_dbm);
 
207
        dp->di_dbm = NULL;
 
208
        Py_INCREF(Py_None);
 
209
        return Py_None;
 
210
}
 
211
 
 
212
static PyObject *
 
213
dbm_keys(register dbmobject *dp, PyObject *unused)
 
214
{
 
215
        register PyObject *v, *item;
 
216
        datum key;
 
217
        int err;
 
218
 
 
219
        check_dbmobject_open(dp);
 
220
        v = PyList_New(0);
 
221
        if (v == NULL)
 
222
                return NULL;
 
223
        for (key = dbm_firstkey(dp->di_dbm); key.dptr;
 
224
             key = dbm_nextkey(dp->di_dbm)) {
 
225
                item = PyString_FromStringAndSize(key.dptr, key.dsize);
 
226
                if (item == NULL) {
 
227
                        Py_DECREF(v);
 
228
                        return NULL;
 
229
                }
 
230
                err = PyList_Append(v, item);
 
231
                Py_DECREF(item);
 
232
                if (err != 0) {
 
233
                        Py_DECREF(v);
 
234
                        return NULL;
 
235
                }
 
236
        }
 
237
        return v;
 
238
}
 
239
 
 
240
static PyObject *
 
241
dbm_has_key(register dbmobject *dp, PyObject *args)
 
242
{
 
243
        char *tmp_ptr;
 
244
        datum key, val;
 
245
        int tmp_size;
 
246
        
 
247
        if (!PyArg_ParseTuple(args, "s#:has_key", &tmp_ptr, &tmp_size))
 
248
                return NULL;
 
249
        key.dptr = tmp_ptr;
 
250
        key.dsize = tmp_size;
 
251
        check_dbmobject_open(dp);
 
252
        val = dbm_fetch(dp->di_dbm, key);
 
253
        return PyInt_FromLong(val.dptr != NULL);
 
254
}
 
255
 
 
256
static PyObject *
 
257
dbm_get(register dbmobject *dp, PyObject *args)
 
258
{
 
259
        datum key, val;
 
260
        PyObject *defvalue = Py_None;
 
261
        char *tmp_ptr;
 
262
        int tmp_size;
 
263
 
 
264
        if (!PyArg_ParseTuple(args, "s#|O:get",
 
265
                              &tmp_ptr, &tmp_size, &defvalue))
 
266
                return NULL;
 
267
        key.dptr = tmp_ptr;
 
268
        key.dsize = tmp_size;
 
269
        check_dbmobject_open(dp);
 
270
        val = dbm_fetch(dp->di_dbm, key);
 
271
        if (val.dptr != NULL)
 
272
                return PyString_FromStringAndSize(val.dptr, val.dsize);
 
273
        else {
 
274
                Py_INCREF(defvalue);
 
275
                return defvalue;
 
276
        }
 
277
}
 
278
 
 
279
static PyObject *
 
280
dbm_setdefault(register dbmobject *dp, PyObject *args)
 
281
{
 
282
        datum key, val;
 
283
        PyObject *defvalue = NULL;
 
284
        char *tmp_ptr;
 
285
        int tmp_size;
 
286
 
 
287
        if (!PyArg_ParseTuple(args, "s#|S:setdefault",
 
288
                              &tmp_ptr, &tmp_size, &defvalue))
 
289
                return NULL;
 
290
        key.dptr = tmp_ptr;
 
291
        key.dsize = tmp_size;
 
292
        check_dbmobject_open(dp);
 
293
        val = dbm_fetch(dp->di_dbm, key);
 
294
        if (val.dptr != NULL)
 
295
                return PyString_FromStringAndSize(val.dptr, val.dsize);
 
296
        if (defvalue == NULL) {
 
297
                defvalue = PyString_FromStringAndSize(NULL, 0);
 
298
                if (defvalue == NULL)
 
299
                        return NULL;
 
300
        }
 
301
        else
 
302
                Py_INCREF(defvalue);
 
303
        val.dptr = PyString_AS_STRING(defvalue);
 
304
        val.dsize = PyString_GET_SIZE(defvalue);
 
305
        if (dbm_store(dp->di_dbm, key, val, DBM_INSERT) < 0) {
 
306
                dbm_clearerr(dp->di_dbm);
 
307
                PyErr_SetString(DbmError, "cannot add item to database");
 
308
                return NULL;
 
309
        }
 
310
        return defvalue;
 
311
}
 
312
 
 
313
static PyMethodDef dbm_methods[] = {
 
314
        {"close",       (PyCFunction)dbm__close,        METH_NOARGS,
 
315
         "close()\nClose the database."},
 
316
        {"keys",        (PyCFunction)dbm_keys,          METH_NOARGS,
 
317
         "keys() -> list\nReturn a list of all keys in the database."},
 
318
        {"has_key",     (PyCFunction)dbm_has_key,       METH_VARARGS,
 
319
         "has_key(key} -> boolean\nReturn true iff key is in the database."},
 
320
        {"get",         (PyCFunction)dbm_get,           METH_VARARGS,
 
321
         "get(key[, default]) -> value\n"
 
322
         "Return the value for key if present, otherwise default."},
 
323
        {"setdefault",  (PyCFunction)dbm_setdefault,    METH_VARARGS,
 
324
         "setdefault(key[, default]) -> value\n"
 
325
         "Return the value for key if present, otherwise default.  If key\n"
 
326
         "is not in the database, it is inserted with default as the value."},
 
327
        {NULL,          NULL}           /* sentinel */
 
328
};
 
329
 
 
330
static PyObject *
 
331
dbm_getattr(dbmobject *dp, char *name)
 
332
{
 
333
        return Py_FindMethod(dbm_methods, (PyObject *)dp, name);
 
334
}
 
335
 
 
336
static PyTypeObject Dbmtype = {
 
337
        PyVarObject_HEAD_INIT(NULL, 0)
 
338
        "dbm.dbm",
 
339
        sizeof(dbmobject),
 
340
        0,
 
341
        (destructor)dbm_dealloc,  /*tp_dealloc*/
 
342
        0,                        /*tp_print*/
 
343
        (getattrfunc)dbm_getattr, /*tp_getattr*/
 
344
        0,                        /*tp_setattr*/
 
345
        0,                        /*tp_compare*/
 
346
        0,                        /*tp_repr*/
 
347
        0,                        /*tp_as_number*/
 
348
    &dbm_as_sequence,     /*tp_as_sequence*/
 
349
        &dbm_as_mapping,          /*tp_as_mapping*/
 
350
    0,                    /*tp_hash*/
 
351
    0,                    /*tp_call*/
 
352
    0,                    /*tp_str*/
 
353
    0,                    /*tp_getattro*/
 
354
    0,                    /*tp_setattro*/
 
355
    0,                    /*tp_as_buffer*/
 
356
    Py_TPFLAGS_DEFAULT,   /*tp_xxx4*/
 
357
};
 
358
 
 
359
/* ----------------------------------------------------------------- */
 
360
 
 
361
static PyObject *
 
362
dbmopen(PyObject *self, PyObject *args)
 
363
{
 
364
        char *name;
 
365
        char *flags = "r";
 
366
        int iflags;
 
367
        int mode = 0666;
 
368
 
 
369
        if ( !PyArg_ParseTuple(args, "s|si:open", &name, &flags, &mode) )
 
370
                return NULL;
 
371
        if ( strcmp(flags, "r") == 0 )
 
372
                iflags = O_RDONLY;
 
373
        else if ( strcmp(flags, "w") == 0 )
 
374
                iflags = O_RDWR;
 
375
        else if ( strcmp(flags, "rw") == 0 ) /* B/W compat */
 
376
                iflags = O_RDWR|O_CREAT; 
 
377
        else if ( strcmp(flags, "c") == 0 )
 
378
                iflags = O_RDWR|O_CREAT;
 
379
        else if ( strcmp(flags, "n") == 0 )
 
380
                iflags = O_RDWR|O_CREAT|O_TRUNC;
 
381
        else {
 
382
                PyErr_SetString(DbmError,
 
383
                                "arg 2 to open should be 'r', 'w', 'c', or 'n'");
 
384
                return NULL;
 
385
        }
 
386
        return newdbmobject(name, iflags, mode);
 
387
}
 
388
 
 
389
static PyMethodDef dbmmodule_methods[] = {
 
390
        { "open", (PyCFunction)dbmopen, METH_VARARGS,
 
391
          "open(path[, flag[, mode]]) -> mapping\n"
 
392
          "Return a database object."},
 
393
        { 0, 0 },
 
394
};
 
395
 
 
396
PyMODINIT_FUNC
 
397
initdbm(void) {
 
398
        PyObject *m, *d, *s;
 
399
 
 
400
        Dbmtype.ob_type = &PyType_Type;
 
401
        m = Py_InitModule("dbm", dbmmodule_methods);
 
402
        if (m == NULL)
 
403
                return;
 
404
        d = PyModule_GetDict(m);
 
405
        if (DbmError == NULL)
 
406
                DbmError = PyErr_NewException("dbm.error", NULL, NULL);
 
407
        s = PyString_FromString(which_dbm);
 
408
        if (s != NULL) {
 
409
                PyDict_SetItemString(d, "library", s);
 
410
                Py_DECREF(s);
 
411
        }
 
412
        if (DbmError != NULL)
 
413
                PyDict_SetItemString(d, "error", DbmError);
 
414
}