#include "xmlparse.h"
#endif
+#ifndef PyGC_HEAD_SIZE
+#define PyGC_HEAD_SIZE 0
+#define PyObject_GC_Init(x)
+#define PyObject_GC_Fini(m)
+#define Py_TPFLAGS_GC 0
+#endif
+
enum HandlerTypes {
StartElement,
EndElement,
}
if (PyDict_SetItemString(attrs_obj,
(char*)*attrs_k, rv) < 0) {
+ Py_DECREF(rv);
Py_DECREF(attrs_obj);
attrs_obj = NULL;
goto finally;
/* Callback routines */
-static void clear_handlers(xmlparseobject *self);
+static void clear_handlers(xmlparseobject *self, int decref);
static void
flag_error(xmlparseobject *self)
{
- clear_handlers(self);
+ clear_handlers(self, 1);
}
#define RC_HANDLER(RC, NAME, PARAMS, INIT, PARAM_FORMAT, CONVERSION, \
if (!rv || bytes_read == 0)
break;
}
+ if (rv == 0) {
+ PyErr_Format(ErrorObject, "%.200s: line %i, column %i",
+ XML_ErrorString(XML_GetErrorCode(self->itself)),
+ XML_GetErrorLineNumber(self->itself),
+ XML_GetErrorColumnNumber(self->itself));
+ return NULL;
+ }
return Py_BuildValue("i", rv);
}
#endif
new_parser->itself = XML_ExternalEntityParserCreate(self->itself, context,
- encoding);
- if (!new_parser) {
- Py_DECREF(new_parser);
- return PyErr_NoMemory();
+ encoding);
+ new_parser->handlers = 0;
+ PyObject_GC_Init(new_parser);
+
+ if (!new_parser->itself) {
+ Py_DECREF(new_parser);
+ return PyErr_NoMemory();
}
XML_SetUserData(new_parser->itself, (void *)new_parser);
/* do nothing */;
new_parser->handlers = malloc(sizeof(PyObject *)*i);
- clear_handlers(new_parser);
+ if (!new_parser->handlers) {
+ Py_DECREF(new_parser);
+ return PyErr_NoMemory();
+ }
+ clear_handlers(new_parser, 0);
/* then copy handlers from self */
for (i = 0; handler_info[i].name != NULL; i++) {
/* ---------- */
-static xmlparseobject *
+static PyObject *
newxmlparseobject(char *encoding, char *namespace_separator)
{
int i;
self->returns_unicode = 1;
#endif
+ self->handlers = NULL;
if (namespace_separator) {
self->itself = XML_ParserCreateNS(encoding, *namespace_separator);
}
else{
self->itself = XML_ParserCreate(encoding);
}
+ PyObject_GC_Init(self);
if (self->itself == NULL) {
PyErr_SetString(PyExc_RuntimeError,
"XML_ParserCreate failed");
/* do nothing */;
self->handlers = malloc(sizeof(PyObject *)*i);
- clear_handlers(self);
+ if (!self->handlers){
+ Py_DECREF(self);
+ return PyErr_NoMemory();
+ }
+ clear_handlers(self, 0);
- return self;
+ return (PyObject*)self;
}
xmlparse_dealloc(xmlparseobject *self)
{
int i;
+ PyObject_GC_Fini(self);
if (self->itself)
XML_ParserFree(self->itself);
self->itself = NULL;
- for (i=0; handler_info[i].name != NULL; i++) {
- Py_XDECREF(self->handlers[i]);
+ if(self->handlers){
+ for (i=0; handler_info[i].name != NULL; i++) {
+ Py_XDECREF(self->handlers[i]);
+ }
+ free (self->handlers);
}
#if PY_MAJOR_VERSION == 1 && PY_MINOR_VERSION < 6
/* Code for versions before 1.6 */
return -1;
}
+#ifdef WITH_CYCLE_GC
+static int
+xmlparse_traverse(xmlparseobject *op, visitproc visit, void *arg)
+{
+ int i, err;
+ for (i = 0; handler_info[i].name != NULL; i++) {
+ if (!op->handlers[i])
+ continue;
+ err = visit(op->handlers[i], arg);
+ if (err)
+ return err;
+ }
+ return 0;
+}
+
+static int
+xmlparse_clear(xmlparseobject *op)
+{
+ clear_handlers(op, 1);
+ return 0;
+}
+#endif
+
static char Xmlparsetype__doc__[] =
"XML parser";
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
"xmlparser", /*tp_name*/
- sizeof(xmlparseobject), /*tp_basicsize*/
+ sizeof(xmlparseobject) + PyGC_HEAD_SIZE,/*tp_basicsize*/
0, /*tp_itemsize*/
/* methods */
(destructor)xmlparse_dealloc, /*tp_dealloc*/
(hashfunc)0, /*tp_hash*/
(ternaryfunc)0, /*tp_call*/
(reprfunc)0, /*tp_str*/
-
- /* Space for future expansion */
- 0L,0L,0L,0L,
- Xmlparsetype__doc__ /* Documentation string */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /*tp_flags*/
+ Xmlparsetype__doc__, /* Documentation string */
+#ifdef WITH_CYCLE_GC
+ (traverseproc)xmlparse_traverse, /* tp_traverse */
+ (inquiry)xmlparse_clear /* tp_clear */
+#else
+ 0, 0
+#endif
};
/* End of code for xmlparser objects */
}
static void
-clear_handlers(xmlparseobject *self)
+clear_handlers(xmlparseobject *self, int decref)
{
- int i = 0;
-
- for (; handler_info[i].name!=NULL; i++) {
- self->handlers[i]=NULL;
- handler_info[i].setter(self->itself, NULL);
- }
+ int i = 0;
+
+ for (; handler_info[i].name!=NULL; i++) {
+ if (decref){
+ Py_XDECREF(self->handlers[i]);
+ }
+ self->handlers[i]=NULL;
+ handler_info[i].setter(self->itself, NULL);
+ }
}
typedef void (*pairsetter)(XML_Parser, void *handler1, void *handler2);