1 |
/* 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 |
|
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 |
/* 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 |
value = do_read_attribute(handle, record, i, name); |
161 |
if (!value) |
162 |
goto fail; |
163 |
|
164 |
PyDict_SetItemString(dict, name, value); |
165 |
Py_DECREF(value); |
166 |
} |
167 |
|
168 |
return dict; |
169 |
|
170 |
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 |
/* The commit method implementation |
349 |
* |
350 |
* The method relies on the DBFUpdateHeader method which is not |
351 |
* available in shapelib <= 1.2.10. setup.py defines |
352 |
* HAVE_UPDATE_HEADER's value depending on whether the function is |
353 |
* available in the shapelib version the code is compiled with. |
354 |
*/ |
355 |
%{ |
356 |
static |
357 |
void |
358 |
DBFInfo_commit(DBFHandle handle) |
359 |
{ |
360 |
#if HAVE_UPDATE_HEADER |
361 |
DBFUpdateHeader(handle); |
362 |
#endif |
363 |
} |
364 |
%} |
365 |
|
366 |
|
367 |
/* |
368 |
* The SWIG Interface definition. |
369 |
*/ |
370 |
|
371 |
/* include some common SWIG type definitions and standard exception |
372 |
handling code */ |
373 |
%include typemaps.i |
374 |
%include exception.i |
375 |
|
376 |
/* As for ShapeFile in shapelib.i, We define a new C-struct that holds |
377 |
* the DBFHandle. This is mainly done so we can separate the close() |
378 |
* method from the destructor but it also helps with exception handling. |
379 |
* |
380 |
* After the DBFFile has been opened or created the handle is not NULL. |
381 |
* The close() method closes the file and sets handle to NULL as an |
382 |
* indicator that the file has been closed. |
383 |
*/ |
384 |
|
385 |
%{ |
386 |
typedef struct { |
387 |
DBFHandle handle; |
388 |
} DBFFile; |
389 |
%} |
390 |
|
391 |
|
392 |
/* The first argument to the DBFFile methods is a DBFFile pointer. |
393 |
* We have to check whether handle is not NULL in most methods but not |
394 |
* all. In the destructor and the close method, it's OK for handle to be |
395 |
* NULL. We achieve this by checking whether the preprocessor macro |
396 |
* NOCHECK_$name is defined. SWIG replaces $name with the name of the |
397 |
* function for which the code is inserted. In the %{,%}-block below we |
398 |
* define the macros for the destructor and the close() method. |
399 |
*/ |
400 |
|
401 |
%typemap(python,check) DBFFile *{ |
402 |
%#ifndef NOCHECK_$name |
403 |
if (!$target || !$target->handle) |
404 |
SWIG_exception(SWIG_TypeError, "dbffile already closed"); |
405 |
%#endif |
406 |
} |
407 |
|
408 |
%{ |
409 |
#define NOCHECK_delete_DBFFile |
410 |
#define NOCHECK_DBFFile_close |
411 |
%} |
412 |
|
413 |
|
414 |
/* An exception handle for the constructor and the module level open() |
415 |
* and create() functions. |
416 |
* |
417 |
* Annoyingly, we *have* to put braces around the SWIG_exception() |
418 |
* calls, at least in the python case, because of the way the macro is |
419 |
* written. Of course, always putting braces around the branches of an |
420 |
* if-statement is often considered good practice. |
421 |
*/ |
422 |
%typemap(python,except) DBFFile * { |
423 |
$function; |
424 |
if (!$source) |
425 |
{ |
426 |
SWIG_exception(SWIG_MemoryError, "no memory"); |
427 |
} |
428 |
else if (!$source->handle) |
429 |
{ |
430 |
SWIG_exception(SWIG_IOError, "$name failed"); |
431 |
} |
432 |
} |
433 |
|
434 |
/* Exception handler for the add_field method */ |
435 |
%typemap(python,except) int DBFFile_add_field { |
436 |
$function; |
437 |
if ($source < 0) |
438 |
{ |
439 |
SWIG_exception(SWIG_RuntimeError, "add_field failed"); |
440 |
} |
441 |
} |
442 |
|
443 |
/* define and use some typemaps for the field_info() method whose |
444 |
* C-implementation has three output parameters that are returned |
445 |
* through pointers passed into the function. SWIG already has |
446 |
* definitions for common types such as int* and we can use those for |
447 |
* the last two parameters: |
448 |
*/ |
449 |
|
450 |
%apply int * OUTPUT { int * output_width } |
451 |
%apply int * OUTPUT { int * output_decimals } |
452 |
|
453 |
/* the fieldname has to be defined manually: */ |
454 |
%typemap(python,ignore) char *fieldname_out(char temp[12]) { |
455 |
$target = temp; |
456 |
} |
457 |
|
458 |
%typemap(python,argout) char *fieldname_out() { |
459 |
PyObject * string = PyString_FromString($source); |
460 |
$target = t_output_helper($target,string); |
461 |
} |
462 |
|
463 |
|
464 |
|
465 |
/* |
466 |
* The SWIG-version of the DBFFile struct |
467 |
*/ |
468 |
|
469 |
typedef struct |
470 |
{ |
471 |
%addmethods { |
472 |
DBFFile(const char *file, const char * mode = "rb") { |
473 |
DBFFile * self = malloc(sizeof(DBFFile)); |
474 |
if (self) |
475 |
self->handle = DBFOpen(file, mode); |
476 |
return self; |
477 |
} |
478 |
|
479 |
~DBFFile() { |
480 |
if (self->handle) |
481 |
DBFClose(self->handle); |
482 |
free(self); |
483 |
} |
484 |
|
485 |
void close() { |
486 |
if (self->handle) |
487 |
DBFClose(self->handle); |
488 |
self->handle = NULL; |
489 |
} |
490 |
|
491 |
int field_count() { |
492 |
return DBFGetFieldCount(self->handle); |
493 |
} |
494 |
|
495 |
int record_count() { |
496 |
return DBFGetRecordCount(self->handle); |
497 |
} |
498 |
|
499 |
int field_info(int iField, char * fieldname_out, |
500 |
int * output_width, int * output_decimals) { |
501 |
return DBFGetFieldInfo(self->handle, iField, fieldname_out, |
502 |
output_width, output_decimals); |
503 |
} |
504 |
|
505 |
PyObject * read_record(int record) { |
506 |
return DBFInfo_read_record(self->handle, record); |
507 |
} |
508 |
|
509 |
PyObject * read_attribute(int record, int field) { |
510 |
return DBFInfo_read_attribute(self->handle, record, field); |
511 |
} |
512 |
|
513 |
int add_field(const char * pszFieldName, DBFFieldType eType, |
514 |
int nWidth, int nDecimals) { |
515 |
return DBFAddField(self->handle, pszFieldName, eType, nWidth, |
516 |
nDecimals); |
517 |
} |
518 |
|
519 |
PyObject *write_record(int record, PyObject *dict_or_sequence) { |
520 |
return DBFInfo_write_record(self->handle, record, |
521 |
dict_or_sequence); |
522 |
} |
523 |
|
524 |
void commit() { |
525 |
DBFInfo_commit(self->handle); |
526 |
} |
527 |
/* Delete the commit method from the class if it doesn't have a |
528 |
* real implementation. |
529 |
*/ |
530 |
%pragma(python) addtomethod="__class__:if not dbflibc._have_commit: del commit" |
531 |
|
532 |
/* The __del__ method generated by the old SWIG version we're |
533 |
* tries to access self.thisown which may not be set at all when |
534 |
* there was an exception during construction. Therefore we |
535 |
* override it with our own version. |
536 |
* FIXME: It would be better to upgrade to a newer SWIG version |
537 |
* or to get rid of SWIG entirely. |
538 |
*/ |
539 |
%pragma(python) addtoclass = " |
540 |
def __del__(self,dbflibc=dbflibc): |
541 |
if getattr(self, 'thisown', 0): |
542 |
dbflibc.delete_DBFFile(self) |
543 |
" |
544 |
|
545 |
|
546 |
} |
547 |
} DBFFile; |
548 |
|
549 |
|
550 |
/* |
551 |
* Two module level functions, open() and create() that correspond to |
552 |
* DBFOpen and DBFCreate respectively. open() is equivalent to the |
553 |
* DBFFile constructor. |
554 |
*/ |
555 |
|
556 |
|
557 |
%{ |
558 |
DBFFile * open_DBFFile(const char * file, const char * mode) |
559 |
{ |
560 |
DBFFile * self = malloc(sizeof(DBFFile)); |
561 |
if (self) |
562 |
self->handle = DBFOpen(file, mode); |
563 |
return self; |
564 |
} |
565 |
%} |
566 |
|
567 |
%name(open) %new DBFFile * open_DBFFile(const char * file, |
568 |
const char * mode = "rb"); |
569 |
|
570 |
%{ |
571 |
DBFFile * create_DBFFile(const char * file) |
572 |
{ |
573 |
DBFFile * self = malloc(sizeof(DBFFile)); |
574 |
if (self) |
575 |
self->handle = DBFCreate(file); |
576 |
return self; |
577 |
} |
578 |
%} |
579 |
%name(create) %new DBFFile * create_DBFFile(const char * file); |
580 |
|
581 |
|
582 |
|
583 |
/* constant definitions copied from shapefil.h */ |
584 |
typedef enum { |
585 |
FTString, |
586 |
FTInteger, |
587 |
FTDouble, |
588 |
FTInvalid |
589 |
} DBFFieldType; |
590 |
|
591 |
|
592 |
/* Put the value of the HAVE_UPDATE_HEADER preprocessor macro into the |
593 |
* wrapper so that the __class__ pragma above knows when to remove the |
594 |
* commit method |
595 |
*/ |
596 |
const int _have_commit = HAVE_UPDATE_HEADER; |
597 |
|