/[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 2754 - (hide annotations)
Wed Apr 11 19:04:12 2007 UTC (17 years, 10 months ago) by bramz
File MIME type: text/plain
File size: 24938 byte(s)
Bug fix: in dbffile_add_field, the exception must be cleared if the first PyArg_ParseTuple fails.
1 bramz 2752 /* Copyright (c) 2001, 2002, 2007 by Intevation GmbH
2     * Authors:
3     * Bram de Greve <[email protected]>
4     * Bernhard Herzog <[email protected]>
5     *
6     * This program is free software under the GPL (>=v2)
7     * Read the file COPYING coming with Thuban for details.
8     */
9    
10 bramz 2742 #include "pyshapelib_common.h"
11 jan 1611
12 bramz 2752 /* UNICODE & LANGUAGE DRIVER SUPPORT FOR DBFLIB
13     *
14     * When writing Unicode objects to a dbflib database, the unicode has to be
15     * encoded in 8-bit characters using a code page. This code page is indentified
16     * by the Language Driver ID (LDID) field in the database header.
17     *
18     * At this moment, this need unofficial modifications of the maptools shapelib
19     * library because they do not read the LDID. No patch has been submitted yet,
20     * but the version contained in the Thuban source tree incorporates the required
21     * modifications.
22     *
23     * pyshapelib is designed to compile with either the patched or unpatched shapelib
24     * by defining HAVE_LANGUAGE_DRIVER as true or false respectively. In the latter
25     * case, a Windows ANSI code page (cp1252) is assumed
26     */
27     #if HAVE_LANGUAGE_DRIVER
28    
29     #define PYSHAPELIB_NUM_LANGUAGE_DRIVERS 256
30    
31     #define PYSHAPELIB_ADD_LANGUAGE_DRIVER(ldid, codec, name)\
32     codecs[ldid] = codec;\
33     drivers[ldid] = "LDID_" name;\
34     PyModule_AddIntConstant(module, "LDID_" name, ldid)
35    
36     static char* codecs[PYSHAPELIB_NUM_LANGUAGE_DRIVERS];
37     static char* drivers[PYSHAPELIB_NUM_LANGUAGE_DRIVERS];
38    
39     #endif
40    
41    
42    
43     /** Determine name of Python's built-in codec
44     */
45     static char* get_codec(DBFHandle handle)
46     {
47     #if HAVE_LANGUAGE_DRIVER
48     if (!codecs[handle->nLanguageDriver])
49     {
50     PyErr_Format(PyExc_ValueError, "Language Driver ID %d not recognized", handle->nLanguageDriver);
51     }
52     return codecs[handle->nLanguageDriver];
53     #else
54     return "cp1252";
55     #endif
56     }
57    
58    
59    
60     /** decode to unicode object
61     */
62     static PyObject* decode_string(DBFHandle handle, const char* string)
63     {
64     char* codec = get_codec(handle);
65     if (!codec) return NULL;
66     return PyUnicode_Decode(string, strlen(string), codec, NULL);
67     }
68    
69     /** encode unicode object to normal Python string object
70     */
71     static PyObject* encode_string(DBFHandle handle, PyObject* string)
72     {
73     char* codec = get_codec(handle);
74     if (!codec) return NULL;
75    
76     if (PyString_Check(string))
77     {
78     return PyString_AsEncodedObject(string, codec, NULL);
79     }
80     if (PyUnicode_Check(string))
81     {
82     return PyUnicode_AsEncodedString(string, codec, NULL);
83     }
84    
85     PyErr_SetString(PyExc_TypeError, "value is neither a string or unicode object");
86     return NULL;
87     }
88    
89    
90    
91 bramz 2742 /* --- DBFFile ------------------------------------------------------------------------------------------------------- */
92 jan 1611
93 bramz 2742 typedef struct {
94     PyObject_HEAD
95     DBFHandle handle;
96     } DBFFileObject;
97 jan 1611
98    
99 bh 1917
100 bramz 2742 /* allocator
101     */
102     static PyObject* dbffile_new(PyTypeObject* type, PyObject* args, PyObject* kwds)
103 bh 1917 {
104 bramz 2742 DBFFileObject* self;
105     self = (DBFFileObject*) type->tp_alloc(type, 0);
106     self->handle = NULL;
107     return (PyObject*) self;
108     }
109 bh 1917
110 bramz 2742
111    
112     /* deallocator
113     */
114     static void dbffile_dealloc(DBFFileObject* self)
115     {
116     DBFClose(self->handle);
117     self->handle = NULL;
118     self->ob_type->tp_free((PyObject*)self);
119     }
120    
121    
122    
123     /* constructor
124     */
125     static int dbffile_init(DBFFileObject* self, PyObject* args, PyObject* kwds)
126     {
127 bramz 2751 char* file = NULL;
128 bramz 2742 char* mode = "rb";
129 bramz 2745 static char *kwlist[] = {"name", "mode", NULL};
130 bramz 2751
131     DBFClose(self->handle);
132     self->handle = NULL;
133    
134     #if defined(SHPAPI_HAS_WIDE) && defined(Py_WIN_WIDE_FILENAMES)
135     if (GetVersion() < 0x80000000) { /* On NT, so wide API available */
136     PyObject *wfile;
137     if (PyArg_ParseTupleAndKeywords(args, kwds, "U|s:DBFFile", kwlist, &wfile, &mode))
138     {
139     PyObject *wmode = PyUnicode_DecodeASCII(mode, strlen(mode), NULL);
140     if (!wmode) return -1;
141     self->handle = DBFOpenW(PyUnicode_AS_UNICODE(wfile), PyUnicode_AS_UNICODE(wmode));
142     Py_DECREF(wmode);
143     if (!self->handle)
144     {
145     PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, wfile);
146     return -1;
147     }
148     }
149     else
150     {
151     /* Drop the argument parsing error as narrow
152     strings are also valid. */
153     PyErr_Clear();
154     }
155     }
156     #endif
157    
158 bramz 2749 if (!self->handle)
159     {
160 bramz 2751 if (!PyArg_ParseTupleAndKeywords(args, kwds, "et|s:DBFFile", kwlist,
161     Py_FileSystemDefaultEncoding, &file, &mode)) return -1;
162     self->handle = DBFOpen(file, mode);
163    
164     if (!self->handle)
165     {
166     PyErr_SetFromErrnoWithFilename(PyExc_IOError, file);
167     PyMem_Free(file);
168     return -1;
169     }
170    
171     PyMem_Free(file);
172 bramz 2749 }
173    
174 bramz 2751 return 0;
175 bramz 2742 }
176 bh 1917
177    
178    
179 bramz 2742 static PyObject* dbffile_close(DBFFileObject* self)
180 bh 1917 {
181 bramz 2742 DBFClose(self->handle);
182     self->handle = NULL;
183     Py_RETURN_NONE;
184     }
185 bh 1917
186    
187 bramz 2742
188     static PyObject* dbffile_field_count(DBFFileObject* self)
189     {
190     return PyInt_FromLong((long)DBFGetFieldCount(self->handle));
191 bh 1917 }
192    
193 jan 1611
194 bramz 2742
195     static PyObject* dbffile_record_count(DBFFileObject* self)
196 jan 1611 {
197 bramz 2742 return PyInt_FromLong((long)DBFGetRecordCount(self->handle));
198     }
199 jan 1611
200    
201 bramz 2742
202     static PyObject* dbffile_field_info(DBFFileObject* self, PyObject* args)
203     {
204     char field_name[12];
205     int field, width = 0, decimals = 0, field_type;
206 bramz 2753 PyObject* name_object = NULL;
207 jan 1611
208 bramz 2744 if (!PyArg_ParseTuple(args, "i:field_info", &field)) return NULL;
209 bramz 2742
210     field_name[0] = '\0';
211     field_type = DBFGetFieldInfo(self->handle, field, field_name, &width, &decimals);
212 bramz 2753 name_object = decode_string(self->handle, field_name);
213 bramz 2742
214 bramz 2753 return Py_BuildValue("iOii", field_type, name_object, width, decimals);
215 bramz 2742 }
216 bh 1917
217 jan 1611
218 bh 1917
219 bramz 2742 static PyObject* dbffile_add_field(DBFFileObject* self, PyObject* args)
220     {
221 bramz 2753 PyObject *oname = NULL, *name = NULL;
222 bramz 2742 int type, width, decimals;
223     int field;
224    
225 bramz 2754 if (!PyArg_ParseTuple(args, "Uiii:add_field", &oname, &type, &width, &decimals))
226     {
227     PyErr_Clear();
228     if (!PyArg_ParseTuple(args, "Siii:add_field", &oname, &type, &width, &decimals)) return NULL;
229     }
230 bramz 2742
231 bramz 2753 name = encode_string(self->handle, oname);
232     if (!name) return NULL;
233    
234     field = DBFAddField(self->handle, PyString_AsString(name), (DBFFieldType)type, width, decimals);
235     Py_DECREF(name);
236 bramz 2742
237     if (field < 0)
238     {
239     PyErr_SetString(PyExc_ValueError, "Failed to add field due to inappropriate field definition");
240     return NULL;
241     }
242     return PyInt_FromLong((long)field);
243 jan 1611 }
244    
245    
246    
247 bramz 2742 /* Read one attribute from the dbf handle and return it as a new python object
248     *
249     * If an error occurs, set the appropriate Python exception and return
250     * NULL.
251     *
252     * Assume that the values of the record and field arguments are valid.
253     * The name argument will be passed to DBFGetFieldInfo as is and should
254     * thus be either NULL or a pointer to an array of at least 12 chars
255     */
256     static PyObject* do_read_attribute(DBFHandle handle, int record, int field, char * name)
257 jan 1611 {
258 bramz 2742 int type, width;
259 bramz 2752 const char* string;
260 bramz 2742 type = DBFGetFieldInfo(handle, field, name, &width, NULL);
261    
262     /* For strings NULL and the empty string are indistinguishable
263     * in DBF files. We prefer empty strings instead for backwards
264     * compatibility reasons because older wrapper versions returned
265     * emtpy strings as empty strings.
266     */
267     if (type != FTString && DBFIsAttributeNULL(handle, record, field))
268 jan 1611 {
269 bramz 2742 Py_RETURN_NONE;
270 jan 1611 }
271 bramz 2742 else
272 jan 1611 {
273 bramz 2742 switch (type)
274     {
275     case FTString:
276 bramz 2752 string = DBFReadStringAttribute(handle, record, field);
277     if (string) return decode_string(handle, string);
278 jan 1611
279 bramz 2742 case FTInteger:
280     return PyInt_FromLong((long)DBFReadIntegerAttribute(handle, record, field));
281 jan 1611
282 bramz 2742 case FTDouble:
283     return PyFloat_FromDouble(DBFReadDoubleAttribute(handle, record, field));
284 bramz 2745
285     case FTLogical:
286 bramz 2752 string = DBFReadLogicalAttribute(handle, record, field);
287     if (string)
288 bramz 2745 {
289 bramz 2752 switch (string[0])
290 bramz 2745 {
291     case 'F':
292     case 'N':
293     Py_RETURN_FALSE;
294     case 'T':
295     case 'Y':
296     Py_RETURN_TRUE;
297     }
298     }
299     break;
300 jan 1611
301 bramz 2742 default:
302     PyErr_Format(PyExc_TypeError, "Invalid field data type %d", type);
303     return NULL;
304     }
305 jan 1611 }
306 bramz 2745
307     PyErr_Format(PyExc_IOError, "Can't read value for row %d column %d", record, field);
308     return NULL;
309 bramz 2742 }
310 jan 1611
311    
312 bramz 2742
313     /* the read_attribute method. Return the value of the given record and
314     * field as a python object of the appropriate type.
315     */
316     static PyObject* dbffile_read_attribute(DBFFileObject* self, PyObject* args)
317 jan 1611 {
318 bramz 2742 int record, field;
319 jan 1611
320 bramz 2744 if (!PyArg_ParseTuple(args, "ii:read_field", &record, &field)) return NULL;
321 bramz 2742
322     if (record < 0 || record >= DBFGetRecordCount(self->handle))
323     {
324     PyErr_Format(PyExc_ValueError,
325     "record index %d out of bounds (record count: %d)",
326     record, DBFGetRecordCount(self->handle));
327     return NULL;
328     }
329 jan 1611
330 bramz 2742 if (field < 0 || field >= DBFGetFieldCount(self->handle))
331 jan 1611 {
332 bramz 2742 PyErr_Format(PyExc_ValueError,
333     "field index %d out of bounds (field count: %d)",
334     field, DBFGetFieldCount(self->handle));
335     return NULL;
336 jan 1611 }
337 bramz 2742
338     return do_read_attribute(self->handle, record, field, NULL);
339     }
340    
341    
342    
343     /* the read_record method. Return the record record as a dictionary with
344     * whose keys are the names of the fields, and their values as the
345     * appropriate Python type.
346     */
347     static PyObject* dbffile_read_record(DBFFileObject* self, PyObject* args)
348     {
349     int record;
350     int num_fields;
351     int i;
352     char name[12];
353     PyObject *dict;
354     PyObject *value = NULL;
355    
356 bramz 2744 if (!PyArg_ParseTuple(args, "i:read_record", &record)) return NULL;
357 bramz 2742
358     if (record < 0 || record >= DBFGetRecordCount(self->handle))
359 jan 1611 {
360 bramz 2742 PyErr_Format(PyExc_ValueError,
361     "record index %d out of bounds (record count: %d)",
362     record, DBFGetRecordCount(self->handle));
363     return NULL;
364 jan 1611 }
365 bramz 2742
366     dict = PyDict_New();
367     if (!dict) return NULL;
368    
369     num_fields = DBFGetFieldCount(self->handle);
370 jan 1611 for (i = 0; i < num_fields; i++)
371     {
372 bramz 2742 value = do_read_attribute(self->handle, record, i, name);
373     if (!value || PyDict_SetItemString(dict, name, value) < 0) goto fail;
374 jan 1611 Py_DECREF(value);
375 bramz 2742 value = NULL;
376 jan 1611 }
377    
378 bramz 2742 return dict;
379 jan 1611
380 bramz 2742 fail:
381     Py_XDECREF(value);
382     Py_DECREF(dict);
383     return NULL;
384 jan 1611 }
385    
386    
387 bramz 2742
388     /* write a single field of a record. */
389 bramz 2753 static int do_write_attribute(DBFHandle handle, int record, int field, int type, PyObject* value)
390 bh 2212 {
391 bramz 2753 PyObject* string_value = NULL;
392 bramz 2742 int int_value;
393     double double_value;
394 bramz 2745 int logical_value;
395 bh 2212
396 bramz 2742 if (value == Py_None)
397     {
398 bramz 2745 if (DBFWriteNULLAttribute(handle, record, field)) return 1;
399 bramz 2742 }
400     else
401     {
402     switch (type)
403     {
404     case FTString:
405 bramz 2753 string_value = encode_string(handle, value);
406     if (!string_value) return 0;
407     if (DBFWriteStringAttribute(handle, record, field, PyString_AsString(string_value)))
408 bramz 2752 {
409 bramz 2753 Py_DECREF(string_value);
410 bramz 2752 return 1;
411     }
412 bramz 2753 Py_DECREF(string_value);
413 bramz 2742 break;
414 bh 2212
415 bramz 2742 case FTInteger:
416     int_value = PyInt_AsLong(value);
417     if (int_value == -1 && PyErr_Occurred()) return 0;
418 bramz 2745 if (DBFWriteIntegerAttribute(handle, record, field, int_value)) return 1;
419 bramz 2742 break;
420 jan 1611
421 bramz 2742 case FTDouble:
422     double_value = PyFloat_AsDouble(value);
423     if (double_value == -1 && PyErr_Occurred()) return 0;
424 bramz 2745 if (DBFWriteDoubleAttribute(handle, record, field, double_value)) return 1;
425 bramz 2742 break;
426 bramz 2745
427     case FTLogical:
428     logical_value = PyObject_IsTrue(value);
429     if (logical_value == -1) return 0;
430     if (DBFWriteLogicalAttribute(handle, record, field, logical_value ? 'T' : 'F')) return 1;
431     break;
432 jan 1611
433 bramz 2742 default:
434     PyErr_Format(PyExc_TypeError, "Invalid field data type %d", type);
435     return 0;
436     }
437     }
438 jan 1611
439 bramz 2745 PyErr_Format(PyExc_IOError, "can't write field %d of record %d", field, record);
440     return 0;
441 bramz 2742 }
442 jan 1611
443    
444    
445 bramz 2753 static PyObject* dbffile_write_attribute(DBFFileObject* self, PyObject* args)
446 bramz 2742 {
447     int record, field;
448     PyObject* value;
449     int type;
450    
451 bramz 2753 if (!PyArg_ParseTuple(args, "iiO:write_attribute", &record, &field, &value)) return NULL;
452 bramz 2742
453     if (field < 0 || field >= DBFGetFieldCount(self->handle))
454     {
455     PyErr_Format(PyExc_ValueError,
456     "field index %d out of bounds (field count: %d)",
457     field, DBFGetFieldCount(self->handle));
458     return NULL;
459     }
460    
461     type = DBFGetFieldInfo(self->handle, field, NULL, NULL, NULL);
462 bramz 2753 if (!do_write_attribute(self->handle, record, field, type, value)) return NULL;
463 bramz 2742 Py_RETURN_NONE;
464 jan 1611 }
465    
466    
467    
468 bramz 2742 static PyObject* dbffile_write_record(DBFFileObject* self, PyObject* args)
469     {
470     int record;
471     PyObject* record_object;
472     int i, num_fields;
473    
474     int type;
475     char name[12];
476     PyObject* value = NULL;
477    
478 bramz 2744 if (!PyArg_ParseTuple(args, "iO:write_record", &record, &record_object)) return NULL;
479 bramz 2742
480     num_fields = DBFGetFieldCount(self->handle);
481    
482     /* mimic ShapeFile functionality where id = -1 means appending */
483     if (record == -1)
484     {
485     record = num_fields;
486     }
487 jan 1611
488 bramz 2742 if (PySequence_Check(record_object))
489     {
490     /* It's a sequence object. Iterate through all items in the
491     * sequence and write them to the appropriate field.
492     */
493     if (PySequence_Length(record_object) != num_fields)
494     {
495     PyErr_SetString(PyExc_TypeError, "record must have one item for each field");
496     return NULL;
497     }
498     for (i = 0; i < num_fields; ++i)
499     {
500     type = DBFGetFieldInfo(self->handle, i, NULL, NULL, NULL);
501     value = PySequence_GetItem(record_object, i);
502     if (!value) return NULL;
503 bramz 2753 if (!do_write_attribute(self->handle, record, i, type, value))
504 bramz 2742 {
505     Py_DECREF(value);
506     return NULL;
507     }
508     Py_DECREF(value);
509     }
510     }
511     else
512     {
513     /* It's a dictionary-like object. Iterate over the names of the
514     * known fields and write the corresponding item
515     */
516     for (i = 0; i < num_fields; ++i)
517     {
518     name[0] = '\0';
519     type = DBFGetFieldInfo(self->handle, i, name, NULL, NULL);
520     value = PyDict_GetItemString(record_object, name);
521 bramz 2753 if (value && !do_write_attribute(self->handle, record, i, type, value)) return NULL;
522 bramz 2742 }
523     }
524    
525     return PyInt_FromLong((long)record);
526 bh 1761 }
527 jan 1611
528    
529    
530 bramz 2742 static PyObject* dbffile_repr(DBFFileObject* self)
531     {
532     /* TODO: it would be nice to do something like "dbflib.DBFFile(filename, mode)" instead */
533     return PyString_FromFormat("<dbflib.DBFFile object at %p>", self->handle);
534 jan 1611 }
535    
536    
537    
538 bramz 2742 /* The commit method implementation
539     *
540     * The method relies on the DBFUpdateHeader method which is not
541     * available in shapelib <= 1.2.10. setup.py defines
542     * HAVE_UPDATE_HEADER's value depending on whether the function is
543     * available in the shapelib version the code is compiled with.
544     */
545     #if HAVE_UPDATE_HEADER
546     static PyObject* dbffile_commit(DBFFileObject* self)
547 jan 1611 {
548 bramz 2742 DBFUpdateHeader(self->handle);
549     Py_RETURN_NONE;
550     }
551     #endif
552 jan 1611
553    
554 bramz 2752 #if HAVE_LANGUAGE_DRIVER
555 jan 1611
556 bramz 2752 static PyObject* dbffile_language_driver(DBFFileObject* self, void* closure)
557     {
558     return PyInt_FromLong((long)self->handle->nLanguageDriver);
559     }
560    
561     #endif
562    
563    
564 bramz 2742 static struct PyMethodDef dbffile_methods[] =
565     {
566 bramz 2744 {"close", (PyCFunction)dbffile_close, METH_NOARGS,
567 bramz 2745 "close() -> None\n\n"
568     "closes DBFFile"},
569 bramz 2744 {"field_count", (PyCFunction)dbffile_field_count, METH_NOARGS,
570 bramz 2745 "field_count() -> integer\n\n"
571 bramz 2744 "returns number of fields currently defined"},
572     {"record_count", (PyCFunction)dbffile_record_count, METH_NOARGS,
573 bramz 2745 "record_count() -> integer\n\n"
574 bramz 2744 "returns number of records that currently exist"},
575     {"field_info", (PyCFunction)dbffile_field_info, METH_VARARGS,
576 bramz 2745 "field_info(field_index) -> (type, name, width, decimals)\n\n"
577     "returns info of a field as a tuple with:\n"
578     "- type: the type of the field corresponding to the integer value of one "
579     " of the constants FTString, FTInteger, ...\n"
580     "- name: the name of the field as a string\n"
581     "- width: the width of the field as a number of characters\n"
582     "- decimals: the number of decimal digits" },
583 bramz 2742 {"add_field", (PyCFunction)dbffile_add_field, METH_VARARGS,
584 bramz 2745 "add_field(type, name, width, decimals) -> field_index\n\n"
585 bramz 2742 "adds a new field and returns field index if successful\n"
586 bramz 2745 "- type: the type of the field corresponding to the integer value of one "
587     " of the constants FTString, FTInteger, ...\n"
588     "- name: the name of the field as a string\n"
589     "- width: the width of the field as a number of characters\n"
590     "- decimals: the number of decimal digits" },
591 bramz 2744 {"read_attribute", (PyCFunction)dbffile_read_attribute, METH_VARARGS,
592 bramz 2745 "read_attribute(record_index, field_index) -> value\n\n"
593     "returns the value of one field of a record"},
594 bramz 2744 {"read_record", (PyCFunction)dbffile_read_record, METH_VARARGS,
595 bramz 2745 "read_record(record_index) -> dict\n\n"
596     "returns an entire record as a dictionary of field names and values"},
597 bramz 2753 {"write_attribute", (PyCFunction)dbffile_write_attribute, METH_VARARGS,
598     "write_attribute(record_index, field_index, new_value)\n"
599 bramz 2745 "writes a single field of a record"},
600 bramz 2744 {"write_record", (PyCFunction)dbffile_write_record, METH_VARARGS,
601 bramz 2745 "write_record(record_index, record) -> record_index\n\n"
602     "Writes an entire record as a dict or a sequence, and return index of record\n"
603     "Record can either be a dictionary in which case the keys are used as field names, "
604 bramz 2744 "or a sequence that must have an item for every field (length = field_count())"},
605 bramz 2742 #if HAVE_UPDATE_HEADER
606 bramz 2750 {"commit", (PyCFunction)dbffile_commit, METH_NOARGS,
607 bramz 2745 "commit() -> None"},
608 bramz 2742 #endif
609     {NULL}
610     };
611 jan 1611
612    
613 bh 1917
614 bramz 2742 static struct PyGetSetDef dbffile_getsetters[] =
615     {
616 bramz 2752 #if HAVE_LANGUAGE_DRIVER
617     {"language_driver", (getter)dbffile_language_driver, NULL, "Language Driver ID (read-only)" },
618     #endif
619 bramz 2742 {NULL}
620     };
621 jan 1611
622    
623    
624 bramz 2742 static PyTypeObject DBFFileType = PYSHAPELIB_DEFINE_TYPE(DBFFileObject, dbffile, "shapelib.DBFFile", 0);
625 bh 2453
626    
627 jan 1611
628 bramz 2742 /* --- dbflib -------------------------------------------------------------------------------------------------------- */
629 jan 1611
630 bramz 2742 static PyObject* dbflib_open(PyObject* module, PyObject* args)
631     {
632     return PyObject_CallObject((PyObject*)&DBFFileType, args);
633     }
634 jan 1611
635    
636    
637 bramz 2742 static PyObject* dbflib_create(PyObject* module, PyObject* args)
638     {
639     char* file;
640     DBFFileObject* result;
641 bramz 2751 DBFHandle handle = NULL;
642     int wideargument = 0;
643    
644     #if defined(SHPAPI_HAS_WIDE) && defined(Py_WIN_WIDE_FILENAMES)
645     if (GetVersion() < 0x80000000) { /* On NT, so wide API available */
646     PyObject *wfile;
647     if (PyArg_ParseTuple(args, "U:create", &wfile))
648     {
649     wideargument = 1;
650     handle = DBFCreateW(PyUnicode_AS_UNICODE(wfile));
651     if (!handle)
652     {
653     PyErr_SetFromErrnoWithFilenameObject(PyExc_IOError, wfile);
654     return NULL;
655     }
656     }
657     else
658     {
659     /* Drop the argument parsing error as narrow
660     strings are also valid. */
661     PyErr_Clear();
662     }
663     }
664     #endif
665 bramz 2742
666 bramz 2751 if (!handle)
667     {
668     if (!PyArg_ParseTuple(args, "et:create", Py_FileSystemDefaultEncoding, &file)) return NULL;
669     handle = DBFCreate(file);
670     if (!handle)
671     {
672     PyErr_SetFromErrnoWithFilename(PyExc_IOError, file);
673     PyMem_Free(file);
674     return NULL;
675     }
676     PyMem_Free(file);
677     }
678    
679 bramz 2742 result = PyObject_New(DBFFileObject, &DBFFileType);
680     if (!result)
681     {
682 bramz 2751 DBFClose(handle);
683 bramz 2742 return PyErr_NoMemory();
684     }
685    
686 bramz 2751 result->handle = handle;
687 bramz 2742 return (PyObject*) result;
688     }
689 jan 1611
690    
691    
692 bramz 2752 #if HAVE_LANGUAGE_DRIVER
693    
694     /** translate a numeric Language Driver ID to the name of Python's codec.
695     */
696     static PyObject* dbflib_language_driver_codec(PyObject* module, PyObject* args)
697     {
698     int ldid;
699     if (!PyArg_ParseTuple(args, "i:language_driver_name", &ldid)) return NULL;
700     if (ldid < 0 || ldid >= PYSHAPELIB_NUM_LANGUAGE_DRIVERS || !codecs[ldid])
701     {
702     PyErr_SetString(PyExc_ValueError, "invalid driver id");
703     return NULL;
704     }
705     return PyString_FromString(codecs[ldid]);
706     }
707    
708     /** translate a numeric Language Driver ID to a string represting its constant.
709     */
710     static PyObject* dbflib_language_driver_name(PyObject* module, PyObject* args)
711     {
712     int ldid;
713     if (!PyArg_ParseTuple(args, "i:language_driver_name", &ldid)) return NULL;
714     if (ldid < 0 || ldid >= PYSHAPELIB_NUM_LANGUAGE_DRIVERS || !drivers[ldid])
715     {
716     PyErr_SetString(PyExc_ValueError, "invalid driver id");
717     return NULL;
718     }
719     return PyString_FromString(drivers[ldid]);
720     }
721    
722     #endif
723    
724    
725    
726 bramz 2742 static struct PyMethodDef dbflib_methods[] =
727     {
728 bramz 2744 {"open", (PyCFunction)dbflib_open, METH_VARARGS,
729 bramz 2745 "open(name [, mode]) -> DBFFile\n\n"
730     "opens a DBFFile" },
731 bramz 2744 {"create", (PyCFunction)dbflib_create, METH_VARARGS,
732 bramz 2752 "create(name [, language_driver]) -> DBFFile\n\n"
733     "create a DBFFile " },
734     #if HAVE_LANGUAGE_DRIVER
735     {"language_driver_codec", (PyCFunction)dbflib_language_driver_codec, METH_VARARGS,
736     "language_driver_codec(driver_id) -> string\n\n"
737     "translate language driver id into the name of the Python's codec used as code page." },
738     {"language_driver_name", (PyCFunction)dbflib_language_driver_name, METH_VARARGS,
739     "language_driver_name(driver_id) -> string\n\n"
740     "translate language driver id into a string." },
741     #endif
742 bramz 2742 {NULL}
743     };
744 jan 1611
745 bh 2212
746 bramz 2742 PyMODINIT_FUNC initdbflib(void)
747     {
748 bramz 2752 int i;
749    
750 bramz 2742 PyObject* module = Py_InitModule("dbflib", dbflib_methods);
751     if (!module) return;
752    
753     PYSHAPELIB_ADD_TYPE(DBFFileType, "DBFFile");
754    
755     PYSHAPELIB_ADD_CONSTANT(FTString);
756     PYSHAPELIB_ADD_CONSTANT(FTInteger);
757     PYSHAPELIB_ADD_CONSTANT(FTDouble);
758 bramz 2745 PYSHAPELIB_ADD_CONSTANT(FTLogical);
759 bramz 2742 PYSHAPELIB_ADD_CONSTANT(FTInvalid);
760     PyModule_AddIntConstant(module, "_have_commit", HAVE_UPDATE_HEADER);
761 bramz 2752
762     #if HAVE_LANGUAGE_DRIVER
763     /* table compiled from these resources:
764     * http://www.clicketyclick.dk/databases/xbase/format/dbf.html
765     * http://www.esrinl.com/content/file.asp?id=307
766     * http://msdn2.microsoft.com/en-us/library/aa975345(VS.71).aspx
767     */
768     for (i = 0; i < PYSHAPELIB_NUM_LANGUAGE_DRIVERS; ++i)
769     {
770     codecs[i] = NULL;
771     drivers[i] = NULL;
772     }
773     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x00, "cp1252", "NOT_SET");
774     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x01, "cp437", "DOS_USA");
775     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x02, "cp850", "DOS_INTERNATIONAL");
776     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x03, "cp1252", "WINDOWS_ANSI");
777     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x04, "mac_roman", "STANDARD_MACINTOSH");
778     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x08, "cp865", "DANISH_OEM");
779     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x09, "cp437", "DUTCH_OEM");
780     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x0a, "cp850", "DUTCH_OEM_2");
781     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x0b, "cp437", "FINNISH_OEM");
782     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x0d, "cp437", "FRENCH_OEM");
783     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x0e, "cp850", "FRENCH_OEM_2");
784     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x0f, "cp437", "GERMAN_OEM");
785     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x10, "cp850", "GERMAN_OEM_2");
786     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x11, "cp437", "ITALIAN_OEM");
787     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x12, "cp850", "ITALIAN_OEM_2");
788     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x13, "cp932", "JAPANESE_SHIFT_JIS");
789     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x14, "cp850", "SPANISH_OEM_2");
790     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x15, "cp437", "SWEDISH_OEM");
791     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x16, "cp850", "SWEDISH_OEM_2");
792     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x17, "cp865", "NORWEGIAN_OEM");
793     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x18, "cp437", "SPANISH_OEM");
794     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x19, "cp437", "ENGLISH_BRITAIN_OEM");
795     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x1a, "cp850", "ENGLISH_BRITAIN_OEM_2");
796     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x0b, "cp437", "ENGLISH_US_OEM");
797     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x1c, "cp863", "FRENCH_CANADA_OEM");
798     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x1d, "cp850", "FRENCH_OEM_2");
799     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x1f, "cp852", "CZECH_OEM");
800     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x22, "cp852", "HUNGARIAN_OEM");
801     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x23, "cp852", "POLISH_OEM");
802     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x24, "cp860", "PORTUGUESE_OEM");
803     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x25, "cp850", "PORTUGUESE_OEM_2");
804     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x26, "cp866", "RUSSIAN_OEM");
805     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x37, "cp850", "ENGLISH_US_OEM_2");
806     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x40, "cp852", "ROMANIAN_OEM");
807     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x4d, "cp936", "CHINESE_GBK_PRC");
808     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x4e, "cp949", "KOREAN_ANSI_OEM);");
809     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x4f, "cp950", "CHINESE_BIG5_TAIWAN");
810     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x50, "cp874", "THAI_ANSI_OEM");
811     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x57, "cp1252", "ESRI_ANSI");
812     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x58, "cp1252", "WESTERN_EUROPEAN_ANSI");
813     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x59, "cp1252", "SPANISH_ANSI");
814     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x64, "cp852", "EASTERN_EUROPEAN_MSDOS");
815     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x65, "cp866", "RUSSIAN_MSDOS");
816     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x66, "cp865", "NORDIC_MSDOS");
817     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x67, "cp861", "ICELANDIC_MSDOS");
818     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x68, "cp895", "CZECH_MSDOS");
819     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x69, "cp620", "POLISH_MSDOS");
820     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x6a, "cp737", "GREEK_MSDOS");
821     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x6b, "cp857", "TURKISH_MSDOS");
822     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x6c, "cp863", "FRENCH_CANADA_MSDOS");
823     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x78, "cp950", "TAIWAN_BIG5");
824     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x79, "cp949", "HANGUL_WANSUG");
825     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x7a, "cp936", "PRC_GBK");
826     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x7b, "cp932", "JAPANESE_SHIFT_JIS");
827     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x7c, "cp874", "THAI_WINDOWS_MSDOS");
828     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x7d, "cp1255", "HEBREW_WINDOWS");
829     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x7e, "cp1256", "ARABIC_WINDOWS");
830     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x86, "cp737", "GREEK_OEM");
831     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x87, "cp852", "SLOVENIAN_OEM");
832     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x88, "cp857", "TURKISH_OEM");
833     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x96, "mac_cyrillic", "RUSSIAN_MACINTOSH");
834     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x97, "mac_latin2", "EASTERN_EUROPEAN_MACINTOSH");
835     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x98, "mac_greek", "GREEK_MACINTOSH");
836     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0xc8, "cp1250", "EASTERN_EUROPEAN_WINDOWS");
837     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0xc9, "cp1251", "RUSSIAN_WINDOWS");
838     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0xca, "cp1254", "TURKISH_WINDOWS");
839     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0xcb, "cp1253", "GREEK_WINDOWS");
840     PYSHAPELIB_ADD_LANGUAGE_DRIVER(0xcc, "cp1257", "BALTIC_WINDOWS");
841     #endif
842    
843 bramz 2742 }

Properties

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

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26