This should speed up and correct a few problems:
authorDaniel Veillard <veillard@src.gnome.org>
Wed, 21 Feb 2001 03:12:53 +0000 (03:12 +0000)
committerDaniel Veillard <veillard@src.gnome.org>
Wed, 21 Feb 2001 03:12:53 +0000 (03:12 +0000)
- 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
TODO
libxslt/pattern.c
libxslt/transform.c
libxslt/variables.c
libxslt/xsltInternals.h

index a3d1c92..e610266 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Wed Feb 21 09:10:13 CET 2001 Daniel Veillard <Daniel.Veillard@imag.fr>
+
+       * 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 <Daniel.Veillard@imag.fr>
 
        * libxslt/Makefile.am: small cleanup
diff --git a/TODO b/TODO
index 353526e..25883ca 100644 (file)
--- 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:
index 231fe1c..94c803d 100644 (file)
@@ -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 <string.h>
@@ -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;
index 085f236..992e01f 100644 (file)
@@ -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));
index be53cd4..cde2a8a 100644 (file)
@@ -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)) {
index 47dfe94..b7b3f88 100644 (file)
@@ -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);