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:
Daniel Veillard 2002-05-29 08:21:33 +00:00
parent c0801af9f8
commit 46de64e9c0
5 changed files with 226 additions and 27 deletions

View File

@ -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
View File

@ -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);
}

View File

@ -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,

View File

@ -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
View File

@ -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: