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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1611 - (show 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 /* 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