From 4b1d154e7be8c19e6f340c5c533548c4d308ab74 Mon Sep 17 00:00:00 2001 From: Daniel Veillard Date: Wed, 21 Feb 2001 03:12:53 +0000 Subject: [PATCH] This should speed up and correct a few problems: - libxslt/transform.c libxslt/variables.c libxslt/xsltInternals.h: fixed the param evaluation problem in apply-template - libxslt/pattern.c: speed up seriously some context computation - libxslt/xsltInternals.h: preparing for extension support Daniel --- ChangeLog | 7 +++ TODO | 32 ++++++----- libxslt/pattern.c | 142 ++++++++++++++++++++++++++++++++++++++++++------ libxslt/transform.c | 6 ++ libxslt/variables.c | 10 +++- libxslt/xsltInternals.h | 11 ++++ 6 files changed, 175 insertions(+), 33 deletions(-) diff --git a/ChangeLog b/ChangeLog index a3d1c92..e610266 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Wed Feb 21 09:10:13 CET 2001 Daniel Veillard + + * libxslt/transform.c libxslt/variables.c libxslt/xsltInternals.h: + fixed the param evaluation problem in apply-template + * libxslt/pattern.c: speed up seriously some context computation + * libxslt/xsltInternals.h: preparing for extension support + Mon Feb 19 19:34:59 CET 2001 Daniel Veillard * libxslt/Makefile.am: small cleanup diff --git a/TODO b/TODO index 353526e..25883ca 100644 --- a/TODO +++ b/TODO @@ -4,6 +4,10 @@ * * ******** +Leak: + - find and fix memleak in xmlspec + => this is new ... + Doc: - manpage and doc for xsltproc @@ -18,24 +22,17 @@ Embedding Stylesheets: - example in 2.7 would force to validate Import: - -> make sure we use the cascade wherever it's needed Extra functions: -> document() should not be a problem since Result Tree Fragments are implemented => started, incomplete - -> missing key support ID and Key support: -> Id should be simple, key will probably requires some hash tables. -Templates: - -> check the built-in template rule for attributes - -> make sure @xxx matches are applied - Pattern tester: -> try to optimize for ID scan and tests. - -> support for mode Pattern scanner: -> add error checks on all returns @@ -54,22 +51,28 @@ Sorting: -> add lang and case-order -> add foreign sorting functions (interfaces ?). -Validity: - -> should we add validation by default ? Make this an option - -> redirrect validity errors - -Contextual error reporting: - -> provide a couple of functions providing context analysis, not urgent - ******** * * * DONE * * * ******** +Templates: + -> check the built-in template rule for attributes + -> make sure @xxx matches are applied + +Contextual error reporting: + -> provide a couple of functions providing context analysis, not urgent + +Validity: + -> should we add validation by default ? Make this an option + -> redirrect validity errors + => done added a special parsing mode + Import: -> parse them -> provide functions to circulate in the import tree of stylesheets + -> make sure we use the cascade wherever it's needed Extra functions: -> make a separate module. @@ -95,6 +98,7 @@ Support for disable-output-escaping="yes": Pattern scanner: -> compute priority -> handle unions + -> support for mode => done Pattern tester: diff --git a/libxslt/pattern.c b/libxslt/pattern.c index 231fe1c..94c803d 100644 --- a/libxslt/pattern.c +++ b/libxslt/pattern.c @@ -9,6 +9,11 @@ * Daniel.Veillard@imag.fr */ +/* + * TODO: handle pathological cases like *[*[@a="b"]] + * TODO: detect [number] at compilation, optimize accordingly + */ + #include "xsltconfig.h" #include @@ -60,6 +65,12 @@ struct _xsltStepOp { xmlChar *value; xmlChar *value2; xmlChar *value3; + /* + * Optimisations for count + */ + xmlNodePtr previous; + int index; + int len; }; struct _xsltCompMatch { @@ -495,40 +506,135 @@ xsltTestCompMatch(xsltTransformContextPtr ctxt, xsltCompMatchPtr comp, (node->type == XML_ELEMENT_NODE) && (node->parent != NULL)) { - /* TODO: cache those informations !!! */ - xmlNodePtr siblings = node->parent->children; + if ((select->previous != NULL) && + (select->previous->parent == node->parent)) { + /* + * just walk back to adjust the index + */ + int i = 0; + xmlNodePtr sibling = node; - while (siblings != NULL) { - if (siblings->type == XML_ELEMENT_NODE) { - if (siblings == node) { - len++; - pos = len; - } else if (xmlStrEqual(node->name, - siblings->name)) { - len++; + while (sibling != NULL) { + if (sibling == select->previous) + break; + if (xmlStrEqual(node->name, sibling->name)) { + if ((select->value2 == NULL) || + ((sibling->ns != NULL) && + (xmlStrEqual(select->value2, + sibling->ns->href)))) + i++; + } + sibling = sibling->prev; + } + if (sibling == NULL) { + /* hum going backward in document order ... */ + i = 0; + sibling = node; + while (sibling != NULL) { + if (sibling == select->previous) + break; + if ((select->value2 == NULL) || + ((sibling->ns != NULL) && + (xmlStrEqual(select->value2, + sibling->ns->href)))) + i--; + sibling = sibling->next; } } - siblings = siblings->next; + if (sibling != NULL) { + pos = select->index + i; + len = select->len; + select->previous = node; + select->index = pos; + } else + pos = 0; + } else { + /* + * recompute the index + */ + xmlNodePtr siblings = node->parent->children; + + while (siblings != NULL) { + if (siblings->type == XML_ELEMENT_NODE) { + if (siblings == node) { + len++; + pos = len; + } else if (xmlStrEqual(node->name, + siblings->name)) { + if ((select->value2 == NULL) || + ((siblings->ns != NULL) && + (xmlStrEqual(select->value2, + siblings->ns->href)))) + len++; + } + } + siblings = siblings->next; + } } if (pos != 0) { ctxt->xpathCtxt->contextSize = len; ctxt->xpathCtxt->proximityPosition = pos; + select->previous = node; + select->index = pos; + select->len = len; } } else if ((select != NULL) && (select->op == XSLT_OP_ALL)) { - xmlNodePtr siblings = node->parent->children; + if ((select->previous != NULL) && + (select->previous->parent == node->parent)) { + /* + * just walk back to adjust the index + */ + int i = 0; + xmlNodePtr sibling = node; + + while (sibling != NULL) { + if (sibling == select->previous) + break; + if (sibling->type == XML_ELEMENT_NODE) + i++; + sibling = sibling->prev; + } + if (sibling == NULL) { + /* hum going backward in document order ... */ + i = 0; + sibling = node; + while (sibling != NULL) { + if (sibling == select->previous) + break; + if (sibling->type == XML_ELEMENT_NODE) + i--; + sibling = sibling->next; + } + } + if (sibling != NULL) { + pos = select->index + i; + len = select->len; + select->previous = node; + select->index = pos; + } else + pos = 0; + } else { + /* + * recompute the index + */ + xmlNodePtr siblings = node->parent->children; - while (siblings != NULL) { - if (siblings->type == XML_ELEMENT_NODE) { - len++; - if (siblings == node) { - pos = len; + while (siblings != NULL) { + if (siblings->type == XML_ELEMENT_NODE) { + len++; + if (siblings == node) { + pos = len; + } } + siblings = siblings->next; } - siblings = siblings->next; } if (pos != 0) { ctxt->xpathCtxt->contextSize = len; ctxt->xpathCtxt->proximityPosition = pos; + select->previous = node; + select->index = pos; + select->len = len; } } oldNode = ctxt->node; diff --git a/libxslt/transform.c b/libxslt/transform.c index 085f236..992e01f 100644 --- a/libxslt/transform.c +++ b/libxslt/transform.c @@ -152,6 +152,7 @@ xsltNewTransformContext(xsltStylesheetPtr style, xmlDocPtr doc) { cur->varsNr = 0; cur->varsMax = 5; cur->vars = NULL; + cur->varsComputed = 0; cur->style = style; xmlXPathInit(); @@ -1470,8 +1471,12 @@ xsltCallTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node, "xslt:call-template: template %s not found\n", ncname); goto error; } + /* + * Create a new frame but block access to variables + */ templPush(ctxt, template); varsPush(ctxt, NULL); + ctxt->varsComputed = 1; cur = inst->children; while (cur != NULL) { if (ctxt->state == XSLT_STATE_STOPPED) break; @@ -1488,6 +1493,7 @@ xsltCallTemplate(xsltTransformContextPtr ctxt, xmlNodePtr node, } cur = cur->next; } + ctxt->varsComputed = 0; xsltApplyOneTemplate(ctxt, node, template->content, 1); xsltFreeStackElemList(varsPop(ctxt)); diff --git a/libxslt/variables.c b/libxslt/variables.c index be53cd4..cde2a8a 100644 --- a/libxslt/variables.c +++ b/libxslt/variables.c @@ -186,7 +186,15 @@ xsltStackLookup(xsltTransformContextPtr ctxt, const xmlChar *name, if ((ctxt == NULL) || (name == NULL)) return(NULL); - for (i = ctxt->varsNr - 1;i >= 0;i--) { + /* + * Do the lookup from the top of the stack, but + * don't use params being computed in a call-param + */ + i = ctxt->varsNr - 1; + if (ctxt->varsComputed) + i--; + + for (;i >= 0;i--) { cur = ctxt->varsTab[i]; while (cur != NULL) { if (xmlStrEqual(cur->name, name)) { diff --git a/libxslt/xsltInternals.h b/libxslt/xsltInternals.h index 47dfe94..b7b3f88 100644 --- a/libxslt/xsltInternals.h +++ b/libxslt/xsltInternals.h @@ -209,6 +209,14 @@ struct _xsltTransformContext { int varsNr; /* Nb of variable list in the stack */ int varsMax; /* Size of the variable list stack */ xsltStackElemPtr *varsTab; /* the variable list stack */ + int varsComputed; /* switched during param template + evaluation */ + + /* + * Extensions + */ + xmlHashTablePtr extFunctions; /* the extension functions */ + xmlHashTablePtr extElements; /* the extension elements */ const xmlChar *mode; /* the current mode */ const xmlChar *modeURI; /* the current mode URI */ @@ -227,6 +235,9 @@ struct _xsltTransformContext { xsltTransformState state; /* the current state */ }; +typedef void (*xsltTransformFunction) (xsltTransformContextPtr ctxt, + xmlNodePtr node, xmlNodePtr inst); + #define CHECK_STOPPED if (ctxt->state == XSLT_STATE_STOPPED) return; #define CHECK_STOPPEDE if (ctxt->state == XSLT_STATE_STOPPED) goto error; #define CHECK_STOPPED0 if (ctxt->state == XSLT_STATE_STOPPED) return(0); -- 2.7.4