⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xmlreader.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 5 页
字号:
    if ((cur->type != XML_TEXT_NODE) &&
        (cur->type != XML_COMMENT_NODE))
	DICT_FREE(cur->name);

    if (((cur->type == XML_ELEMENT_NODE) ||
	 (cur->type == XML_TEXT_NODE)) &&
	(reader != NULL) && (reader->ctxt != NULL) &&
	(reader->ctxt->freeElemsNr < 100)) {
	cur->next = reader->ctxt->freeElems;
	reader->ctxt->freeElems = cur;
	reader->ctxt->freeElemsNr++;
    } else {
	xmlFree(cur);
    }
}

/**
 * xmlTextReaderFreeIDTable:
 * @table:  An id table
 *
 * Deallocate the memory used by an ID hash table.
 */
static void
xmlTextReaderFreeIDTable(xmlIDTablePtr table) {
    xmlHashFree(table, (xmlHashDeallocator) xmlFreeID);
}

/**
 * xmlTextReaderFreeDoc:
 * @reader:  the xmlTextReaderPtr used
 * @cur:  pointer to the document
 *
 * Free up all the structures used by a document, tree included.
 */
static void
xmlTextReaderFreeDoc(xmlTextReaderPtr reader, xmlDocPtr cur) {
    xmlDtdPtr extSubset, intSubset;

    if (cur == NULL) return;

    if ((__xmlRegisterCallbacks) && (xmlDeregisterNodeDefaultValue))
	xmlDeregisterNodeDefaultValue((xmlNodePtr) cur);

    /*
     * Do this before freeing the children list to avoid ID lookups
     */
    if (cur->ids != NULL) xmlTextReaderFreeIDTable((xmlIDTablePtr) cur->ids);
    cur->ids = NULL;
    if (cur->refs != NULL) xmlFreeRefTable((xmlRefTablePtr) cur->refs);
    cur->refs = NULL;
    extSubset = cur->extSubset;
    intSubset = cur->intSubset;
    if (intSubset == extSubset)
	extSubset = NULL;
    if (extSubset != NULL) {
	xmlUnlinkNode((xmlNodePtr) cur->extSubset);
	cur->extSubset = NULL;
	xmlFreeDtd(extSubset);
    }
    if (intSubset != NULL) {
	xmlUnlinkNode((xmlNodePtr) cur->intSubset);
	cur->intSubset = NULL;
	xmlFreeDtd(intSubset);
    }

    if (cur->children != NULL) xmlTextReaderFreeNodeList(reader, cur->children);

    if (cur->version != NULL) xmlFree((char *) cur->version);
    if (cur->name != NULL) xmlFree((char *) cur->name);
    if (cur->encoding != NULL) xmlFree((char *) cur->encoding);
    if (cur->oldNs != NULL) xmlFreeNsList(cur->oldNs);
    if (cur->URL != NULL) xmlFree((char *) cur->URL);
    if (cur->dict != NULL) xmlDictFree(cur->dict);

    xmlFree(cur);
}

/************************************************************************
 *									*
 *			The reader core parser				*
 *									*
 ************************************************************************/
#ifdef DEBUG_READER
static void
xmlTextReaderDebug(xmlTextReaderPtr reader) {
    if ((reader == NULL) || (reader->ctxt == NULL)) {
	fprintf(stderr, "xmlTextReader NULL\n");
	return;
    }
    fprintf(stderr, "xmlTextReader: state %d depth %d ",
	    reader->state, reader->depth);
    if (reader->node == NULL) {
	fprintf(stderr, "node = NULL\n");
    } else {
	fprintf(stderr, "node %s\n", reader->node->name);
    }
    fprintf(stderr, "  input: base %d, cur %d, depth %d: ",
	    reader->base, reader->cur, reader->ctxt->nodeNr);
    if (reader->input->buffer == NULL) {
	fprintf(stderr, "buffer is NULL\n");
    } else {
#ifdef LIBXML_DEBUG_ENABLED
	xmlDebugDumpString(stderr,
		&reader->input->buffer->content[reader->cur]);
#endif
	fprintf(stderr, "\n");
    }
}
#endif

/**
 * xmlTextReaderEntPush:
 * @reader:  the xmlTextReaderPtr used
 * @value:  the entity reference node
 *
 * Pushes a new entity reference node on top of the entities stack
 *
 * Returns 0 in case of error, the index in the stack otherwise
 */
static int
xmlTextReaderEntPush(xmlTextReaderPtr reader, xmlNodePtr value)
{
    if (reader->entMax <= 0) {
	reader->entMax = 10;
	reader->entTab = (xmlNodePtr *) xmlMalloc(reader->entMax *
		                                  sizeof(reader->entTab[0]));
        if (reader->entTab == NULL) {
            xmlGenericError(xmlGenericErrorContext, "xmlMalloc failed !\n");
            return (0);
        }
    }
    if (reader->entNr >= reader->entMax) {
        reader->entMax *= 2;
        reader->entTab =
            (xmlNodePtr *) xmlRealloc(reader->entTab,
                                      reader->entMax *
                                      sizeof(reader->entTab[0]));
        if (reader->entTab == NULL) {
            xmlGenericError(xmlGenericErrorContext, "xmlRealloc failed !\n");
            return (0);
        }
    }
    reader->entTab[reader->entNr] = value;
    reader->ent = value;
    return (reader->entNr++);
}

/**
 * xmlTextReaderEntPop:
 * @reader:  the xmlTextReaderPtr used
 *
 * Pops the top element entity from the entities stack
 *
 * Returns the entity just removed
 */
static xmlNodePtr
xmlTextReaderEntPop(xmlTextReaderPtr reader)
{
    xmlNodePtr ret;

    if (reader->entNr <= 0)
        return (0);
    reader->entNr--;
    if (reader->entNr > 0)
        reader->ent = reader->entTab[reader->entNr - 1];
    else
        reader->ent = NULL;
    ret = reader->entTab[reader->entNr];
    reader->entTab[reader->entNr] = 0;
    return (ret);
}

/**
 * xmlTextReaderStartElement:
 * @ctx: the user data (XML parser context)
 * @fullname:  The element name, including namespace prefix
 * @atts:  An array of name/value attributes pairs, NULL terminated
 *
 * called when an opening tag has been processed.
 */
static void
xmlTextReaderStartElement(void *ctx, const xmlChar *fullname,
	                  const xmlChar **atts) {
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    xmlTextReaderPtr reader = ctxt->_private;

#ifdef DEBUG_CALLBACKS
    printf("xmlTextReaderStartElement(%s)\n", fullname);
#endif
    if ((reader != NULL) && (reader->startElement != NULL)) {
	reader->startElement(ctx, fullname, atts);
	if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
	    (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
	    (ctxt->input->cur[1] == '>'))
	    ctxt->node->extra = NODE_IS_EMPTY;
    }
    if (reader != NULL)
	reader->state = XML_TEXTREADER_ELEMENT;
}

/**
 * xmlTextReaderEndElement:
 * @ctx: the user data (XML parser context)
 * @fullname:  The element name, including namespace prefix
 *
 * called when an ending tag has been processed.
 */
static void
xmlTextReaderEndElement(void *ctx, const xmlChar *fullname) {
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    xmlTextReaderPtr reader = ctxt->_private;

#ifdef DEBUG_CALLBACKS
    printf("xmlTextReaderEndElement(%s)\n", fullname);
#endif
    if ((reader != NULL) && (reader->endElement != NULL)) {
	reader->endElement(ctx, fullname);
    }
}

/**
 * xmlTextReaderStartElementNs:
 * @ctx: the user data (XML parser context)
 * @localname:  the local name of the element
 * @prefix:  the element namespace prefix if available
 * @URI:  the element namespace name if available
 * @nb_namespaces:  number of namespace definitions on that node
 * @namespaces:  pointer to the array of prefix/URI pairs namespace definitions
 * @nb_attributes:  the number of attributes on that node
 * nb_defaulted:  the number of defaulted attributes.
 * @attributes:  pointer to the array of (localname/prefix/URI/value/end)
 *               attribute values.
 *
 * called when an opening tag has been processed.
 */
static void
xmlTextReaderStartElementNs(void *ctx,
                      const xmlChar *localname,
		      const xmlChar *prefix,
		      const xmlChar *URI,
		      int nb_namespaces,
		      const xmlChar **namespaces,
		      int nb_attributes,
		      int nb_defaulted,
		      const xmlChar **attributes)
{
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    xmlTextReaderPtr reader = ctxt->_private;

#ifdef DEBUG_CALLBACKS
    printf("xmlTextReaderStartElementNs(%s)\n", localname);
#endif
    if ((reader != NULL) && (reader->startElementNs != NULL)) {
	reader->startElementNs(ctx, localname, prefix, URI, nb_namespaces,
	                       namespaces, nb_attributes, nb_defaulted,
			       attributes);
	if ((ctxt->node != NULL) && (ctxt->input != NULL) &&
	    (ctxt->input->cur != NULL) && (ctxt->input->cur[0] == '/') &&
	    (ctxt->input->cur[1] == '>'))
	    ctxt->node->extra = NODE_IS_EMPTY;
    }
    if (reader != NULL)
	reader->state = XML_TEXTREADER_ELEMENT;
}

/**
 * xmlTextReaderEndElementNs:
 * @ctx: the user data (XML parser context)
 * @localname:  the local name of the element
 * @prefix:  the element namespace prefix if available
 * @URI:  the element namespace name if available
 *
 * called when an ending tag has been processed.
 */
static void
xmlTextReaderEndElementNs(void *ctx,
                          const xmlChar * localname,
                          const xmlChar * prefix,
		          const xmlChar * URI)
{
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    xmlTextReaderPtr reader = ctxt->_private;

#ifdef DEBUG_CALLBACKS
    printf("xmlTextReaderEndElementNs(%s)\n", localname);
#endif
    if ((reader != NULL) && (reader->endElementNs != NULL)) {
	reader->endElementNs(ctx, localname, prefix, URI);
    }
}


/**
 * xmlTextReaderCharacters:
 * @ctx: the user data (XML parser context)
 * @ch:  a xmlChar string
 * @len: the number of xmlChar
 *
 * receiving some chars from the parser.
 */
static void
xmlTextReaderCharacters(void *ctx, const xmlChar *ch, int len)
{
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    xmlTextReaderPtr reader = ctxt->_private;

#ifdef DEBUG_CALLBACKS
    printf("xmlTextReaderCharacters()\n");
#endif
    if ((reader != NULL) && (reader->characters != NULL)) {
	reader->characters(ctx, ch, len);
    }
}

/**
 * xmlTextReaderCDataBlock:
 * @ctx: the user data (XML parser context)
 * @value:  The pcdata content
 * @len:  the block length
 *
 * called when a pcdata block has been parsed
 */
static void
xmlTextReaderCDataBlock(void *ctx, const xmlChar *ch, int len)
{
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
    xmlTextReaderPtr reader = ctxt->_private;

#ifdef DEBUG_CALLBACKS
    printf("xmlTextReaderCDataBlock()\n");
#endif
    if ((reader != NULL) && (reader->cdataBlock != NULL)) {
	reader->cdataBlock(ctx, ch, len);
    }
}

/**
 * xmlTextReaderPushData:
 * @reader:  the xmlTextReaderPtr used
 *
 * Push data down the progressive parser until a significant callback
 * got raised.
 *
 * Returns -1 in case of failure, 0 otherwise
 */
static int
xmlTextReaderPushData(xmlTextReaderPtr reader) {
    xmlBufferPtr inbuf;
    int val, s;
    xmlTextReaderState oldstate;

    if ((reader->input == NULL) || (reader->input->buffer == NULL))
	return(-1);

    oldstate = reader->state;
    reader->state = XML_TEXTREADER_NONE;
    inbuf = reader->input->buffer;

    while (reader->state == XML_TEXTREADER_NONE) {
	if (inbuf->use < reader->cur + CHUNK_SIZE) {
	    /*
	     * Refill the buffer unless we are at the end of the stream
	     */
	    if (reader->mode != XML_TEXTREADER_MODE_EOF) {
		val = xmlParserInputBufferRead(reader->input, 4096);
		if ((val == 0) &&
		    (inbuf->alloc == XML_BUFFER_ALLOC_IMMUTABLE)) {
		    if (inbuf->use == reader->cur) {
			reader->mode = XML_TEXTREADER_MODE_EOF;
			reader->state = oldstate;
		    }
		} else if (val < 0) {
		    reader->mode = XML_TEXTREADER_MODE_EOF;
		    reader->state = oldstate;
		    if ((oldstate != XML_TEXTREADER_START) ||
			(reader->ctxt->myDoc != NULL))
			return(val);
		} else if (val == 0) {
		    /* mark the end of the stream and process the remains */
		    reader->mode = XML_TEXTREADER_MODE_EOF;
		    break;
		}

	    } else 
		break;
	}
	/*
	 * parse by block of CHUNK_SIZE bytes, various tests show that
	 * it's the best tradeoff at least on a 1.2GH Duron
	 */
	if (inbuf->use >= reader->cur + CHUNK_SIZE) {
	    val = xmlParseChunk(reader->ctxt,
		          (const char *) &inbuf->content[reader->cur],
			  CHUNK_SIZE, 0);
	    reader->cur += CHUNK_SIZE;
	    if ((val != 0) || (reader->ctxt->wellFormed == 0))
		return(-1);
	} else {
	    s = inbuf->use - reader->cur;
	    val = xmlParseChunk(reader->ctxt,
		          (const char *) &inbuf->content[reader->cur],
			  s, 0);
	    reader->cur += s;
	    if ((val != 0) || (reader->ctxt->wellFormed == 0))
		return(-1);
	    break;
	}
    }

    /*
     * Discard the consumed input when needed and possible
     */
    if (reader->mode == XML_TEXTREADER_MODE_INTERACTIVE) {
        if (inbuf->alloc != XML_BUFFER_ALLOC_IMMUTABLE) {
	    if ((reader->cur >= 4096) &&
		(inbuf->use - reader->cur <= CHUNK_SIZE)) {
		val = xmlBufferShrink(inbuf, reader->cur);
		if (val >= 0) {
		    reader->cur -= val;
		}
	    }
	}
    }

    /*
     * At the end of the stream signal that the work is done to the Push
     * parser.
     */
    else if (reader->mode == XML_TEXTREADER_MODE_EOF) {
	if (reader->mode != XML_TEXTREADER_DONE) {
	    s = inbuf->use - reader->cur;
	    val = xmlParseChunk(reader->ctxt,
		    (const char *) &inbuf->content[reader->cur], 
		    s, 1);
	    reader->cur = inbuf->use;
	    reader->mode = XML_TEXTREADER_DONE;
	    if ((val != 0) || (reader->ctxt->wellFormed == 0))
	        return(-1);
	}

⌨️ 快捷键说明

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