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