|
| 1 | +From adebe45f6ef9f9d036acacd8aec7411d4ea84e25 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Nick Wellnhofer <wellnhofer@aevum.de> |
| 3 | +Date: Wed, 31 Aug 2022 15:29:57 +0200 |
| 4 | +Subject: [PATCH] Infrastructure to store extra data in source nodes |
| 5 | + |
| 6 | +Provide a mechanism to store bit flags in nodes from the source |
| 7 | +document. This will later be used to store key and id status. |
| 8 | + |
| 9 | +Provide a function to find the psvi member of a node. |
| 10 | + |
| 11 | +Revert any changes to the source document after the transformation. |
| 12 | +Upstream Patch Reference: https://gitlab.gnome.org/GNOME/libxslt/-/commit/adebe45f6ef9f9d036acacd8aec7411d4ea84e25 |
| 13 | +--- |
| 14 | + libxslt/transform.c | 34 ++++++++++ |
| 15 | + libxslt/xsltInternals.h | 1 + |
| 16 | + libxslt/xsltutils.c | 135 ++++++++++++++++++++++++++++++++++++++++ |
| 17 | + libxslt/xsltutils.h | 13 ++++ |
| 18 | + 4 files changed, 183 insertions(+) |
| 19 | + |
| 20 | +diff --git a/libxslt/transform.c b/libxslt/transform.c |
| 21 | +index cb43bb47..512eb024 100644 |
| 22 | +--- a/libxslt/transform.c |
| 23 | ++++ b/libxslt/transform.c |
| 24 | +@@ -5746,6 +5746,37 @@ xsltCountKeys(xsltTransformContextPtr ctxt) |
| 25 | + return(ctxt->nbKeys); |
| 26 | + } |
| 27 | + |
| 28 | ++/** |
| 29 | ++ * xsltCleanupSourceDoc: |
| 30 | ++ * @doc: Document |
| 31 | ++ * |
| 32 | ++ * Resets source node flags and ids stored in 'psvi' member. |
| 33 | ++ */ |
| 34 | ++static void |
| 35 | ++xsltCleanupSourceDoc(xmlDocPtr doc) { |
| 36 | ++ xmlNodePtr cur = (xmlNodePtr) doc; |
| 37 | ++ void **psviPtr; |
| 38 | ++ |
| 39 | ++ while (1) { |
| 40 | ++ xsltClearSourceNodeFlags(cur, XSLT_SOURCE_NODE_MASK); |
| 41 | ++ psviPtr = xsltGetPSVIPtr(cur); |
| 42 | ++ if (psviPtr) |
| 43 | ++ *psviPtr = NULL; |
| 44 | ++ |
| 45 | ++ if (cur->children != NULL && cur->type != XML_ENTITY_REF_NODE) { |
| 46 | ++ cur = cur->children; |
| 47 | ++ } else { |
| 48 | ++ while (cur->next == NULL) { |
| 49 | ++ cur = cur->parent; |
| 50 | ++ if (cur == (xmlNodePtr) doc) |
| 51 | ++ return; |
| 52 | ++ } |
| 53 | ++ |
| 54 | ++ cur = cur->next; |
| 55 | ++ } |
| 56 | ++ } |
| 57 | ++} |
| 58 | ++ |
| 59 | + /** |
| 60 | + * xsltApplyStylesheetInternal: |
| 61 | + * @style: a parsed XSLT stylesheet |
| 62 | +@@ -6144,6 +6175,9 @@ xsltApplyStylesheetInternal(xsltStylesheetPtr style, xmlDocPtr doc, |
| 63 | + printf("# Reused variables : %d\n", ctxt->cache->dbgReusedVars); |
| 64 | + #endif |
| 65 | + |
| 66 | ++ if (ctxt->sourceDocDirty) |
| 67 | ++ xsltCleanupSourceDoc(doc); |
| 68 | ++ |
| 69 | + if ((ctxt != NULL) && (userCtxt == NULL)) |
| 70 | + xsltFreeTransformContext(ctxt); |
| 71 | + |
| 72 | +diff --git a/libxslt/xsltInternals.h b/libxslt/xsltInternals.h |
| 73 | +index 14343d27..b0125c21 100644 |
| 74 | +--- a/libxslt/xsltInternals.h |
| 75 | ++++ b/libxslt/xsltInternals.h |
| 76 | +@@ -1786,6 +1786,7 @@ struct _xsltTransformContext { |
| 77 | + int maxTemplateVars; |
| 78 | + unsigned long opLimit; |
| 79 | + unsigned long opCount; |
| 80 | ++ int sourceDocDirty; |
| 81 | + }; |
| 82 | + |
| 83 | + /** |
| 84 | +diff --git a/libxslt/xsltutils.c b/libxslt/xsltutils.c |
| 85 | +index f352ca1b..9f0feb53 100644 |
| 86 | +--- a/libxslt/xsltutils.c |
| 87 | ++++ b/libxslt/xsltutils.c |
| 88 | +@@ -1834,6 +1834,141 @@ xsltSaveResultToString(xmlChar **doc_txt_ptr, int * doc_txt_len, |
| 89 | + return 0; |
| 90 | + } |
| 91 | + |
| 92 | ++/** |
| 93 | ++ * xsltGetSourceNodeFlags: |
| 94 | ++ * @node: Node from source document |
| 95 | ++ * |
| 96 | ++ * Returns the flags for a source node. |
| 97 | ++ */ |
| 98 | ++int |
| 99 | ++xsltGetSourceNodeFlags(xmlNodePtr node) { |
| 100 | ++ /* |
| 101 | ++ * Squeeze the bit flags into the upper bits of |
| 102 | ++ * |
| 103 | ++ * - 'int properties' member in struct _xmlDoc |
| 104 | ++ * - 'xmlAttributeType atype' member in struct _xmlAttr |
| 105 | ++ * - 'unsigned short extra' member in struct _xmlNode |
| 106 | ++ */ |
| 107 | ++ switch (node->type) { |
| 108 | ++ case XML_DOCUMENT_NODE: |
| 109 | ++ case XML_HTML_DOCUMENT_NODE: |
| 110 | ++ return ((xmlDocPtr) node)->properties >> 27; |
| 111 | ++ |
| 112 | ++ case XML_ATTRIBUTE_NODE: |
| 113 | ++ return ((xmlAttrPtr) node)->atype >> 27; |
| 114 | ++ |
| 115 | ++ case XML_ELEMENT_NODE: |
| 116 | ++ case XML_TEXT_NODE: |
| 117 | ++ case XML_CDATA_SECTION_NODE: |
| 118 | ++ case XML_PI_NODE: |
| 119 | ++ case XML_COMMENT_NODE: |
| 120 | ++ return node->extra >> 12; |
| 121 | ++ |
| 122 | ++ default: |
| 123 | ++ return 0; |
| 124 | ++ } |
| 125 | ++} |
| 126 | ++ |
| 127 | ++/** |
| 128 | ++ * xsltSetSourceNodeFlags: |
| 129 | ++ * @node: Node from source document |
| 130 | ++ * @flags: Flags |
| 131 | ++ * |
| 132 | ++ * Sets the specified flags to 1. |
| 133 | ++ * |
| 134 | ++ * Returns 0 on success, -1 on error. |
| 135 | ++ */ |
| 136 | ++int |
| 137 | ++xsltSetSourceNodeFlags(xsltTransformContextPtr ctxt, xmlNodePtr node, |
| 138 | ++ int flags) { |
| 139 | ++ if (node->doc == ctxt->initialContextDoc) |
| 140 | ++ ctxt->sourceDocDirty = 1; |
| 141 | ++ |
| 142 | ++ switch (node->type) { |
| 143 | ++ case XML_DOCUMENT_NODE: |
| 144 | ++ case XML_HTML_DOCUMENT_NODE: |
| 145 | ++ ((xmlDocPtr) node)->properties |= flags << 27; |
| 146 | ++ return 0; |
| 147 | ++ |
| 148 | ++ case XML_ATTRIBUTE_NODE: |
| 149 | ++ ((xmlAttrPtr) node)->atype |= flags << 27; |
| 150 | ++ return 0; |
| 151 | ++ |
| 152 | ++ case XML_ELEMENT_NODE: |
| 153 | ++ case XML_TEXT_NODE: |
| 154 | ++ case XML_CDATA_SECTION_NODE: |
| 155 | ++ case XML_PI_NODE: |
| 156 | ++ case XML_COMMENT_NODE: |
| 157 | ++ node->extra |= flags << 12; |
| 158 | ++ return 0; |
| 159 | ++ |
| 160 | ++ default: |
| 161 | ++ return -1; |
| 162 | ++ } |
| 163 | ++} |
| 164 | ++ |
| 165 | ++/** |
| 166 | ++ * xsltClearSourceNodeFlags: |
| 167 | ++ * @node: Node from source document |
| 168 | ++ * @flags: Flags |
| 169 | ++ * |
| 170 | ++ * Sets the specified flags to 0. |
| 171 | ++ * |
| 172 | ++ * Returns 0 on success, -1 on error. |
| 173 | ++ */ |
| 174 | ++int |
| 175 | ++xsltClearSourceNodeFlags(xmlNodePtr node, int flags) { |
| 176 | ++ switch (node->type) { |
| 177 | ++ case XML_DOCUMENT_NODE: |
| 178 | ++ case XML_HTML_DOCUMENT_NODE: |
| 179 | ++ ((xmlDocPtr) node)->properties &= ~(flags << 27); |
| 180 | ++ return 0; |
| 181 | ++ |
| 182 | ++ case XML_ATTRIBUTE_NODE: |
| 183 | ++ ((xmlAttrPtr) node)->atype &= ~(flags << 27); |
| 184 | ++ return 0; |
| 185 | ++ |
| 186 | ++ case XML_ELEMENT_NODE: |
| 187 | ++ case XML_TEXT_NODE: |
| 188 | ++ case XML_CDATA_SECTION_NODE: |
| 189 | ++ case XML_PI_NODE: |
| 190 | ++ case XML_COMMENT_NODE: |
| 191 | ++ node->extra &= ~(flags << 12); |
| 192 | ++ return 0; |
| 193 | ++ |
| 194 | ++ default: |
| 195 | ++ return -1; |
| 196 | ++ } |
| 197 | ++} |
| 198 | ++ |
| 199 | ++/** |
| 200 | ++ * xsltGetPSVIPtr: |
| 201 | ++ * @cur: Node |
| 202 | ++ * |
| 203 | ++ * Returns a pointer to the psvi member of a node or NULL on error. |
| 204 | ++ */ |
| 205 | ++void ** |
| 206 | ++xsltGetPSVIPtr(xmlNodePtr cur) { |
| 207 | ++ switch (cur->type) { |
| 208 | ++ case XML_DOCUMENT_NODE: |
| 209 | ++ case XML_HTML_DOCUMENT_NODE: |
| 210 | ++ return &((xmlDocPtr) cur)->psvi; |
| 211 | ++ |
| 212 | ++ case XML_ATTRIBUTE_NODE: |
| 213 | ++ return &((xmlAttrPtr) cur)->psvi; |
| 214 | ++ |
| 215 | ++ case XML_ELEMENT_NODE: |
| 216 | ++ case XML_TEXT_NODE: |
| 217 | ++ case XML_CDATA_SECTION_NODE: |
| 218 | ++ case XML_PI_NODE: |
| 219 | ++ case XML_COMMENT_NODE: |
| 220 | ++ return &cur->psvi; |
| 221 | ++ |
| 222 | ++ default: |
| 223 | ++ return NULL; |
| 224 | ++ } |
| 225 | ++} |
| 226 | ++ |
| 227 | + #ifdef WITH_PROFILER |
| 228 | + |
| 229 | + /************************************************************************ |
| 230 | +diff --git a/libxslt/xsltutils.h b/libxslt/xsltutils.h |
| 231 | +index 7a12f7b3..65ef78e0 100644 |
| 232 | +--- a/libxslt/xsltutils.h |
| 233 | ++++ b/libxslt/xsltutils.h |
| 234 | +@@ -244,6 +244,19 @@ XSLTPUBFUN xmlXPathCompExprPtr XSLTCALL |
| 235 | + const xmlChar *str, |
| 236 | + int flags); |
| 237 | + |
| 238 | ++#ifdef IN_LIBXSLT |
| 239 | ++#define XSLT_SOURCE_NODE_MASK 15 |
| 240 | ++int |
| 241 | ++xsltGetSourceNodeFlags(xmlNodePtr node); |
| 242 | ++int |
| 243 | ++xsltSetSourceNodeFlags(xsltTransformContextPtr ctxt, xmlNodePtr node, |
| 244 | ++ int flags); |
| 245 | ++int |
| 246 | ++xsltClearSourceNodeFlags(xmlNodePtr node, int flags); |
| 247 | ++void ** |
| 248 | ++xsltGetPSVIPtr(xmlNodePtr cur); |
| 249 | ++#endif |
| 250 | ++ |
| 251 | + /* |
| 252 | + * Profiling. |
| 253 | + */ |
| 254 | +-- |
| 255 | +GitLab |
| 256 | + |
0 commit comments