/[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 1611 - (hide annotations)
Tue Aug 19 21:24:20 2003 UTC (21 years, 6 months ago) by jan
Original Path: trunk/thuban/libraries/pyshapelib/dbflib.i
File size: 12020 byte(s)
These files have been moved here from thuban/extensions/pyshapelib/
See there in the Attic for the older history.

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

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26