mirror of
https://github.com/GNOME/libxml2.git
synced 2025-04-06 19:20:23 +08:00
performance patch from Peter Jacobi Daniel
* SAX.c parser.c tree.c include/libxml/tree.h: performance patch from Peter Jacobi Daniel
This commit is contained in:
parent
c0801af9f8
commit
46de64e9c0
@ -1,3 +1,8 @@
|
||||
Wed May 29 10:21:39 CEST 2002 Daniel Veillard <daniel@veillard.com>
|
||||
|
||||
* SAX.c parser.c tree.c include/libxml/tree.h: performance patch from
|
||||
Peter Jacobi
|
||||
|
||||
Mon May 27 23:18:33 CEST 2002 Daniel Veillard <daniel@veillard.com>
|
||||
|
||||
* configure.in: preparing 2.4.22
|
||||
|
8
SAX.c
8
SAX.c
@ -907,7 +907,7 @@ attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
|
||||
}
|
||||
|
||||
/* !!!!!! <a toto:arg="" xmlns:toto="http://toto.com"> */
|
||||
ret = xmlNewNsProp(ctxt->node, namespace, name, NULL);
|
||||
ret = xmlNewNsPropEatName(ctxt->node, namespace, name, NULL);
|
||||
|
||||
if (ret != NULL) {
|
||||
if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
|
||||
@ -984,8 +984,6 @@ attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
|
||||
|
||||
if (nval != NULL)
|
||||
xmlFree(nval);
|
||||
if (name != NULL)
|
||||
xmlFree(name);
|
||||
if (ns != NULL)
|
||||
xmlFree(ns);
|
||||
}
|
||||
@ -1194,7 +1192,7 @@ startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
|
||||
* attributes parsing, since local namespace can be defined as
|
||||
* an attribute at this level.
|
||||
*/
|
||||
ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
|
||||
ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL);
|
||||
if (ret == NULL) return;
|
||||
if (ctxt->myDoc->children == NULL) {
|
||||
#ifdef DEBUG_SAX_TREE
|
||||
@ -1334,8 +1332,6 @@ startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
|
||||
|
||||
if (prefix != NULL)
|
||||
xmlFree(prefix);
|
||||
if (name != NULL)
|
||||
xmlFree(name);
|
||||
|
||||
}
|
||||
|
||||
|
@ -591,6 +591,10 @@ xmlAttrPtr xmlNewNsProp (xmlNodePtr node,
|
||||
xmlNsPtr ns,
|
||||
const xmlChar *name,
|
||||
const xmlChar *value);
|
||||
xmlAttrPtr xmlNewNsPropEatName (xmlNodePtr node,
|
||||
xmlNsPtr ns,
|
||||
xmlChar *name,
|
||||
const xmlChar *value);
|
||||
void xmlFreePropList (xmlAttrPtr cur);
|
||||
void xmlFreeProp (xmlAttrPtr cur);
|
||||
xmlAttrPtr xmlCopyProp (xmlNodePtr target,
|
||||
@ -608,12 +612,18 @@ xmlNodePtr xmlNewDocNode (xmlDocPtr doc,
|
||||
xmlNsPtr ns,
|
||||
const xmlChar *name,
|
||||
const xmlChar *content);
|
||||
xmlNodePtr xmlNewDocNodeEatName (xmlDocPtr doc,
|
||||
xmlNsPtr ns,
|
||||
xmlChar *name,
|
||||
const xmlChar *content);
|
||||
xmlNodePtr xmlNewDocRawNode (xmlDocPtr doc,
|
||||
xmlNsPtr ns,
|
||||
const xmlChar *name,
|
||||
const xmlChar *content);
|
||||
xmlNodePtr xmlNewNode (xmlNsPtr ns,
|
||||
const xmlChar *name);
|
||||
xmlNodePtr xmlNewNodeEatName (xmlNsPtr ns,
|
||||
xmlChar *name);
|
||||
xmlNodePtr xmlNewChild (xmlNodePtr parent,
|
||||
xmlNsPtr ns,
|
||||
const xmlChar *name,
|
||||
|
83
parser.c
83
parser.c
@ -281,18 +281,24 @@ static int spacePop(xmlParserCtxtPtr ctxt) {
|
||||
xmlPopInput(ctxt); \
|
||||
} while (0)
|
||||
|
||||
#define SHRINK if (ctxt->input->cur - ctxt->input->base > INPUT_CHUNK) {\
|
||||
xmlParserInputShrink(ctxt->input); \
|
||||
if ((*ctxt->input->cur == 0) && \
|
||||
(xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) \
|
||||
xmlPopInput(ctxt); \
|
||||
#define SHRINK if (ctxt->input->cur - ctxt->input->base > INPUT_CHUNK) \
|
||||
xmlSHRINK (ctxt);
|
||||
|
||||
static void xmlSHRINK (xmlParserCtxtPtr ctxt) {
|
||||
xmlParserInputShrink(ctxt->input);
|
||||
if ((*ctxt->input->cur == 0) &&
|
||||
(xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
|
||||
xmlPopInput(ctxt);
|
||||
}
|
||||
|
||||
#define GROW if (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK) { \
|
||||
xmlParserInputGrow(ctxt->input, INPUT_CHUNK); \
|
||||
if ((*ctxt->input->cur == 0) && \
|
||||
(xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) \
|
||||
xmlPopInput(ctxt); \
|
||||
#define GROW if (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK) \
|
||||
xmlGROW (ctxt);
|
||||
|
||||
static void xmlGROW (xmlParserCtxtPtr ctxt) {
|
||||
xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
|
||||
if ((*ctxt->input->cur == 0) &&
|
||||
(xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
|
||||
xmlPopInput(ctxt);
|
||||
}
|
||||
|
||||
#define SKIP_BLANKS xmlSkipBlankChars(ctxt)
|
||||
@ -1746,6 +1752,46 @@ xmlParseName(xmlParserCtxtPtr ctxt) {
|
||||
return(xmlParseNameComplex(ctxt));
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlParseNameAndCompare:
|
||||
* @ctxt: an XML parser context
|
||||
*
|
||||
* parse an XML name and compares for match
|
||||
* (specialized for endtag parsing)
|
||||
*
|
||||
*
|
||||
* Returns NULL for an illegal name, (xmlChar*) 1 for success
|
||||
* and the name for mismatch
|
||||
*/
|
||||
|
||||
xmlChar *
|
||||
xmlParseNameAndCompare(xmlParserCtxtPtr ctxt, xmlChar const *other) {
|
||||
const xmlChar *cmp = other;
|
||||
const xmlChar *in;
|
||||
xmlChar *ret;
|
||||
int count = 0;
|
||||
|
||||
GROW;
|
||||
|
||||
in = ctxt->input->cur;
|
||||
while (*in != 0 && *in == *cmp) {
|
||||
++in;
|
||||
++cmp;
|
||||
}
|
||||
if (*cmp == 0 && (*in == '>' || IS_BLANK (*in))) {
|
||||
/* success */
|
||||
ctxt->input->cur = in;
|
||||
return (xmlChar*) 1;
|
||||
}
|
||||
/* failure (or end of input buffer), check with full function */
|
||||
ret = xmlParseName (ctxt);
|
||||
if (ret != 0 && xmlStrEqual (ret, other)) {
|
||||
xmlFree (ret);
|
||||
return (xmlChar*) 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static xmlChar *
|
||||
xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
|
||||
xmlChar buf[XML_MAX_NAMELEN + 5];
|
||||
@ -6556,7 +6602,7 @@ xmlParseEndTag(xmlParserCtxtPtr ctxt) {
|
||||
}
|
||||
SKIP(2);
|
||||
|
||||
name = xmlParseName(ctxt);
|
||||
name = xmlParseNameAndCompare(ctxt,ctxt->name);
|
||||
|
||||
/*
|
||||
* We should definitely be at the ending "S? '>'" part
|
||||
@ -6578,20 +6624,17 @@ xmlParseEndTag(xmlParserCtxtPtr ctxt) {
|
||||
* start-tag.
|
||||
*
|
||||
*/
|
||||
if ((name == NULL) || (ctxt->name == NULL) ||
|
||||
(!xmlStrEqual(name, ctxt->name))) {
|
||||
if (name != (xmlChar*)1) {
|
||||
ctxt->errNo = XML_ERR_TAG_NAME_MISMATCH;
|
||||
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) {
|
||||
if ((name != NULL) && (ctxt->name != NULL)) {
|
||||
if (name != NULL) {
|
||||
ctxt->sax->error(ctxt->userData,
|
||||
"Opening and ending tag mismatch: %s and %s\n",
|
||||
ctxt->name, name);
|
||||
} else if (ctxt->name != NULL) {
|
||||
xmlFree(name);
|
||||
} else {
|
||||
ctxt->sax->error(ctxt->userData,
|
||||
"Ending tag error for: %s\n", ctxt->name);
|
||||
} else {
|
||||
ctxt->sax->error(ctxt->userData,
|
||||
"Ending tag error: internal error ???\n");
|
||||
}
|
||||
|
||||
}
|
||||
@ -6604,10 +6647,8 @@ xmlParseEndTag(xmlParserCtxtPtr ctxt) {
|
||||
*/
|
||||
if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
|
||||
(!ctxt->disableSAX))
|
||||
ctxt->sax->endElement(ctxt->userData, name);
|
||||
ctxt->sax->endElement(ctxt->userData, ctxt->name);
|
||||
|
||||
if (name != NULL)
|
||||
xmlFree(name);
|
||||
oldname = namePop(ctxt);
|
||||
spacePop(ctxt);
|
||||
if (oldname != NULL) {
|
||||
|
147
tree.c
147
tree.c
@ -1203,6 +1203,83 @@ xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
|
||||
return(cur);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlNewNsPropEatName:
|
||||
* @node: the holding node
|
||||
* @ns: the namespace
|
||||
* @name: the name of the attribute
|
||||
* @value: the value of the attribute
|
||||
*
|
||||
* Create a new property tagged with a namespace and carried by a node.
|
||||
* Returns a pointer to the attribute
|
||||
*/
|
||||
xmlAttrPtr
|
||||
xmlNewNsPropEatName(xmlNodePtr node, xmlNsPtr ns, xmlChar *name,
|
||||
const xmlChar *value) {
|
||||
xmlAttrPtr cur;
|
||||
xmlDocPtr doc = NULL;
|
||||
|
||||
if (name == NULL) {
|
||||
#ifdef DEBUG_TREE
|
||||
xmlGenericError(xmlGenericErrorContext,
|
||||
"xmlNewNsPropEatName : name == NULL\n");
|
||||
#endif
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a new property and fill the fields.
|
||||
*/
|
||||
cur = (xmlAttrPtr) xmlMalloc(sizeof(xmlAttr));
|
||||
if (cur == NULL) {
|
||||
xmlGenericError(xmlGenericErrorContext,
|
||||
"xmlNewNsPropEatName : malloc failed\n");
|
||||
return(NULL);
|
||||
}
|
||||
memset(cur, 0, sizeof(xmlAttr));
|
||||
cur->type = XML_ATTRIBUTE_NODE;
|
||||
|
||||
cur->parent = node;
|
||||
if (node != NULL) {
|
||||
doc = node->doc;
|
||||
cur->doc = doc;
|
||||
}
|
||||
cur->ns = ns;
|
||||
cur->name = name;
|
||||
if (value != NULL) {
|
||||
xmlChar *buffer;
|
||||
xmlNodePtr tmp;
|
||||
|
||||
buffer = xmlEncodeEntitiesReentrant(doc, value);
|
||||
cur->children = xmlStringGetNodeList(doc, buffer);
|
||||
cur->last = NULL;
|
||||
tmp = cur->children;
|
||||
while (tmp != NULL) {
|
||||
tmp->parent = (xmlNodePtr) cur;
|
||||
if (tmp->next == NULL)
|
||||
cur->last = tmp;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
xmlFree(buffer);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add it at the end to preserve parsing order ...
|
||||
*/
|
||||
if (node != NULL) {
|
||||
if (node->properties == NULL) {
|
||||
node->properties = cur;
|
||||
} else {
|
||||
xmlAttrPtr prev = node->properties;
|
||||
|
||||
while (prev->next != NULL) prev = prev->next;
|
||||
prev->next = cur;
|
||||
cur->prev = prev;
|
||||
}
|
||||
}
|
||||
return(cur);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlNewDocProp:
|
||||
* @doc: the document
|
||||
@ -1431,6 +1508,44 @@ xmlNewNode(xmlNsPtr ns, const xmlChar *name) {
|
||||
return(cur);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlNewNodeEatName:
|
||||
* @ns: namespace if any
|
||||
* @name: the node name
|
||||
*
|
||||
* Creation of a new node element. @ns is optional (NULL).
|
||||
*
|
||||
* Returns a pointer to the new node object.
|
||||
*/
|
||||
xmlNodePtr
|
||||
xmlNewNodeEatName(xmlNsPtr ns, xmlChar *name) {
|
||||
xmlNodePtr cur;
|
||||
|
||||
if (name == NULL) {
|
||||
#ifdef DEBUG_TREE
|
||||
xmlGenericError(xmlGenericErrorContext,
|
||||
"xmlNewNode : name == NULL\n");
|
||||
#endif
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate a new node and fill the fields.
|
||||
*/
|
||||
cur = (xmlNodePtr) xmlMalloc(sizeof(xmlNode));
|
||||
if (cur == NULL) {
|
||||
xmlGenericError(xmlGenericErrorContext,
|
||||
"xmlNewNode : malloc failed\n");
|
||||
return(NULL);
|
||||
}
|
||||
memset(cur, 0, sizeof(xmlNode));
|
||||
cur->type = XML_ELEMENT_NODE;
|
||||
|
||||
cur->name = name;
|
||||
cur->ns = ns;
|
||||
return(cur);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlNewDocNode:
|
||||
* @doc: the document
|
||||
@ -1463,6 +1578,38 @@ xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
|
||||
return(cur);
|
||||
}
|
||||
|
||||
/**
|
||||
* xmlNewDocNodeEatName:
|
||||
* @doc: the document
|
||||
* @ns: namespace if any
|
||||
* @name: the node name
|
||||
* @content: the XML text content if any
|
||||
*
|
||||
* Creation of a new node element within a document. @ns and @content
|
||||
* are optional (NULL).
|
||||
* NOTE: @content is supposed to be a piece of XML CDATA, so it allow entities
|
||||
* references, but XML special chars need to be escaped first by using
|
||||
* xmlEncodeEntitiesReentrant(). Use xmlNewDocRawNode() if you don't
|
||||
* need entities support.
|
||||
*
|
||||
* Returns a pointer to the new node object.
|
||||
*/
|
||||
xmlNodePtr
|
||||
xmlNewDocNodeEatName(xmlDocPtr doc, xmlNsPtr ns,
|
||||
xmlChar *name, const xmlChar *content) {
|
||||
xmlNodePtr cur;
|
||||
|
||||
cur = xmlNewNodeEatName(ns, name);
|
||||
if (cur != NULL) {
|
||||
cur->doc = doc;
|
||||
if (content != NULL) {
|
||||
cur->children = xmlStringGetNodeList(doc, content);
|
||||
UPDATE_LAST_CHILD_AND_PARENT(cur)
|
||||
}
|
||||
}
|
||||
return(cur);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* xmlNewDocRawNode:
|
||||
|
Loading…
x
Reference in New Issue
Block a user