mirror of
https://gitlab.gnome.org/GNOME/libxml2.git
synced 2025-07-30 22:43:14 +03: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:
@ -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>
|
Mon May 27 23:18:33 CEST 2002 Daniel Veillard <daniel@veillard.com>
|
||||||
|
|
||||||
* configure.in: preparing 2.4.22
|
* 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"> */
|
/* !!!!!! <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 (ret != NULL) {
|
||||||
if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
|
if ((ctxt->replaceEntities == 0) && (!ctxt->html)) {
|
||||||
@ -984,8 +984,6 @@ attribute(void *ctx, const xmlChar *fullname, const xmlChar *value)
|
|||||||
|
|
||||||
if (nval != NULL)
|
if (nval != NULL)
|
||||||
xmlFree(nval);
|
xmlFree(nval);
|
||||||
if (name != NULL)
|
|
||||||
xmlFree(name);
|
|
||||||
if (ns != NULL)
|
if (ns != NULL)
|
||||||
xmlFree(ns);
|
xmlFree(ns);
|
||||||
}
|
}
|
||||||
@ -1194,7 +1192,7 @@ startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
|
|||||||
* attributes parsing, since local namespace can be defined as
|
* attributes parsing, since local namespace can be defined as
|
||||||
* an attribute at this level.
|
* an attribute at this level.
|
||||||
*/
|
*/
|
||||||
ret = xmlNewDocNode(ctxt->myDoc, NULL, name, NULL);
|
ret = xmlNewDocNodeEatName(ctxt->myDoc, NULL, name, NULL);
|
||||||
if (ret == NULL) return;
|
if (ret == NULL) return;
|
||||||
if (ctxt->myDoc->children == NULL) {
|
if (ctxt->myDoc->children == NULL) {
|
||||||
#ifdef DEBUG_SAX_TREE
|
#ifdef DEBUG_SAX_TREE
|
||||||
@ -1334,8 +1332,6 @@ startElement(void *ctx, const xmlChar *fullname, const xmlChar **atts)
|
|||||||
|
|
||||||
if (prefix != NULL)
|
if (prefix != NULL)
|
||||||
xmlFree(prefix);
|
xmlFree(prefix);
|
||||||
if (name != NULL)
|
|
||||||
xmlFree(name);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,6 +591,10 @@ xmlAttrPtr xmlNewNsProp (xmlNodePtr node,
|
|||||||
xmlNsPtr ns,
|
xmlNsPtr ns,
|
||||||
const xmlChar *name,
|
const xmlChar *name,
|
||||||
const xmlChar *value);
|
const xmlChar *value);
|
||||||
|
xmlAttrPtr xmlNewNsPropEatName (xmlNodePtr node,
|
||||||
|
xmlNsPtr ns,
|
||||||
|
xmlChar *name,
|
||||||
|
const xmlChar *value);
|
||||||
void xmlFreePropList (xmlAttrPtr cur);
|
void xmlFreePropList (xmlAttrPtr cur);
|
||||||
void xmlFreeProp (xmlAttrPtr cur);
|
void xmlFreeProp (xmlAttrPtr cur);
|
||||||
xmlAttrPtr xmlCopyProp (xmlNodePtr target,
|
xmlAttrPtr xmlCopyProp (xmlNodePtr target,
|
||||||
@ -608,12 +612,18 @@ xmlNodePtr xmlNewDocNode (xmlDocPtr doc,
|
|||||||
xmlNsPtr ns,
|
xmlNsPtr ns,
|
||||||
const xmlChar *name,
|
const xmlChar *name,
|
||||||
const xmlChar *content);
|
const xmlChar *content);
|
||||||
|
xmlNodePtr xmlNewDocNodeEatName (xmlDocPtr doc,
|
||||||
|
xmlNsPtr ns,
|
||||||
|
xmlChar *name,
|
||||||
|
const xmlChar *content);
|
||||||
xmlNodePtr xmlNewDocRawNode (xmlDocPtr doc,
|
xmlNodePtr xmlNewDocRawNode (xmlDocPtr doc,
|
||||||
xmlNsPtr ns,
|
xmlNsPtr ns,
|
||||||
const xmlChar *name,
|
const xmlChar *name,
|
||||||
const xmlChar *content);
|
const xmlChar *content);
|
||||||
xmlNodePtr xmlNewNode (xmlNsPtr ns,
|
xmlNodePtr xmlNewNode (xmlNsPtr ns,
|
||||||
const xmlChar *name);
|
const xmlChar *name);
|
||||||
|
xmlNodePtr xmlNewNodeEatName (xmlNsPtr ns,
|
||||||
|
xmlChar *name);
|
||||||
xmlNodePtr xmlNewChild (xmlNodePtr parent,
|
xmlNodePtr xmlNewChild (xmlNodePtr parent,
|
||||||
xmlNsPtr ns,
|
xmlNsPtr ns,
|
||||||
const xmlChar *name,
|
const xmlChar *name,
|
||||||
|
83
parser.c
83
parser.c
@ -281,18 +281,24 @@ static int spacePop(xmlParserCtxtPtr ctxt) {
|
|||||||
xmlPopInput(ctxt); \
|
xmlPopInput(ctxt); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define SHRINK if (ctxt->input->cur - ctxt->input->base > INPUT_CHUNK) {\
|
#define SHRINK if (ctxt->input->cur - ctxt->input->base > INPUT_CHUNK) \
|
||||||
xmlParserInputShrink(ctxt->input); \
|
xmlSHRINK (ctxt);
|
||||||
if ((*ctxt->input->cur == 0) && \
|
|
||||||
(xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) \
|
static void xmlSHRINK (xmlParserCtxtPtr ctxt) {
|
||||||
xmlPopInput(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) { \
|
#define GROW if (ctxt->input->end - ctxt->input->cur < INPUT_CHUNK) \
|
||||||
xmlParserInputGrow(ctxt->input, INPUT_CHUNK); \
|
xmlGROW (ctxt);
|
||||||
if ((*ctxt->input->cur == 0) && \
|
|
||||||
(xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0)) \
|
static void xmlGROW (xmlParserCtxtPtr ctxt) {
|
||||||
xmlPopInput(ctxt); \
|
xmlParserInputGrow(ctxt->input, INPUT_CHUNK);
|
||||||
|
if ((*ctxt->input->cur == 0) &&
|
||||||
|
(xmlParserInputGrow(ctxt->input, INPUT_CHUNK) <= 0))
|
||||||
|
xmlPopInput(ctxt);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SKIP_BLANKS xmlSkipBlankChars(ctxt)
|
#define SKIP_BLANKS xmlSkipBlankChars(ctxt)
|
||||||
@ -1746,6 +1752,46 @@ xmlParseName(xmlParserCtxtPtr ctxt) {
|
|||||||
return(xmlParseNameComplex(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 *
|
static xmlChar *
|
||||||
xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
|
xmlParseNameComplex(xmlParserCtxtPtr ctxt) {
|
||||||
xmlChar buf[XML_MAX_NAMELEN + 5];
|
xmlChar buf[XML_MAX_NAMELEN + 5];
|
||||||
@ -6556,7 +6602,7 @@ xmlParseEndTag(xmlParserCtxtPtr ctxt) {
|
|||||||
}
|
}
|
||||||
SKIP(2);
|
SKIP(2);
|
||||||
|
|
||||||
name = xmlParseName(ctxt);
|
name = xmlParseNameAndCompare(ctxt,ctxt->name);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We should definitely be at the ending "S? '>'" part
|
* We should definitely be at the ending "S? '>'" part
|
||||||
@ -6578,20 +6624,17 @@ xmlParseEndTag(xmlParserCtxtPtr ctxt) {
|
|||||||
* start-tag.
|
* start-tag.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
if ((name == NULL) || (ctxt->name == NULL) ||
|
if (name != (xmlChar*)1) {
|
||||||
(!xmlStrEqual(name, ctxt->name))) {
|
|
||||||
ctxt->errNo = XML_ERR_TAG_NAME_MISMATCH;
|
ctxt->errNo = XML_ERR_TAG_NAME_MISMATCH;
|
||||||
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) {
|
if ((ctxt->sax != NULL) && (ctxt->sax->error != NULL)) {
|
||||||
if ((name != NULL) && (ctxt->name != NULL)) {
|
if (name != NULL) {
|
||||||
ctxt->sax->error(ctxt->userData,
|
ctxt->sax->error(ctxt->userData,
|
||||||
"Opening and ending tag mismatch: %s and %s\n",
|
"Opening and ending tag mismatch: %s and %s\n",
|
||||||
ctxt->name, name);
|
ctxt->name, name);
|
||||||
} else if (ctxt->name != NULL) {
|
xmlFree(name);
|
||||||
|
} else {
|
||||||
ctxt->sax->error(ctxt->userData,
|
ctxt->sax->error(ctxt->userData,
|
||||||
"Ending tag error for: %s\n", ctxt->name);
|
"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) &&
|
if ((ctxt->sax != NULL) && (ctxt->sax->endElement != NULL) &&
|
||||||
(!ctxt->disableSAX))
|
(!ctxt->disableSAX))
|
||||||
ctxt->sax->endElement(ctxt->userData, name);
|
ctxt->sax->endElement(ctxt->userData, ctxt->name);
|
||||||
|
|
||||||
if (name != NULL)
|
|
||||||
xmlFree(name);
|
|
||||||
oldname = namePop(ctxt);
|
oldname = namePop(ctxt);
|
||||||
spacePop(ctxt);
|
spacePop(ctxt);
|
||||||
if (oldname != NULL) {
|
if (oldname != NULL) {
|
||||||
|
147
tree.c
147
tree.c
@ -1203,6 +1203,83 @@ xmlNewNsProp(xmlNodePtr node, xmlNsPtr ns, const xmlChar *name,
|
|||||||
return(cur);
|
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:
|
* xmlNewDocProp:
|
||||||
* @doc: the document
|
* @doc: the document
|
||||||
@ -1431,6 +1508,44 @@ xmlNewNode(xmlNsPtr ns, const xmlChar *name) {
|
|||||||
return(cur);
|
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:
|
* xmlNewDocNode:
|
||||||
* @doc: the document
|
* @doc: the document
|
||||||
@ -1463,6 +1578,38 @@ xmlNewDocNode(xmlDocPtr doc, xmlNsPtr ns,
|
|||||||
return(cur);
|
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:
|
* xmlNewDocRawNode:
|
||||||
|
Reference in New Issue
Block a user