/[thuban]/branches/WIP-pyshapelib-bramz/libraries/pyshapelib/dbflibmodule.c
ViewVC logotype

Annotation of /branches/WIP-pyshapelib-bramz/libraries/pyshapelib/dbflibmodule.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1917 - (hide annotations)
Mon Nov 3 17:31:11 2003 UTC (21 years, 4 months ago) by bh
Original Path: trunk/thuban/libraries/pyshapelib/dbflib.i
File size: 13922 byte(s)
* dbflib.i (do_read_attribute): New helper function for reading
one attribute as a python object
(DBFInfo_read_attribute): New. Implement the read_attribute method
(DBFInfo_read_record): Use do_read_attribute to read the
individual values
(struct DBFFile): Add the read_attribute method.

* dbflib_wrap.c, dbflib.py: Update from dbflib.i.

1 jan 1611 /* SWIG (www.swig.org) interface file for the dbf interface of shapelib
2     *
3     * At the moment (Dec 2000) this file is only useful to generate Python
4     * bindings. Invoke swig as follows:
5     *
6     * swig -python -shadow dbflib.i
7     *
8     * to generate dbflib_wrap.c and dbflib.py. dbflib_wrap.c defines a
9     * bunch of Python-functions that wrap the appripriate dbflib functions
10     * and dbflib.py contains an object oriented wrapper around
11     * dbflib_wrap.c.
12     *
13     * This module defines one object type: DBFFile.
14     */
15    
16     /* this is the dbflib module */
17     %module dbflib
18    
19     /* first a %{,%} block. These blocks are copied verbatim to the
20     * dbflib_wrap.c file and are not parsed by SWIG. This is the place to
21     * import headerfiles and define helper-functions that are needed by the
22     * automatically generated wrappers.
23     */
24    
25     %{
26     #include "shapefil.h"
27    
28 bh 1917
29     /* Read one attribute from the dbf handle and return it as a new python object
30     *
31     * If an error occurs, set the appropriate Python exception and return
32     * NULL.
33     *
34     * Assume that the values of the record and field arguments are valid.
35     * The name argument will be passed to DBFGetFieldInfo as is and should
36     * thus be either NULL or a pointer to an array of at least 12 chars
37     */
38     static PyObject *
39     do_read_attribute(DBFInfo * handle, int record, int field, char * name)
40     {
41     int type, width;
42     PyObject *value;
43    
44     type = DBFGetFieldInfo(handle, field, name, &width, NULL);
45     /* For strings NULL and the empty string are indistinguishable
46     * in DBF files. We prefer empty strings instead for backwards
47     * compatibility reasons because older wrapper versions returned
48     * emtpy strings as empty strings.
49     */
50     if (type != FTString && DBFIsAttributeNULL(handle, record, field))
51     {
52     value = Py_None;
53     Py_INCREF(value);
54     }
55     else
56     {
57     switch (type)
58     {
59     case FTString:
60     {
61     const char * temp = DBFReadStringAttribute(handle, record, field);
62     if (temp)
63     {
64     value = PyString_FromString(temp);
65     }
66     else
67     {
68     PyErr_Format(PyExc_IOError,
69     "Can't read value for row %d column %d",
70     record, field);
71     value = NULL;
72     }
73     break;
74     }
75     case FTInteger:
76     value = PyInt_FromLong(DBFReadIntegerAttribute(handle, record,
77     field));
78     break;
79     case FTDouble:
80     value = PyFloat_FromDouble(DBFReadDoubleAttribute(handle, record,
81     field));
82     break;
83     default:
84     PyErr_Format(PyExc_TypeError, "Invalid field data type %d",
85     type);
86     value = NULL;
87     }
88     }
89     if (!value)
90     return NULL;
91    
92     return value;
93     }
94    
95     /* the read_attribute method. Return the value of the given record and
96     * field as a python object of the appropriate type.
97     *
98     * In case of error, set a python exception and return NULL. Since that
99     * value will be returned to the python interpreter as is, the
100     * interpreter should recognize the exception.
101     */
102    
103     static PyObject *
104     DBFInfo_read_attribute(DBFInfo * handle, int record, int field)
105     {
106     if (record < 0 || record >= DBFGetRecordCount(handle))
107     {
108     PyErr_Format(PyExc_ValueError,
109     "record index %d out of bounds (record count: %d)",
110     record, DBFGetRecordCount(handle));
111     return NULL;
112     }
113    
114     if (field < 0 || field >= DBFGetFieldCount(handle))
115     {
116     PyErr_Format(PyExc_ValueError,
117     "field index %d out of bounds (field count: %d)",
118     field, DBFGetFieldCount(handle));
119     return NULL;
120     }
121    
122     return do_read_attribute(handle, record, field, NULL);
123     }
124    
125    
126 jan 1611 /* the read_record method. Return the record record as a dictionary with
127     * whose keys are the names of the fields, and their values as the
128     * appropriate Python type.
129     *
130     * In case of error, set a python exception and return NULL. Since that
131     * value will be returned to the python interpreter as is, the
132     * interpreter should recognize the exception.
133     */
134    
135     static PyObject *
136     DBFInfo_read_record(DBFInfo * handle, int record)
137     {
138     int num_fields;
139     int i;
140     int type, width;
141     char name[12];
142     PyObject *dict;
143     PyObject *value;
144    
145     if (record < 0 || record >= DBFGetRecordCount(handle))
146     {
147     PyErr_Format(PyExc_ValueError,
148     "record index %d out of bounds (record count: %d)",
149     record, DBFGetRecordCount(handle));
150     return NULL;
151     }
152    
153     dict = PyDict_New();
154     if (!dict)
155     return NULL;
156    
157     num_fields = DBFGetFieldCount(handle);
158     for (i = 0; i < num_fields; i++)
159     {
160 bh 1917 value = do_read_attribute(handle, record, i, name);
161 jan 1611 if (!value)
162     goto fail;
163 bh 1917
164 jan 1611 PyDict_SetItemString(dict, name, value);
165     Py_DECREF(value);
166     }
167    
168     return dict;
169 bh 1917
170 jan 1611 fail:
171     Py_XDECREF(dict);
172     return NULL;
173     }
174    
175     /* the write_record method. Write the record record given wither as a
176     * dictionary or a sequence (i.e. a list or a tuple).
177     *
178     * If it's a dictionary the keys must be the names of the fields and
179     * their value must have a suitable type. Only the fields actually
180     * contained in the dictionary are written. Fields for which there's no
181     * item in the dict are not modified.
182     *
183     * If it's a sequence, all fields must be present in the right order.
184     *
185     * In case of error, set a python exception and return NULL. Since that
186     * value will be returned to the python interpreter as is, the
187     * interpreter should recognize the exception.
188     *
189     * The method is implemented with two c-functions, write_field to write
190     * a single field and DBFInfo_write_record as the front-end.
191     */
192    
193    
194     /* write a single field of a record. */
195     static int
196     write_field(DBFHandle handle, int record, int field, int type,
197     PyObject * value)
198     {
199     char * string_value;
200     int int_value;
201     double double_value;
202    
203     if (value == Py_None)
204     {
205     if (!DBFWriteNULLAttribute(handle, record, field))
206     {
207     PyErr_Format(PyExc_IOError,
208     "can't write NULL field %d of record %d",
209     field, record);
210     return 0;
211     }
212     }
213     else
214     {
215     switch (type)
216     {
217     case FTString:
218     string_value = PyString_AsString(value);
219     if (!string_value)
220     return 0;
221     if (!DBFWriteStringAttribute(handle, record, field, string_value))
222     {
223     PyErr_Format(PyExc_IOError,
224     "can't write field %d of record %d",
225     field, record);
226     return 0;
227     }
228     break;
229    
230     case FTInteger:
231     int_value = PyInt_AsLong(value);
232     if (int_value == -1 && PyErr_Occurred())
233     return 0;
234     if (!DBFWriteIntegerAttribute(handle, record, field, int_value))
235     {
236     PyErr_Format(PyExc_IOError,
237     "can't write field %d of record %d",
238     field, record);
239     return 0;
240     }
241     break;
242    
243     case FTDouble:
244     double_value = PyFloat_AsDouble(value);
245     if (double_value == -1 && PyErr_Occurred())
246     return 0;
247     if (!DBFWriteDoubleAttribute(handle, record, field, double_value))
248     {
249     PyErr_Format(PyExc_IOError,
250     "can't write field %d of record %d",
251     field, record);
252     return 0;
253     }
254     break;
255    
256     default:
257     PyErr_Format(PyExc_TypeError, "Invalid field data type %d", type);
258     return 0;
259     }
260     }
261    
262     return 1;
263     }
264    
265     static
266     PyObject *
267     DBFInfo_write_record(DBFHandle handle, int record, PyObject *record_object)
268     {
269     int num_fields;
270     int i, length;
271     int type, width;
272     char name[12];
273     PyObject * value = NULL;
274    
275     num_fields = DBFGetFieldCount(handle);
276    
277     /* We used to use PyMapping_Check to test whether record_object is a
278     * dictionary like object instead of PySequence_Check to test
279     * whether it's a sequence. Unfortunately in Python 2.3
280     * PyMapping_Check returns true for lists and tuples too so the old
281     * approach doesn't work anymore.
282     */
283     if (PySequence_Check(record_object))
284     {
285     /* It's a sequence object. Iterate through all items in the
286     * sequence and write them to the appropriate field.
287     */
288     length = PySequence_Length(record_object);
289     if (length != num_fields)
290     {
291     PyErr_SetString(PyExc_TypeError,
292     "record must have one item for each field");
293     goto fail;
294     }
295     for (i = 0; i < length; i++)
296     {
297     type = DBFGetFieldInfo(handle, i, name, &width, NULL);
298     value = PySequence_GetItem(record_object, i);
299     if (value)
300     {
301     if (!write_field(handle, record, i, type, value))
302     goto fail;
303     Py_DECREF(value);
304     }
305     else
306     {
307     goto fail;
308     }
309     }
310     }
311     else
312     {
313     /* It's a dictionary-like object. Iterate over the names of the
314     * known fields and write the corresponding item
315     */
316     for (i = 0; i < num_fields; i++)
317     {
318     type = DBFGetFieldInfo(handle, i, name, &width, NULL);
319    
320     /* if the dictionary has the key name write that object to
321     * the appropriate field, other wise just clear the python
322     * exception and do nothing.
323     */
324     value = PyMapping_GetItemString(record_object, name);
325     if (value)
326     {
327     if (!write_field(handle, record, i, type, value))
328     goto fail;
329     Py_DECREF(value);
330     }
331     else
332     {
333     PyErr_Clear();
334     }
335     }
336     }
337    
338     Py_INCREF(Py_None);
339     return Py_None;
340    
341     fail:
342     Py_XDECREF(value);
343     return NULL;
344     }
345     %}
346    
347    
348     /*
349     * The SWIG Interface definition.
350     */
351    
352     /* include some common SWIG type definitions and standard exception
353     handling code */
354     %include typemaps.i
355     %include exception.i
356    
357     /* As for ShapeFile in shapelib.i, We define a new C-struct that holds
358     * the DBFHandle. This is mainly done so we can separate the close()
359     * method from the destructor but it also helps with exception handling.
360     *
361     * After the DBFFile has been opened or created the handle is not NULL.
362     * The close() method closes the file and sets handle to NULL as an
363     * indicator that the file has been closed.
364     */
365    
366     %{
367     typedef struct {
368     DBFHandle handle;
369     } DBFFile;
370     %}
371    
372    
373     /* The first argument to the DBFFile methods is a DBFFile pointer.
374     * We have to check whether handle is not NULL in most methods but not
375     * all. In the destructor and the close method, it's OK for handle to be
376     * NULL. We achieve this by checking whether the preprocessor macro
377     * NOCHECK_$name is defined. SWIG replaces $name with the name of the
378     * function for which the code is inserted. In the %{,%}-block below we
379     * define the macros for the destructor and the close() method.
380     */
381    
382     %typemap(python,check) DBFFile *{
383     %#ifndef NOCHECK_$name
384     if (!$target || !$target->handle)
385     SWIG_exception(SWIG_TypeError, "dbffile already closed");
386     %#endif
387     }
388    
389     %{
390     #define NOCHECK_delete_DBFFile
391     #define NOCHECK_DBFFile_close
392     %}
393    
394    
395     /* An exception handle for the constructor and the module level open()
396     * and create() functions.
397     *
398     * Annoyingly, we *have* to put braces around the SWIG_exception()
399     * calls, at least in the python case, because of the way the macro is
400     * written. Of course, always putting braces around the branches of an
401     * if-statement is often considered good practice.
402     */
403     %typemap(python,except) DBFFile * {
404     $function;
405     if (!$source)
406     {
407     SWIG_exception(SWIG_MemoryError, "no memory");
408     }
409     else if (!$source->handle)
410     {
411     SWIG_exception(SWIG_IOError, "$name failed");
412     }
413     }
414    
415 bh 1761 /* Exception handler for the add_field method */
416     %typemap(python,except) int DBFFile_add_field {
417     $function;
418     if ($source < 0)
419     {
420     SWIG_exception(SWIG_RuntimeError, "add_field failed");
421     }
422     }
423 jan 1611
424     /* define and use some typemaps for the field_info() method whose
425     * C-implementation has three output parameters that are returned
426     * through pointers passed into the function. SWIG already has
427     * definitions for common types such as int* and we can use those for
428     * the last two parameters:
429     */
430    
431     %apply int * OUTPUT { int * output_width }
432     %apply int * OUTPUT { int * output_decimals }
433    
434     /* the fieldname has to be defined manually: */
435     %typemap(python,ignore) char *fieldname_out(char temp[12]) {
436     $target = temp;
437     }
438    
439     %typemap(python,argout) char *fieldname_out() {
440     PyObject * string = PyString_FromString($source);
441     $target = t_output_helper($target,string);
442     }
443    
444    
445    
446     /*
447     * The SWIG-version of the DBFFile struct
448     */
449    
450     typedef struct
451     {
452     %addmethods {
453     DBFFile(const char *file, const char * mode = "rb") {
454     DBFFile * self = malloc(sizeof(DBFFile));
455     if (self)
456     self->handle = DBFOpen(file, mode);
457     return self;
458     }
459    
460     ~DBFFile() {
461     if (self->handle)
462     DBFClose(self->handle);
463     free(self);
464     }
465    
466     void close() {
467     if (self->handle)
468     DBFClose(self->handle);
469     self->handle = NULL;
470     }
471    
472     int field_count() {
473     return DBFGetFieldCount(self->handle);
474     }
475    
476     int record_count() {
477     return DBFGetRecordCount(self->handle);
478     }
479    
480     int field_info(int iField, char * fieldname_out,
481     int * output_width, int * output_decimals) {
482     return DBFGetFieldInfo(self->handle, iField, fieldname_out,
483     output_width, output_decimals);
484     }
485    
486     PyObject * read_record(int record) {
487     return DBFInfo_read_record(self->handle, record);
488     }
489    
490 bh 1917 PyObject * read_attribute(int record, int field) {
491     return DBFInfo_read_attribute(self->handle, record, field);
492     }
493    
494 jan 1611 int add_field(const char * pszFieldName, DBFFieldType eType,
495     int nWidth, int nDecimals) {
496     return DBFAddField(self->handle, pszFieldName, eType, nWidth,
497     nDecimals);
498     }
499    
500     PyObject *write_record(int record, PyObject *dict_or_sequence) {
501     return DBFInfo_write_record(self->handle, record,
502     dict_or_sequence);
503     }
504    
505     int commit() {
506     return DBFCommit(self->handle);
507     }
508    
509     }
510     } DBFFile;
511    
512    
513     /*
514     * Two module level functions, open() and create() that correspond to
515     * DBFOpen and DBFCreate respectively. open() is equivalent to the
516     * DBFFile constructor.
517     */
518    
519    
520     %{
521     DBFFile * open_DBFFile(const char * file, const char * mode)
522     {
523     DBFFile * self = malloc(sizeof(DBFFile));
524     if (self)
525     self->handle = DBFOpen(file, mode);
526     return self;
527     }
528     %}
529    
530     %name(open) %new DBFFile * open_DBFFile(const char * file,
531     const char * mode = "rb");
532    
533     %{
534     DBFFile * create_DBFFile(const char * file)
535     {
536     DBFFile * self = malloc(sizeof(DBFFile));
537     if (self)
538     self->handle = DBFCreate(file);
539     return self;
540     }
541     %}
542     %name(create) %new DBFFile * create_DBFFile(const char * file);
543    
544    
545    
546     /* constant definitions copied from shapefil.h */
547     typedef enum {
548     FTString,
549     FTInteger,
550     FTDouble,
551     FTInvalid
552     } DBFFieldType;

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26