[Thuban-commits] r2752 - in branches/WIP-pyshapelib-bramz/libraries: pyshapelib shapelib

scm-commit@wald.intevation.org scm-commit at wald.intevation.org
Wed Apr 11 01:45:01 CEST 2007


Author: bramz
Date: 2007-04-11 01:45:00 +0200 (Wed, 11 Apr 2007)
New Revision: 2752

Modified:
   branches/WIP-pyshapelib-bramz/libraries/pyshapelib/ChangeLog
   branches/WIP-pyshapelib-bramz/libraries/pyshapelib/dbflibmodule.c
   branches/WIP-pyshapelib-bramz/libraries/pyshapelib/pyshapelib_common.h
   branches/WIP-pyshapelib-bramz/libraries/pyshapelib/setup.py
   branches/WIP-pyshapelib-bramz/libraries/shapelib/dbfopen.c
   branches/WIP-pyshapelib-bramz/libraries/shapelib/shapefil.h
Log:
attempt to add support for Unicode and Language Driver ID (LDID) support in dbflib

Modified: branches/WIP-pyshapelib-bramz/libraries/pyshapelib/ChangeLog
===================================================================
--- branches/WIP-pyshapelib-bramz/libraries/pyshapelib/ChangeLog	2007-03-28 23:30:15 UTC (rev 2751)
+++ branches/WIP-pyshapelib-bramz/libraries/pyshapelib/ChangeLog	2007-04-10 23:45:00 UTC (rev 2752)
@@ -1,3 +1,30 @@
+2007-04-11	Bram de Greve <bram.degreve at intec.ugent.be>
+
+	* dbflibmodule.c, pyshapelib_common.h, setup.py: attempt to add support for
+	Unicode and Language Driver ID (LDID) support in dbflib.  Before the strings
+	are send to the underlying shapelib, they are encoded using the code page
+	specified by the database's LDID if present.  To know this LDID requires 
+	some unofficial modifications to maptools' shapelib.  Backwards 
+	compatibility is ensured by detecting if this field is present and setting 
+	HAVE_LANGUAGE_DRIVER accordingly in setup.py.  In absence of the LDID, 
+	dbflib assumes a Windows ANSI codepage (cp1252).  
+	New or modified functions/attributes of the DBFFile class:
+	- read_record(...), DBFFile.read_attribute(...): modified, now return 
+	  Unicode strings.
+	- write_record(...) and write_field(...): modified, now accept both regular
+	  and Unicode strings but both are encoded.
+	- language_driver (read-only): new, the numerical value of the LDID 
+	  (exists only if HAVE_LANGUAGE_DRIVER == 1)
+	New or modified functions/constants of the dbflib module:
+	- language_driver_codec(...): added, translates a numerical LDID into the 
+	  string name of the Python codec used to encode/decode the strings. 
+	  (exists only if HAVE_LANGUAGE_DRIVER == 1)
+	- language_driver_name(...): added, translates a numerical LDID into a string
+	  representing the corresponding constant. 
+	  (exists only if HAVE_LANGUAGE_DRIVER == 1)
+	- LDID_NOT_SET, LDID_DOS_USA, ...: constants representing language drivers.
+	  (existsonly if HAVE_LANGUAGE_DRIVER == 1)
+
 2007-03-29	Bram de Greve <bram.degreve at intec.ugent.be>
 
 	* shapelibmodule.c, dbflibmodule.c, pyshapelib_common.h: added support for

Modified: branches/WIP-pyshapelib-bramz/libraries/pyshapelib/dbflibmodule.c
===================================================================
--- branches/WIP-pyshapelib-bramz/libraries/pyshapelib/dbflibmodule.c	2007-03-28 23:30:15 UTC (rev 2751)
+++ branches/WIP-pyshapelib-bramz/libraries/pyshapelib/dbflibmodule.c	2007-04-10 23:45:00 UTC (rev 2752)
@@ -1,5 +1,93 @@
+/* Copyright (c) 2001, 2002, 2007 by Intevation GmbH
+ * Authors:
+ * Bram de Greve <bram.degreve at intec.ugent.be>
+ * Bernhard Herzog <bh at intevation.de>
+ *
+ * This program is free software under the GPL (>=v2)
+ * Read the file COPYING coming with Thuban for details.
+ */
+
 #include "pyshapelib_common.h"
 
+/* UNICODE & LANGUAGE DRIVER SUPPORT FOR DBFLIB
+ *
+ * When writing Unicode objects to a dbflib database, the unicode has to be
+ * encoded in 8-bit characters using a code page.  This code page is indentified
+ * by the Language Driver ID (LDID) field in the database header.
+ *
+ * At this moment, this need unofficial modifications of the maptools shapelib
+ * library because they do not read the LDID.  No patch has been submitted yet,
+ * but the version contained in the Thuban source tree incorporates the required
+ * modifications.
+ *
+ * pyshapelib is designed to compile with either the patched or unpatched shapelib
+ * by defining HAVE_LANGUAGE_DRIVER as true or false respectively.  In the latter 
+ * case, a Windows ANSI code page (cp1252) is assumed
+ */
+ #if HAVE_LANGUAGE_DRIVER
+
+#define PYSHAPELIB_NUM_LANGUAGE_DRIVERS 256
+
+#define PYSHAPELIB_ADD_LANGUAGE_DRIVER(ldid, codec, name)\
+	codecs[ldid] = codec;\
+	drivers[ldid] = "LDID_" name;\
+	PyModule_AddIntConstant(module, "LDID_" name, ldid)
+
+static char* codecs[PYSHAPELIB_NUM_LANGUAGE_DRIVERS];
+static char* drivers[PYSHAPELIB_NUM_LANGUAGE_DRIVERS];
+
+#endif
+
+
+
+/** Determine name of Python's built-in codec
+ */
+static char* get_codec(DBFHandle handle)
+{
+#if HAVE_LANGUAGE_DRIVER
+	if (!codecs[handle->nLanguageDriver])
+	{
+		PyErr_Format(PyExc_ValueError, "Language Driver ID %d not recognized", handle->nLanguageDriver);
+	}
+	return codecs[handle->nLanguageDriver];
+#else
+	return "cp1252";
+#endif
+}
+
+
+
+/** decode to unicode object 
+ */
+static PyObject* decode_string(DBFHandle handle, const char* string)
+{
+	char* codec = get_codec(handle);
+	if (!codec) return NULL;
+	return PyUnicode_Decode(string, strlen(string), codec, NULL);
+}
+
+/** encode unicode object to normal Python string object 
+ */
+static PyObject* encode_string(DBFHandle handle, PyObject* string)
+{
+	char* codec = get_codec(handle);
+	if (!codec) return NULL;
+
+	if (PyString_Check(string))
+	{
+		return PyString_AsEncodedObject(string, codec, NULL);
+	}
+	if (PyUnicode_Check(string))
+	{
+		return PyUnicode_AsEncodedString(string, codec, NULL);
+	}
+
+	PyErr_SetString(PyExc_TypeError, "value is neither a string or unicode object");
+	return NULL;
+}
+
+
+
 /* --- DBFFile ------------------------------------------------------------------------------------------------------- */
 
 typedef struct {
@@ -158,7 +246,7 @@
 static PyObject* do_read_attribute(DBFHandle handle, int record, int field, char * name)
 {
 	int type, width;
-	const char* temp;
+	const char* string;
 	type = DBFGetFieldInfo(handle, field, name, &width, NULL);
 	
 	/* For strings NULL and the empty string are indistinguishable
@@ -175,8 +263,8 @@
 		switch (type)
 		{
 		case FTString:
-			temp = DBFReadStringAttribute(handle, record, field);
-			if (temp) return PyString_FromString(temp);
+			string = DBFReadStringAttribute(handle, record, field);
+			if (string) return decode_string(handle, string);
 
 		case FTInteger:
 			return PyInt_FromLong((long)DBFReadIntegerAttribute(handle, record, field));
@@ -185,10 +273,10 @@
 			return PyFloat_FromDouble(DBFReadDoubleAttribute(handle, record, field));
 			
 		case FTLogical:
-			temp = DBFReadLogicalAttribute(handle, record, field);
-			if (temp)
+			string = DBFReadLogicalAttribute(handle, record, field);
+			if (string)
 			{
-				switch (temp[0])
+				switch (string[0])
 				{
 				case 'F':
 				case 'N':
@@ -290,6 +378,7 @@
 /* write a single field of a record. */
 static int do_write_field(DBFHandle handle, int record, int field, int type, PyObject* value)
 {
+	PyObject* encoded_string = NULL;
 	char * string_value;
 	int int_value;
 	double double_value;
@@ -304,9 +393,20 @@
 		switch (type)
 		{
 		case FTString:
-			string_value = PyString_AsString(value);
-			if (!string_value) return 0;
-			if (DBFWriteStringAttribute(handle, record, field, string_value)) return 1;
+			encoded_string = encode_string(handle, value);
+			if (!encoded_string) return 0;
+			string_value = PyString_AsString(encoded_string);
+			if (!string_value) 
+			{
+				Py_DECREF(encoded_string);
+				return 0;
+			}
+			if (DBFWriteStringAttribute(handle, record, field, string_value))
+			{
+				Py_DECREF(encoded_string);
+				return 1;
+			}
+			Py_DECREF(encoded_string);
 			break;
 
 		case FTInteger:
@@ -448,7 +548,16 @@
 #endif
 
 
+#if HAVE_LANGUAGE_DRIVER
 
+static PyObject* dbffile_language_driver(DBFFileObject* self, void* closure)
+{
+	return PyInt_FromLong((long)self->handle->nLanguageDriver);
+}
+
+#endif
+
+
 static struct PyMethodDef dbffile_methods[] = 
 {
 	{"close", (PyCFunction)dbffile_close, METH_NOARGS, 
@@ -501,6 +610,9 @@
 
 static struct PyGetSetDef dbffile_getsetters[] = 
 {
+#if HAVE_LANGUAGE_DRIVER
+	{"language_driver", (getter)dbffile_language_driver, NULL, "Language Driver ID (read-only)" },
+#endif
 	{NULL}
 };
 
@@ -574,21 +686,64 @@
 
 
 
+#if HAVE_LANGUAGE_DRIVER
+
+/** translate a numeric Language Driver ID to the name of Python's codec.
+ */
+static PyObject* dbflib_language_driver_codec(PyObject* module, PyObject* args)
+{
+	int ldid;
+	if (!PyArg_ParseTuple(args, "i:language_driver_name", &ldid)) return NULL;
+	if (ldid < 0 || ldid >= PYSHAPELIB_NUM_LANGUAGE_DRIVERS || !codecs[ldid])
+	{
+		PyErr_SetString(PyExc_ValueError, "invalid driver id");
+		return NULL;
+	}
+	return PyString_FromString(codecs[ldid]);
+}
+
+/** translate a numeric Language Driver ID to a string represting its constant.
+ */
+static PyObject* dbflib_language_driver_name(PyObject* module, PyObject* args)
+{
+	int ldid;
+	if (!PyArg_ParseTuple(args, "i:language_driver_name", &ldid)) return NULL;
+	if (ldid < 0 || ldid >= PYSHAPELIB_NUM_LANGUAGE_DRIVERS || !drivers[ldid])
+	{
+		PyErr_SetString(PyExc_ValueError, "invalid driver id");
+		return NULL;
+	}
+	return PyString_FromString(drivers[ldid]);
+}
+
+#endif
+
+
+
 static struct PyMethodDef dbflib_methods[] = 
 {
 	{"open", (PyCFunction)dbflib_open, METH_VARARGS, 
 		"open(name [, mode]) -> DBFFile\n\n"
 		"opens a DBFFile" },
 	{"create", (PyCFunction)dbflib_create, METH_VARARGS, 
-		"create(name) -> DBFFile\n\n"
-		"create a DBFFile" },
+		"create(name [, language_driver]) -> DBFFile\n\n"
+		"create a DBFFile " },
+#if HAVE_LANGUAGE_DRIVER
+	{"language_driver_codec", (PyCFunction)dbflib_language_driver_codec, METH_VARARGS, 
+		"language_driver_codec(driver_id) -> string\n\n"
+		"translate language driver id into the name of the Python's codec used as code page." },
+	{"language_driver_name", (PyCFunction)dbflib_language_driver_name, METH_VARARGS, 
+		"language_driver_name(driver_id) -> string\n\n"
+		"translate language driver id into a string." },
+#endif
 	{NULL}
 };
 
 
-
 PyMODINIT_FUNC initdbflib(void)
 {
+	int i;
+
 	PyObject* module = Py_InitModule("dbflib", dbflib_methods);
 	if (!module) return;
 	
@@ -600,4 +755,86 @@
 	PYSHAPELIB_ADD_CONSTANT(FTLogical);
 	PYSHAPELIB_ADD_CONSTANT(FTInvalid);
 	PyModule_AddIntConstant(module, "_have_commit", HAVE_UPDATE_HEADER);
+
+#if HAVE_LANGUAGE_DRIVER
+	/* table compiled from these resources:
+	 * http://www.clicketyclick.dk/databases/xbase/format/dbf.html
+	 * http://www.esrinl.com/content/file.asp?id=307
+	 * http://msdn2.microsoft.com/en-us/library/aa975345(VS.71).aspx
+	 */
+	for (i = 0; i < PYSHAPELIB_NUM_LANGUAGE_DRIVERS; ++i)
+	{
+		codecs[i] = NULL;
+		drivers[i] = NULL;
+	}
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x00, "cp1252", "NOT_SET");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x01, "cp437", "DOS_USA");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x02, "cp850", "DOS_INTERNATIONAL");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x03, "cp1252", "WINDOWS_ANSI");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x04, "mac_roman", "STANDARD_MACINTOSH");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x08, "cp865", "DANISH_OEM");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x09, "cp437", "DUTCH_OEM");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x0a, "cp850", "DUTCH_OEM_2");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x0b, "cp437", "FINNISH_OEM");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x0d, "cp437", "FRENCH_OEM");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x0e, "cp850", "FRENCH_OEM_2");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x0f, "cp437", "GERMAN_OEM");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x10, "cp850", "GERMAN_OEM_2");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x11, "cp437", "ITALIAN_OEM");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x12, "cp850", "ITALIAN_OEM_2");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x13, "cp932", "JAPANESE_SHIFT_JIS");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x14, "cp850", "SPANISH_OEM_2");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x15, "cp437", "SWEDISH_OEM");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x16, "cp850", "SWEDISH_OEM_2");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x17, "cp865", "NORWEGIAN_OEM");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x18, "cp437", "SPANISH_OEM");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x19, "cp437", "ENGLISH_BRITAIN_OEM");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x1a, "cp850", "ENGLISH_BRITAIN_OEM_2");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x0b, "cp437", "ENGLISH_US_OEM");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x1c, "cp863", "FRENCH_CANADA_OEM");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x1d, "cp850", "FRENCH_OEM_2");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x1f, "cp852", "CZECH_OEM");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x22, "cp852", "HUNGARIAN_OEM");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x23, "cp852", "POLISH_OEM");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x24, "cp860", "PORTUGUESE_OEM");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x25, "cp850", "PORTUGUESE_OEM_2");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x26, "cp866", "RUSSIAN_OEM");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x37, "cp850", "ENGLISH_US_OEM_2");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x40, "cp852", "ROMANIAN_OEM");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x4d, "cp936", "CHINESE_GBK_PRC");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x4e, "cp949", "KOREAN_ANSI_OEM);");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x4f, "cp950", "CHINESE_BIG5_TAIWAN");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x50, "cp874", "THAI_ANSI_OEM");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x57, "cp1252", "ESRI_ANSI");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x58, "cp1252", "WESTERN_EUROPEAN_ANSI");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x59, "cp1252", "SPANISH_ANSI");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x64, "cp852", "EASTERN_EUROPEAN_MSDOS");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x65, "cp866", "RUSSIAN_MSDOS");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x66, "cp865", "NORDIC_MSDOS");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x67, "cp861", "ICELANDIC_MSDOS");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x68, "cp895", "CZECH_MSDOS");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x69, "cp620", "POLISH_MSDOS");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x6a, "cp737", "GREEK_MSDOS");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x6b, "cp857", "TURKISH_MSDOS");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x6c, "cp863", "FRENCH_CANADA_MSDOS");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x78, "cp950", "TAIWAN_BIG5");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x79, "cp949", "HANGUL_WANSUG");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x7a, "cp936", "PRC_GBK");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x7b, "cp932", "JAPANESE_SHIFT_JIS");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x7c, "cp874", "THAI_WINDOWS_MSDOS");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x7d, "cp1255", "HEBREW_WINDOWS");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x7e, "cp1256", "ARABIC_WINDOWS");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x86, "cp737", "GREEK_OEM");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x87, "cp852", "SLOVENIAN_OEM");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x88, "cp857", "TURKISH_OEM");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x96, "mac_cyrillic", "RUSSIAN_MACINTOSH");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x97, "mac_latin2", "EASTERN_EUROPEAN_MACINTOSH");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0x98, "mac_greek", "GREEK_MACINTOSH");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0xc8, "cp1250", "EASTERN_EUROPEAN_WINDOWS");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0xc9, "cp1251", "RUSSIAN_WINDOWS");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0xca, "cp1254", "TURKISH_WINDOWS");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0xcb, "cp1253", "GREEK_WINDOWS");
+	PYSHAPELIB_ADD_LANGUAGE_DRIVER(0xcc, "cp1257", "BALTIC_WINDOWS");
+#endif
+
 }

Modified: branches/WIP-pyshapelib-bramz/libraries/pyshapelib/pyshapelib_common.h
===================================================================
--- branches/WIP-pyshapelib-bramz/libraries/pyshapelib/pyshapelib_common.h	2007-03-28 23:30:15 UTC (rev 2751)
+++ branches/WIP-pyshapelib-bramz/libraries/pyshapelib/pyshapelib_common.h	2007-04-10 23:45:00 UTC (rev 2752)
@@ -1,84 +1,106 @@
-#ifndef PYSHAPELIB_H
-#define PYSHAPELIB_H
-
-#include <Python.h>
-#include <structmember.h>
-#include "shapefil.h"
-#include "pyshapelib_api.h"
-
+/* Copyright (c) 2007 by Intevation GmbH
+ * Authors:
+ * Bram de Greve <bram.degreve at intec.ugent.be>
+ *
+ * This program is free software under the GPL (>=v2)
+ * Read the file COPYING coming with Thuban for details.
+ */
+
+#ifndef PYSHAPELIB_H
+#define PYSHAPELIB_H
+
+#include <Python.h>
+#include <structmember.h>
+#include "shapefil.h"
+#include "pyshapelib_api.h"
+
+/* WIDE-CHARACTER FILENAME SUPPORT FOR WINDOWS
+ * 
+ * pyshapelib can support full Unicode strings as filename on the Windows platform
+ * trough the wide-character version of the Win API.  At this moment, however, this
+ * needs unofficial modifications to the shapelib library to be able to use this API.
+ * 
+ * A ticket has been made in the maptools Bugzilla with patches for the 1.2.10 release
+ * of shapelib: http://bugzilla.maptools.org/show_bug.cgi?id=1692
+ *
+ * The version of shapelib that is contained in the thuban source tree already contains
+ * these modifications.
+ */
 #if defined(SHPAPI_HAS_WIDE) && defined(Py_WIN_WIDE_FILENAMES)
 /* Need GetVersion to see if on NT so safe to use _wfopen */
 #	define WIN32_LEAN_AND_MEAN
 #	include <windows.h>
 #endif
-
-/* helper to export constants (macros) to Python.
- * The constant in Python will have the same name as in C
- */
-#define PYSHAPELIB_ADD_CONSTANT(constant) PyModule_AddIntConstant(module, #constant, constant)
-
-/* helper to define the type object.
- *
- * This assumes quite a few things about different things being available and their name.
- * For example, if prefix = foo, then there should be a deallocation function called foo_dealloc.
- * See the macro itself for other examples.
- */
-#define PYSHAPELIB_DEFINE_TYPE(object, prefix, name, doc) \
-{ \
-		PyObject_HEAD_INIT(NULL) \
-		0,									/*ob_size*/ \
-		name,								/*tp_name*/ \
-		sizeof(object),						/*tp_basicsize*/ \
-		0,									/*tp_itemsize*/ \
-		(destructor) prefix ## _dealloc,	/*tp_dealloc*/ \
-		0,									/*tp_print*/ \
-		0,									/*tp_getattr*/ \
-		0,									/*tp_setattr*/ \
-		0,									/*tp_compare*/ \
-		(reprfunc) prefix ## _repr,			/*tp_repr*/ \
-		0,									/*tp_as_number*/ \
-		0,									/*tp_as_sequence*/ \
-		0,									/*tp_as_mapping*/ \
-		0,									/*tp_hash */ \
-		0,									/*tp_call*/ \
-		0,									/*tp_str*/ \
-		0,									/*tp_getattro*/ \
-		0,									/*tp_setattro*/ \
-		0,									/*tp_as_buffer*/ \
-		Py_TPFLAGS_DEFAULT,					/*tp_flags*/ \
-		doc,								/* tp_doc */ \
-		0,									/* tp_traverse */ \
-		0,									/* tp_clear */ \
-		0,									/* tp_richcompare */ \
-		0,									/* tp_weaklistoffset */ \
-		0,									/* tp_iter */ \
-		0,									/* tp_iternext */ \
-		prefix ## _methods,					/* tp_methods */ \
-		0,									/* tp_members */ \
-		prefix ## _getsetters,				/* tp_getset */ \
-		0,									/* tp_base */ \
-		0,									/* tp_dict */ \
-		0,									/* tp_descr_get */ \
-		0,									/* tp_descr_set */ \
-		0,									/* tp_dictoffset */ \
-		(initproc) prefix ## _init,			/* tp_init */ \
-		0,									/* tp_alloc */ \
-		prefix ## _new,						/* tp_new */ \
-	} \
-	/**/
-
-/* helper to add type to module.
- * Does a bit of the tedious bookkeeping for us
- */
-#define PYSHAPELIB_ADD_TYPE(type, name) \
-	type.ob_type = &PyType_Type; \
-	if (PyType_Ready(&type) >= 0) \
-	{ \
-		Py_INCREF(&type); \
-		PyModule_AddObject(module, name, (PyObject*)&type); \
-	}
-
-#define PYSHAPELIB_NO_DATA_LIMIT 1e-38
-#define PYSHAPELIB_NO_DATA 0
-
+
+/* ---------------------------------------------------------------------------------------------- */
+
+/* helper to export constants (macros) to Python.
+ * The constant in Python will have the same name as in C
+ */
+#define PYSHAPELIB_ADD_CONSTANT(constant) PyModule_AddIntConstant(module, #constant, constant)
+
+/* helper to define the type object.
+ *
+ * This assumes quite a few things about different things being available and their name.
+ * For example, if prefix = foo, then there should be a deallocation function called foo_dealloc.
+ * See the macro itself for other examples.
+ */
+#define PYSHAPELIB_DEFINE_TYPE(object, prefix, name, doc) \
+{ \
+		PyObject_HEAD_INIT(NULL) \
+		0,									/*ob_size*/ \
+		name,								/*tp_name*/ \
+		sizeof(object),						/*tp_basicsize*/ \
+		0,									/*tp_itemsize*/ \
+		(destructor) prefix ## _dealloc,	/*tp_dealloc*/ \
+		0,									/*tp_print*/ \
+		0,									/*tp_getattr*/ \
+		0,									/*tp_setattr*/ \
+		0,									/*tp_compare*/ \
+		(reprfunc) prefix ## _repr,			/*tp_repr*/ \
+		0,									/*tp_as_number*/ \
+		0,									/*tp_as_sequence*/ \
+		0,									/*tp_as_mapping*/ \
+		0,									/*tp_hash */ \
+		0,									/*tp_call*/ \
+		0,									/*tp_str*/ \
+		0,									/*tp_getattro*/ \
+		0,									/*tp_setattro*/ \
+		0,									/*tp_as_buffer*/ \
+		Py_TPFLAGS_DEFAULT,					/*tp_flags*/ \
+		doc,								/* tp_doc */ \
+		0,									/* tp_traverse */ \
+		0,									/* tp_clear */ \
+		0,									/* tp_richcompare */ \
+		0,									/* tp_weaklistoffset */ \
+		0,									/* tp_iter */ \
+		0,									/* tp_iternext */ \
+		prefix ## _methods,					/* tp_methods */ \
+		0,									/* tp_members */ \
+		prefix ## _getsetters,				/* tp_getset */ \
+		0,									/* tp_base */ \
+		0,									/* tp_dict */ \
+		0,									/* tp_descr_get */ \
+		0,									/* tp_descr_set */ \
+		0,									/* tp_dictoffset */ \
+		(initproc) prefix ## _init,			/* tp_init */ \
+		0,									/* tp_alloc */ \
+		prefix ## _new,						/* tp_new */ \
+	} \
+	/**/
+
+/* helper to add type to module.
+ * Does a bit of the tedious bookkeeping for us
+ */
+#define PYSHAPELIB_ADD_TYPE(type, name) \
+	type.ob_type = &PyType_Type; \
+	if (PyType_Ready(&type) >= 0) \
+	{ \
+		Py_INCREF(&type); \
+		PyModule_AddObject(module, name, (PyObject*)&type); \
+	}
+
+#define PYSHAPELIB_NO_DATA_LIMIT 1e-38
+#define PYSHAPELIB_NO_DATA 0
+
 #endif
\ No newline at end of file

Modified: branches/WIP-pyshapelib-bramz/libraries/pyshapelib/setup.py
===================================================================
--- branches/WIP-pyshapelib-bramz/libraries/pyshapelib/setup.py	2007-03-28 23:30:15 UTC (rev 2751)
+++ branches/WIP-pyshapelib-bramz/libraries/pyshapelib/setup.py	2007-04-10 23:45:00 UTC (rev 2752)
@@ -21,51 +21,60 @@
 # filenames exclusively, so we use posix conventions when making
 # filenames for distutils.
 for shp_dir in ["..", "../shapelib", "../../../../../../shapelib"]:
-    if (os.path.isdir(convert_path(shp_dir))
-        and os.path.exists(os.path.join(convert_path(shp_dir), "shpopen.c"))):
-        # shp_dir contains shpopen.c, so assume it's the directory with
-        # the shapefile library to use
-        break
+	if (os.path.isdir(convert_path(shp_dir))
+		and os.path.exists(os.path.join(convert_path(shp_dir), "shpopen.c"))):
+		# shp_dir contains shpopen.c, so assume it's the directory with
+		# the shapefile library to use
+		break
 else:
-    print >>sys.stderr, "no shapelib directory found"
-    sys.exit(1)
+	print >>sys.stderr, "no shapelib directory found"
+	sys.exit(1)
 
 def dbf_macros():
-    """Return the macros to define when compiling the dbflib wrapper.
+	"""Return the macros to define when compiling the dbflib wrapper.
 
-    The returned list specifies one macro, HAVE_UPDATE_HEADER, which is
-    '1' if the dbflib version we will be compiling with has the
-    DBFUpdateHeader function and '0' otherwise.  To check whether
-    DBFUpdateHeader is available, we scan shapefil.h for the string
-    'DBFUpdateHeader'.
-    """
-    f = open(convert_path(shp_dir + "/shapefil.h"))
-    contents = f.read()
-    f.close()
-    if contents.find("DBFUpdateHeader") >= 0:
-        return [("HAVE_UPDATE_HEADER", "1")]
-    else:
-        return [("HAVE_UPDATE_HEADER", "0")]
+	The returned list specifies following macros:
+	- HAVE_UPDATE_HEADER, which is 
+	'1' if the dbflib version we will be compiling with has the
+	DBFUpdateHeader function and '0' otherwise.  To check whether
+	DBFUpdateHeader is available, we scan shapefil.h for the string
+	'DBFUpdateHeader'.
+	- HAVE_LANGUAGE_DRIVER, whics is '1' if the dbflib version we will 
+	compiling with has the nLanguageDriver field in DBFInfo and '0' otherwise.
+	Again, shapefil.h is scanned to check this.
+	"""
+	f = open(convert_path(shp_dir + "/shapefil.h"))
+	contents = f.read()
+	f.close()
+	
+	def have(keyword):
+		if keyword in contents:
+			return "1"
+		return 0
+	
+	return [
+		("HAVE_UPDATE_HEADER", have("DBFUpdateHeader")),
+		("HAVE_LANGUAGE_DRIVER", have("nLanguageDriver"))]
 
 extensions = [Extension("shapelib",
-                        ["shapelibmodule.c",
-                         shp_dir + "/shpopen.c",
-                         shp_dir + "/shptree.c"],
-                        include_dirs = [shp_dir]),
-              Extension("shptree",
-                        ["shptreemodule.c"],
-                        include_dirs = [shp_dir]),
-              Extension("dbflib",
-                        ["dbflibmodule.c",
-                         shp_dir + "/dbfopen.c"],
-                        include_dirs = [shp_dir],
-                        define_macros = dbf_macros())]
+						["shapelibmodule.c",
+						shp_dir + "/shpopen.c",
+						shp_dir + "/shptree.c"],
+						include_dirs = [shp_dir]),
+			Extension("shptree",
+						["shptreemodule.c"],
+						include_dirs = [shp_dir]),
+			Extension("dbflib",
+						["dbflibmodule.c",
+						shp_dir + "/dbfopen.c"],
+						include_dirs = [shp_dir],
+						define_macros = dbf_macros())]
 
 setup(name = "pyshapelib",
-      version = "0.3",
-      description = "Python bindings for shapelib",
-      author = "Bernhard Herzog",
-      author_email = "bh at intevation.de",
-      url = "ftp:intevation.de/users/bh",
-      ext_modules = extensions)
+	version = "0.3",
+	description = "Python bindings for shapelib",
+	author = "Bernhard Herzog",
+	author_email = "bh at intevation.de",
+	url = "ftp:intevation.de/users/bh",
+	ext_modules = extensions)
 

Modified: branches/WIP-pyshapelib-bramz/libraries/shapelib/dbfopen.c
===================================================================
--- branches/WIP-pyshapelib-bramz/libraries/shapelib/dbfopen.c	2007-03-28 23:30:15 UTC (rev 2751)
+++ branches/WIP-pyshapelib-bramz/libraries/shapelib/dbfopen.c	2007-04-10 23:45:00 UTC (rev 2752)
@@ -339,6 +339,8 @@
     abyHeader[10] = (unsigned char) (psDBF->nRecordLength % 256);
     abyHeader[11] = (unsigned char) (psDBF->nRecordLength / 256);
 
+	abyHeader[29] = (unsigned char) (psDBF->nLanguageDriver);
+
 /* -------------------------------------------------------------------- */
 /*      Write the initial 32 byte file header, and all the field        */
 /*      descriptions.                                     		*/
@@ -580,6 +582,7 @@
 
     psDBF->nHeaderLength = nHeadLen = pabyBuf[8] + pabyBuf[9]*256;
     psDBF->nRecordLength = nRecLen = pabyBuf[10] + pabyBuf[11]*256;
+	psDBF->nLanguageDriver = pabyBuf[29];
     
     psDBF->nFields = nFields = (nHeadLen - 32) / 32;
 
@@ -828,6 +831,7 @@
     psDBF->pszCurrentRecord = NULL;
 
     psDBF->bNoHeader = TRUE;
+	psDBF->nLanguageDriver = 0x03; // ANSI
 
     return( psDBF );
 }
@@ -1709,7 +1713,7 @@
 void SHPAPI_CALL
 DBFCloneEmptyEx(DBFHandle psDBF, DBFHandle newDBF) 
 {
-   if ( newDBF == NULL ) return ( NULL ); 
+   if ( newDBF == NULL ) return; 
    
    newDBF->pszHeader = (char *) malloc ( 32 * psDBF->nFields );
    memcpy ( newDBF->pszHeader, psDBF->pszHeader, 32 * psDBF->nFields );

Modified: branches/WIP-pyshapelib-bramz/libraries/shapelib/shapefil.h
===================================================================
--- branches/WIP-pyshapelib-bramz/libraries/shapelib/shapefil.h	2007-03-28 23:30:15 UTC (rev 2751)
+++ branches/WIP-pyshapelib-bramz/libraries/shapelib/shapefil.h	2007-04-10 23:45:00 UTC (rev 2752)
@@ -471,6 +471,7 @@
     
     int		bNoHeader;
     int		bUpdated;
+	int		nLanguageDriver;
 } DBFInfo;
 
 typedef DBFInfo * DBFHandle;



More information about the Thuban-commits mailing list