📄 libxml.c
字号:
/* * libxml.c: this modules implements the main part of the glue of the * libxml2 library and the Python interpreter. It provides the * entry points where an automatically generated stub is either * unpractical or would not match cleanly the Python model. * * If compiled with MERGED_MODULES, the entry point will be used to * initialize both the libxml2 and the libxslt wrappers * * See Copyright for the status of this software. * * daniel@veillard.com */#include <Python.h>#include <fileobject.h>/* #include "config.h" */#include <libxml/xmlmemory.h>#include <libxml/parser.h>#include <libxml/tree.h>#include <libxml/xpath.h>#include <libxml/xmlerror.h>#include <libxml/xpathInternals.h>#include <libxml/xmlmemory.h>#include <libxml/xmlIO.h>#include <libxml/c14n.h>#include "libxml_wrap.h"#include "libxml2-py.h"#if (defined(_MSC_VER) || defined(__MINGW32__)) && !defined(vsnprintf)#define vsnprintf(b,c,f,a) _vsnprintf(b,c,f,a)#elif defined(WITH_TRIO)#include "trio.h"#define vsnprintf trio_vsnprintf#endif/* #define DEBUG *//* #define DEBUG_SAX *//* #define DEBUG_XPATH *//* #define DEBUG_ERROR *//* #define DEBUG_MEMORY *//* #define DEBUG_FILES *//* #define DEBUG_LOADER */void initlibxml2mod(void);/** * TODO: * * macro to flag unimplemented blocks */#define TODO \ xmlGenericError(xmlGenericErrorContext, \ "Unimplemented block at %s:%d\n", \ __FILE__, __LINE__);/* * the following vars are used for XPath extensions, but * are also referenced within the parser cleanup routine. */static int libxml_xpathCallbacksInitialized = 0;typedef struct libxml_xpathCallback { xmlXPathContextPtr ctx; xmlChar *name; xmlChar *ns_uri; PyObject *function;} libxml_xpathCallback, *libxml_xpathCallbackPtr;typedef libxml_xpathCallback libxml_xpathCallbackArray[];static int libxml_xpathCallbacksAllocd = 10;static libxml_xpathCallbackArray *libxml_xpathCallbacks = NULL;static int libxml_xpathCallbacksNb = 0;/************************************************************************ * * * Memory debug interface * * * ************************************************************************/#if 0extern void xmlMemFree(void *ptr);extern void *xmlMemMalloc(size_t size);extern void *xmlMemRealloc(void *ptr, size_t size);extern char *xmlMemoryStrdup(const char *str);#endifstatic int libxmlMemoryDebugActivated = 0;static long libxmlMemoryAllocatedBase = 0;static int libxmlMemoryDebug = 0;static xmlFreeFunc freeFunc = NULL;static xmlMallocFunc mallocFunc = NULL;static xmlReallocFunc reallocFunc = NULL;static xmlStrdupFunc strdupFunc = NULL;static voidlibxml_xmlErrorInitialize(void); /* forward declare */PyObject *libxml_xmlMemoryUsed(PyObject * self ATTRIBUTE_UNUSED, PyObject * args ATTRIBUTE_UNUSED){ long ret; PyObject *py_retval; ret = xmlMemUsed(); py_retval = libxml_longWrap(ret); return (py_retval);}PyObject *libxml_xmlDebugMemory(PyObject * self ATTRIBUTE_UNUSED, PyObject * args){ int activate; PyObject *py_retval; long ret; if (!PyArg_ParseTuple(args, (char *) "i:xmlDebugMemory", &activate)) return (NULL);#ifdef DEBUG_MEMORY printf("libxml_xmlDebugMemory(%d) called\n", activate);#endif if (activate != 0) { if (libxmlMemoryDebug == 0) { /* * First initialize the library and grab the old memory handlers * and switch the library to memory debugging */ xmlMemGet((xmlFreeFunc *) & freeFunc, (xmlMallocFunc *) & mallocFunc, (xmlReallocFunc *) & reallocFunc, (xmlStrdupFunc *) & strdupFunc); if ((freeFunc == xmlMemFree) && (mallocFunc == xmlMemMalloc) && (reallocFunc == xmlMemRealloc) && (strdupFunc == xmlMemoryStrdup)) { libxmlMemoryAllocatedBase = xmlMemUsed(); } else { /* * cleanup first, because some memory has been * allocated with the non-debug malloc in xmlInitParser * when the python module was imported */ xmlCleanupParser(); ret = (long) xmlMemSetup(xmlMemFree, xmlMemMalloc, xmlMemRealloc, xmlMemoryStrdup); if (ret < 0) goto error; libxmlMemoryAllocatedBase = xmlMemUsed(); /* reinitialize */ xmlInitParser(); libxml_xmlErrorInitialize(); } ret = 0; } else if (libxmlMemoryDebugActivated == 0) { libxmlMemoryAllocatedBase = xmlMemUsed(); ret = 0; } else { ret = xmlMemUsed() - libxmlMemoryAllocatedBase; } libxmlMemoryDebug = 1; libxmlMemoryDebugActivated = 1; } else { if (libxmlMemoryDebugActivated == 1) ret = xmlMemUsed() - libxmlMemoryAllocatedBase; else ret = 0; libxmlMemoryDebugActivated = 0; } error: py_retval = libxml_longWrap(ret); return (py_retval);}PyObject *libxml_xmlPythonCleanupParser(PyObject *self ATTRIBUTE_UNUSED, PyObject *args ATTRIBUTE_UNUSED) { int ix; long freed = -1; if (libxmlMemoryDebug) { freed = xmlMemUsed(); } xmlCleanupParser(); /* * Need to confirm whether we really want to do this (required for * memcheck) in all cases... */ if (libxml_xpathCallbacks != NULL) { /* if ext funcs declared */ for (ix=0; ix<libxml_xpathCallbacksNb; ix++) { if ((*libxml_xpathCallbacks)[ix].name != NULL) xmlFree((*libxml_xpathCallbacks)[ix].name); if ((*libxml_xpathCallbacks)[ix].ns_uri != NULL) xmlFree((*libxml_xpathCallbacks)[ix].ns_uri); } libxml_xpathCallbacksNb = 0; xmlFree(libxml_xpathCallbacks); libxml_xpathCallbacks = NULL; } if (libxmlMemoryDebug) { freed -= xmlMemUsed(); libxmlMemoryAllocatedBase -= freed; if (libxmlMemoryAllocatedBase < 0) libxmlMemoryAllocatedBase = 0; } Py_INCREF(Py_None); return(Py_None);}PyObject *libxml_xmlDumpMemory(ATTRIBUTE_UNUSED PyObject * self, ATTRIBUTE_UNUSED PyObject * args){ if (libxmlMemoryDebug != 0) xmlMemoryDump(); Py_INCREF(Py_None); return (Py_None);}/************************************************************************ * * * Handling Python FILE I/O at the C level * * The raw I/O attack diectly the File objects, while the * * other routines address the ioWrapper instance instead * * * ************************************************************************//** * xmlPythonFileCloseUnref: * @context: the I/O context * * Close an I/O channel */static intxmlPythonFileCloseRaw (void * context) { PyObject *file, *ret;#ifdef DEBUG_FILES printf("xmlPythonFileCloseUnref\n");#endif file = (PyObject *) context; if (file == NULL) return(-1); ret = PyEval_CallMethod(file, (char *) "close", (char *) "()"); if (ret != NULL) { Py_DECREF(ret); } Py_DECREF(file); return(0);}/** * xmlPythonFileReadRaw: * @context: the I/O context * @buffer: where to drop data * @len: number of bytes to write * * Read @len bytes to @buffer from the Python file in the I/O channel * * Returns the number of bytes read */static intxmlPythonFileReadRaw (void * context, char * buffer, int len) { PyObject *file; PyObject *ret; int lenread = -1; char *data;#ifdef DEBUG_FILES printf("xmlPythonFileReadRaw: %d\n", len);#endif file = (PyObject *) context; if (file == NULL) return(-1); ret = PyEval_CallMethod(file, (char *) "read", (char *) "(i)", len); if (ret == NULL) { printf("xmlPythonFileReadRaw: result is NULL\n"); return(-1); } else if (PyString_Check(ret)) { lenread = PyString_Size(ret); data = PyString_AsString(ret); if (lenread > len) memcpy(buffer, data, len); else memcpy(buffer, data, lenread); Py_DECREF(ret); } else { printf("xmlPythonFileReadRaw: result is not a String\n"); Py_DECREF(ret); } return(lenread);}/** * xmlPythonFileRead: * @context: the I/O context * @buffer: where to drop data * @len: number of bytes to write * * Read @len bytes to @buffer from the I/O channel. * * Returns the number of bytes read */static intxmlPythonFileRead (void * context, char * buffer, int len) { PyObject *file; PyObject *ret; int lenread = -1; char *data;#ifdef DEBUG_FILES printf("xmlPythonFileRead: %d\n", len);#endif file = (PyObject *) context; if (file == NULL) return(-1); ret = PyEval_CallMethod(file, (char *) "io_read", (char *) "(i)", len); if (ret == NULL) { printf("xmlPythonFileRead: result is NULL\n"); return(-1); } else if (PyString_Check(ret)) { lenread = PyString_Size(ret); data = PyString_AsString(ret); if (lenread > len) memcpy(buffer, data, len); else memcpy(buffer, data, lenread); Py_DECREF(ret); } else { printf("xmlPythonFileRead: result is not a String\n"); Py_DECREF(ret); } return(lenread);}/** * xmlFileWrite: * @context: the I/O context * @buffer: where to drop data * @len: number of bytes to write * * Write @len bytes from @buffer to the I/O channel. * * Returns the number of bytes written */static intxmlPythonFileWrite (void * context, const char * buffer, int len) { PyObject *file; PyObject *string; PyObject *ret = NULL; int written = -1;#ifdef DEBUG_FILES printf("xmlPythonFileWrite: %d\n", len);#endif file = (PyObject *) context; if (file == NULL) return(-1); string = PyString_FromStringAndSize(buffer, len); if (string == NULL) return(-1); if (PyObject_HasAttrString(file, (char *) "io_write")) { ret = PyEval_CallMethod(file, (char *) "io_write", (char *) "(O)", string); } else if (PyObject_HasAttrString(file, (char *) "write")) { ret = PyEval_CallMethod(file, (char *) "write", (char *) "(O)", string); } Py_DECREF(string); if (ret == NULL) { printf("xmlPythonFileWrite: result is NULL\n"); return(-1); } else if (PyInt_Check(ret)) { written = (int) PyInt_AsLong(ret); Py_DECREF(ret); } else if (ret == Py_None) { written = len; Py_DECREF(ret); } else { printf("xmlPythonFileWrite: result is not an Int nor None\n"); Py_DECREF(ret); } return(written);}/** * xmlPythonFileClose: * @context: the I/O context * * Close an I/O channel */static intxmlPythonFileClose (void * context) { PyObject *file, *ret = NULL;#ifdef DEBUG_FILES printf("xmlPythonFileClose\n");#endif file = (PyObject *) context; if (file == NULL) return(-1); if (PyObject_HasAttrString(file, (char *) "io_close")) { ret = PyEval_CallMethod(file, (char *) "io_close", (char *) "()"); } else if (PyObject_HasAttrString(file, (char *) "flush")) { ret = PyEval_CallMethod(file, (char *) "flush", (char *) "()"); } if (ret != NULL) { Py_DECREF(ret); } return(0);}#ifdef LIBXML_OUTPUT_ENABLED/** * xmlOutputBufferCreatePythonFile: * @file: a PyFile_Type * @encoder: the encoding converter or NULL * * Create a buffered output for the progressive saving to a PyFile_Type * buffered C I/O * * Returns the new parser output or NULL */static xmlOutputBufferPtrxmlOutputBufferCreatePythonFile(PyObject *file, xmlCharEncodingHandlerPtr encoder) { xmlOutputBufferPtr ret; if (file == NULL) return(NULL); ret = xmlAllocOutputBuffer(encoder); if (ret != NULL) { ret->context = file; /* Py_INCREF(file); */ ret->writecallback = xmlPythonFileWrite; ret->closecallback = xmlPythonFileClose; } return(ret);}PyObject *libxml_xmlCreateOutputBuffer(ATTRIBUTE_UNUSED PyObject *self, PyObject *args) { PyObject *py_retval; PyObject *file; xmlChar *encoding; xmlCharEncodingHandlerPtr handler = NULL; xmlOutputBufferPtr buffer; if (!PyArg_ParseTuple(args, (char *)"Oz:xmlOutputBufferCreate", &file, &encoding)) return(NULL); if ((encoding != NULL) && (encoding[0] != 0)) { handler = xmlFindCharEncodingHandler((const char *) encoding); } buffer = xmlOutputBufferCreatePythonFile(file, handler); if (buffer == NULL) printf("libxml_xmlCreateOutputBuffer: buffer == NULL\n"); py_retval = libxml_xmlOutputBufferPtrWrap(buffer); return(py_retval);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -