pyexpat.c

来自「python s60 1.4.5版本的源代码」· C语言 代码 · 共 1,906 行 · 第 1/4 页

C
1,906
字号
            else if (PyDict_SetItem(container, n, v)) {
                flag_error(self);
                Py_DECREF(n);
                Py_DECREF(v);
                return;
            }
            else {
                Py_DECREF(n);
                Py_DECREF(v);
            }
        }
        args = Py_BuildValue("(O&N)", STRING_CONV_FUNC,name, container);
        if (args == NULL) {
            Py_DECREF(container);
            return;
        }
        /* Container is now a borrowed reference; ignore it. */
        self->in_callback = 1;
        rv = call_with_frame(getcode(StartElement, "StartElement", __LINE__),
                             self->handlers[StartElement], args);
        self->in_callback = 0;
        Py_DECREF(args);
        if (rv == NULL) {
            flag_error(self);
            return;
        }
        Py_DECREF(rv);
    }
}

#define RC_HANDLER(RC, NAME, PARAMS, INIT, PARAM_FORMAT, CONVERSION, \
                RETURN, GETUSERDATA) \
static RC \
my_##NAME##Handler PARAMS {\
    xmlparseobject *self = GETUSERDATA ; \
    PyObject *args = NULL; \
    PyObject *rv = NULL; \
    INIT \
\
    if (self->handlers[NAME] \
        && self->handlers[NAME] != Py_None) { \
        args = Py_BuildValue PARAM_FORMAT ;\
        if (!args) { flag_error(self); return RETURN;} \
        self->in_callback = 1; \
        rv = call_with_frame(getcode(NAME,#NAME,__LINE__), \
                             self->handlers[NAME], args); \
        self->in_callback = 0; \
        Py_DECREF(args); \
        if (rv == NULL) { \
            flag_error(self); \
            return RETURN; \
        } \
        CONVERSION \
        Py_DECREF(rv); \
    } \
    return RETURN; \
}

#define VOID_HANDLER(NAME, PARAMS, PARAM_FORMAT) \
	RC_HANDLER(void, NAME, PARAMS, ;, PARAM_FORMAT, ;, ;,\
	(xmlparseobject *)userData)

#define INT_HANDLER(NAME, PARAMS, PARAM_FORMAT)\
	RC_HANDLER(int, NAME, PARAMS, int rc=0;, PARAM_FORMAT, \
			rc = PyInt_AsLong(rv);, rc, \
	(xmlparseobject *)userData)

VOID_HANDLER(EndElement, 
             (void *userData, const XML_Char *name), 
             ("(O&)", STRING_CONV_FUNC, name))

VOID_HANDLER(ProcessingInstruction,
             (void *userData, 
              const XML_Char *target, 
              const XML_Char *data),
             ("(O&O&)",STRING_CONV_FUNC,target, STRING_CONV_FUNC,data))

#ifndef Py_USING_UNICODE
VOID_HANDLER(CharacterData, 
             (void *userData, const XML_Char *data, int len), 
             ("(N)", conv_string_len_to_utf8(data,len)))
#else
VOID_HANDLER(CharacterData, 
             (void *userData, const XML_Char *data, int len), 
             ("(N)", (self->returns_unicode 
                      ? conv_string_len_to_unicode(data,len) 
                      : conv_string_len_to_utf8(data,len))))
#endif

VOID_HANDLER(UnparsedEntityDecl,
             (void *userData, 
              const XML_Char *entityName,
              const XML_Char *base,
              const XML_Char *systemId,
              const XML_Char *publicId,
              const XML_Char *notationName),
             ("(O&O&O&O&O&)", 
              STRING_CONV_FUNC,entityName, STRING_CONV_FUNC,base, 
              STRING_CONV_FUNC,systemId, STRING_CONV_FUNC,publicId, 
              STRING_CONV_FUNC,notationName))

#if EXPAT_VERSION >= 0x015f00
#ifndef Py_USING_UNICODE
VOID_HANDLER(EntityDecl,
             (void *userData,
              const XML_Char *entityName,
              int is_parameter_entity,
              const XML_Char *value,
              int value_length,
              const XML_Char *base,
              const XML_Char *systemId,
              const XML_Char *publicId,
              const XML_Char *notationName),
             ("O&iNO&O&O&O&",
              STRING_CONV_FUNC,entityName, is_parameter_entity,
              conv_string_len_to_utf8(value, value_length),
              STRING_CONV_FUNC,base, STRING_CONV_FUNC,systemId,
              STRING_CONV_FUNC,publicId, STRING_CONV_FUNC,notationName))
#else
VOID_HANDLER(EntityDecl,
             (void *userData,
              const XML_Char *entityName,
              int is_parameter_entity,
              const XML_Char *value,
              int value_length,
              const XML_Char *base,
              const XML_Char *systemId,
              const XML_Char *publicId,
              const XML_Char *notationName),
             ("O&iNO&O&O&O&",
              STRING_CONV_FUNC,entityName, is_parameter_entity,
              (self->returns_unicode 
               ? conv_string_len_to_unicode(value, value_length) 
               : conv_string_len_to_utf8(value, value_length)),
              STRING_CONV_FUNC,base, STRING_CONV_FUNC,systemId,
              STRING_CONV_FUNC,publicId, STRING_CONV_FUNC,notationName))
#endif

VOID_HANDLER(XmlDecl,
             (void *userData,
              const XML_Char *version,
              const XML_Char *encoding,
              int standalone),
             ("(O&O&i)",
              STRING_CONV_FUNC,version, STRING_CONV_FUNC,encoding, 
              standalone))

static PyObject *
conv_content_model(XML_Content * const model,
                   PyObject *(*conv_string)(XML_Char *))
{
    PyObject *result = NULL;
    PyObject *children = PyTuple_New(model->numchildren);
    int i;

    if (children != NULL) {
        assert(model->numchildren < INT_MAX);
        for (i = 0; i < (int)model->numchildren; ++i) {
            PyObject *child = conv_content_model(&model->children[i],
                                                 conv_string);
            if (child == NULL) {
                Py_XDECREF(children);
                return NULL;
            }
            PyTuple_SET_ITEM(children, i, child);
        }
        result = Py_BuildValue("(iiO&N)",
                               model->type, model->quant,
                               conv_string,model->name, children);
    }
    return result;
}

static PyObject *
conv_content_model_utf8(XML_Content * const model)
{
    return conv_content_model(model, conv_string_to_utf8);
}

#ifdef Py_USING_UNICODE
static PyObject *
conv_content_model_unicode(XML_Content * const model)
{
    return conv_content_model(model, conv_string_to_unicode);
}

VOID_HANDLER(ElementDecl,
             (void *userData,
              const XML_Char *name,
              XML_Content *model),
             ("O&O&",
              STRING_CONV_FUNC,name,
              (self->returns_unicode ? conv_content_model_unicode
                                     : conv_content_model_utf8),model))
#else
VOID_HANDLER(ElementDecl,
             (void *userData,
              const XML_Char *name,
              XML_Content *model),
             ("O&O&",
              STRING_CONV_FUNC,name, conv_content_model_utf8,model))
#endif

VOID_HANDLER(AttlistDecl,
             (void *userData,
              const XML_Char *elname,
              const XML_Char *attname,
              const XML_Char *att_type,
              const XML_Char *dflt,
              int isrequired),
             ("(O&O&O&O&i)",
              STRING_CONV_FUNC,elname, STRING_CONV_FUNC,attname,
              STRING_CONV_FUNC,att_type, STRING_CONV_FUNC,dflt,
              isrequired))
#endif

VOID_HANDLER(NotationDecl, 
		(void *userData,
			const XML_Char *notationName,
			const XML_Char *base,
			const XML_Char *systemId,
			const XML_Char *publicId),
                ("(O&O&O&O&)", 
		 STRING_CONV_FUNC,notationName, STRING_CONV_FUNC,base, 
		 STRING_CONV_FUNC,systemId, STRING_CONV_FUNC,publicId))

VOID_HANDLER(StartNamespaceDecl,
		(void *userData,
		      const XML_Char *prefix,
		      const XML_Char *uri),
                ("(O&O&)", STRING_CONV_FUNC,prefix, STRING_CONV_FUNC,uri))

VOID_HANDLER(EndNamespaceDecl,
		(void *userData,
		    const XML_Char *prefix),
                ("(O&)", STRING_CONV_FUNC,prefix))

VOID_HANDLER(Comment,
               (void *userData, const XML_Char *prefix),
                ("(O&)", STRING_CONV_FUNC,prefix))

VOID_HANDLER(StartCdataSection,
               (void *userData),
		("()"))
		
VOID_HANDLER(EndCdataSection,
               (void *userData),
		("()"))

#ifndef Py_USING_UNICODE
VOID_HANDLER(Default,
	      (void *userData,  const XML_Char *s, int len),
	      ("(N)", conv_string_len_to_utf8(s,len)))

VOID_HANDLER(DefaultHandlerExpand,
	      (void *userData,  const XML_Char *s, int len),
	      ("(N)", conv_string_len_to_utf8(s,len)))
#else
VOID_HANDLER(Default,
	      (void *userData,  const XML_Char *s, int len),
	      ("(N)", (self->returns_unicode 
		       ? conv_string_len_to_unicode(s,len) 
		       : conv_string_len_to_utf8(s,len))))

VOID_HANDLER(DefaultHandlerExpand,
	      (void *userData,  const XML_Char *s, int len),
	      ("(N)", (self->returns_unicode 
		       ? conv_string_len_to_unicode(s,len) 
		       : conv_string_len_to_utf8(s,len))))
#endif

INT_HANDLER(NotStandalone, 
		(void *userData), 
		("()"))

RC_HANDLER(int, ExternalEntityRef,
		(XML_Parser parser,
		    const XML_Char *context,
		    const XML_Char *base,
		    const XML_Char *systemId,
		    const XML_Char *publicId),
		int rc=0;,
                ("(O&O&O&O&)", 
		 STRING_CONV_FUNC,context, STRING_CONV_FUNC,base, 
		 STRING_CONV_FUNC,systemId, STRING_CONV_FUNC,publicId),
		rc = PyInt_AsLong(rv);, rc,
		XML_GetUserData(parser))

/* XXX UnknownEncodingHandler */

#if EXPAT_VERSION == 0x010200
VOID_HANDLER(StartDoctypeDecl,
	     (void *userData, const XML_Char *doctypeName),
	     ("(O&OOi)", STRING_CONV_FUNC,doctypeName,
              Py_None, Py_None, -1))
#elif EXPAT_VERSION >= 0x015f00
VOID_HANDLER(StartDoctypeDecl,
             (void *userData, const XML_Char *doctypeName,
              const XML_Char *sysid, const XML_Char *pubid,
              int has_internal_subset),
             ("(O&O&O&i)", STRING_CONV_FUNC,doctypeName,
              STRING_CONV_FUNC,sysid, STRING_CONV_FUNC,pubid,
              has_internal_subset))
#endif

#if EXPAT_VERSION >= 0x010200
VOID_HANDLER(EndDoctypeDecl, (void *userData), ("()"))
#endif

#if EXPAT_VERSION == 0x010200
VOID_HANDLER(ExternalParsedEntityDecl,
	     (void *userData, const XML_Char *entityName,
	      const XML_Char *base, const XML_Char *systemId,
	      const XML_Char *publicId),
	     ("(O&O&O&O&)", STRING_CONV_FUNC, entityName,
	      STRING_CONV_FUNC, base, STRING_CONV_FUNC, systemId,
	      STRING_CONV_FUNC, publicId))

VOID_HANDLER(InternalParsedEntityDecl,
	     (void *userData, const XML_Char *entityName,
	      const XML_Char *replacementText, int replacementTextLength),
	     ("(O&O&i)", STRING_CONV_FUNC, entityName,
	      STRING_CONV_FUNC, replacementText, replacementTextLength))

#endif /* Expat version 1.2 & better */

/* ---------------------------------------------------------------- */

static char xmlparse_Parse__doc__[] = 
"Parse(data[, isfinal])\n\
Parse XML data.  `isfinal' should be true at end of input.";

static PyObject *
xmlparse_Parse(xmlparseobject *self, PyObject *args)
{
    char *s;
    int slen;
    int isFinal = 0;
    int rv;

    if (!PyArg_ParseTuple(args, "s#|i:Parse", &s, &slen, &isFinal))
        return NULL;
    rv = XML_Parse(self->itself, s, slen, isFinal);
    if (PyErr_Occurred()) {	
        return NULL;
    }
    else if (rv == 0) {
        return set_error(self);
    }
    return PyInt_FromLong(rv);
}

/* File reading copied from cPickle */

#define BUF_SIZE 2048

static int
readinst(char *buf, int buf_size, PyObject *meth)
{
    PyObject *arg = NULL;
    PyObject *bytes = NULL;
    PyObject *str = NULL;
    int len = -1;

    if ((bytes = PyInt_FromLong(buf_size)) == NULL)
        goto finally;

    if ((arg = PyTuple_New(1)) == NULL)
        goto finally;

    PyTuple_SET_ITEM(arg, 0, bytes);

    if ((str = PyObject_CallObject(meth, arg)) == NULL)
        goto finally;

    /* XXX what to do if it returns a Unicode string? */
    if (!PyString_Check(str)) {
        PyErr_Format(PyExc_TypeError, 
                     "read() did not return a string object (type=%.400s)",
                     str->ob_type->tp_name);
        goto finally;
    }
    len = PyString_GET_SIZE(str);
    if (len > buf_size) {
        PyErr_Format(PyExc_ValueError,
                     "read() returned too much data: "
                     "%i bytes requested, %i returned",
                     buf_size, len);
        Py_DECREF(str);
        goto finally;
    }
    memcpy(buf, PyString_AsString(str), len);
finally:
    Py_XDECREF(arg);
    Py_XDECREF(str);
    return len;
}

static char xmlparse_ParseFile__doc__[] = 
"ParseFile(file)\n\
Parse XML data from file-like object.";

static PyObject *
xmlparse_ParseFile(xmlparseobject *self, PyObject *args)
{
    int rv = 1;
    PyObject *f;
    FILE *fp;
    PyObject *readmethod = NULL;

    if (!PyArg_ParseTuple(args, "O:ParseFile", &f))
        return NULL;

    if (PyFile_Check(f)) {
        fp = PyFile_AsFile(f);
    }
    else{
        fp = NULL;
        readmethod = PyObject_GetAttrString(f, "read");
        if (readmethod == NULL) {
            PyErr_Clear();
            PyErr_SetString(PyExc_TypeError, 
                            "argument must have 'read' attribute");
            return 0;
        }
    }
    for (;;) {
        int bytes_read;
        void *buf = XML_GetBuffer(self->itself, BUF_SIZE);
        if (buf == NULL)
            return PyErr_NoMemory();

        if (fp) {
            bytes_read = fread(buf, sizeof(char), BUF_SIZE, fp);
            if (bytes_read < 0) {
                PyErr_SetFromErrno(PyExc_IOError);
                return NULL;
            }
        }
        else {
            bytes_read = readinst(buf, BUF_SIZE, readmethod);
            if (bytes_read < 0)
                return NULL;
        }
        rv = XML_ParseBuffer(self->itself, bytes_read, bytes_read == 0);
        if (PyErr_Occurred())
            return NULL;

        if (!rv || bytes_read == 0)
            break;
    }
    if (rv == 0) {
        return set_error(self);
    }
    return Py_BuildValue("i", rv);
}

static char xmlparse_SetBase__doc__[] = 
"SetBase(base_url)\n\
Set the base URL for the parser.";

static PyObject *
xmlparse_SetBase(xmlparseobject *self, PyObject *args)
{
    char *base;

    if (!PyArg_ParseTuple(args, "s:SetBase", &base))
        return NULL;
    if (!XML_SetBase(self->itself, base)) {
	return PyErr_NoMemory();
    }
    Py_INCREF(Py_None);
    return Py_None;
}

static char xmlparse_GetBase__doc__[] = 
"GetBase() -> url\n\

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?