1*7c568831SAndroid Build Coastguard Worker /*
2*7c568831SAndroid Build Coastguard Worker * xpath.c: XML Path Language implementation
3*7c568831SAndroid Build Coastguard Worker * XPath is a language for addressing parts of an XML document,
4*7c568831SAndroid Build Coastguard Worker * designed to be used by both XSLT and XPointer
5*7c568831SAndroid Build Coastguard Worker *
6*7c568831SAndroid Build Coastguard Worker * Reference: W3C Recommendation 16 November 1999
7*7c568831SAndroid Build Coastguard Worker * http://www.w3.org/TR/1999/REC-xpath-19991116
8*7c568831SAndroid Build Coastguard Worker * Public reference:
9*7c568831SAndroid Build Coastguard Worker * http://www.w3.org/TR/xpath
10*7c568831SAndroid Build Coastguard Worker *
11*7c568831SAndroid Build Coastguard Worker * See Copyright for the status of this software
12*7c568831SAndroid Build Coastguard Worker *
13*7c568831SAndroid Build Coastguard Worker * Author: [email protected]
14*7c568831SAndroid Build Coastguard Worker *
15*7c568831SAndroid Build Coastguard Worker */
16*7c568831SAndroid Build Coastguard Worker
17*7c568831SAndroid Build Coastguard Worker /* To avoid EBCDIC trouble when parsing on zOS */
18*7c568831SAndroid Build Coastguard Worker #if defined(__MVS__)
19*7c568831SAndroid Build Coastguard Worker #pragma convert("ISO8859-1")
20*7c568831SAndroid Build Coastguard Worker #endif
21*7c568831SAndroid Build Coastguard Worker
22*7c568831SAndroid Build Coastguard Worker #define IN_LIBXML
23*7c568831SAndroid Build Coastguard Worker #include "libxml.h"
24*7c568831SAndroid Build Coastguard Worker
25*7c568831SAndroid Build Coastguard Worker #include <limits.h>
26*7c568831SAndroid Build Coastguard Worker #include <string.h>
27*7c568831SAndroid Build Coastguard Worker #include <stddef.h>
28*7c568831SAndroid Build Coastguard Worker #include <math.h>
29*7c568831SAndroid Build Coastguard Worker #include <float.h>
30*7c568831SAndroid Build Coastguard Worker #include <ctype.h>
31*7c568831SAndroid Build Coastguard Worker
32*7c568831SAndroid Build Coastguard Worker #include <libxml/xmlmemory.h>
33*7c568831SAndroid Build Coastguard Worker #include <libxml/tree.h>
34*7c568831SAndroid Build Coastguard Worker #include <libxml/xpath.h>
35*7c568831SAndroid Build Coastguard Worker #include <libxml/xpathInternals.h>
36*7c568831SAndroid Build Coastguard Worker #include <libxml/parserInternals.h>
37*7c568831SAndroid Build Coastguard Worker #include <libxml/hash.h>
38*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_DEBUG_ENABLED
39*7c568831SAndroid Build Coastguard Worker #include <libxml/debugXML.h>
40*7c568831SAndroid Build Coastguard Worker #endif
41*7c568831SAndroid Build Coastguard Worker #include <libxml/xmlerror.h>
42*7c568831SAndroid Build Coastguard Worker #include <libxml/threads.h>
43*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_PATTERN_ENABLED
44*7c568831SAndroid Build Coastguard Worker #include <libxml/pattern.h>
45*7c568831SAndroid Build Coastguard Worker #endif
46*7c568831SAndroid Build Coastguard Worker
47*7c568831SAndroid Build Coastguard Worker #include "private/buf.h"
48*7c568831SAndroid Build Coastguard Worker #include "private/error.h"
49*7c568831SAndroid Build Coastguard Worker #include "private/xpath.h"
50*7c568831SAndroid Build Coastguard Worker
51*7c568831SAndroid Build Coastguard Worker /* Disabled for now */
52*7c568831SAndroid Build Coastguard Worker #if 0
53*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_PATTERN_ENABLED
54*7c568831SAndroid Build Coastguard Worker #define XPATH_STREAMING
55*7c568831SAndroid Build Coastguard Worker #endif
56*7c568831SAndroid Build Coastguard Worker #endif
57*7c568831SAndroid Build Coastguard Worker
58*7c568831SAndroid Build Coastguard Worker /**
59*7c568831SAndroid Build Coastguard Worker * WITH_TIM_SORT:
60*7c568831SAndroid Build Coastguard Worker *
61*7c568831SAndroid Build Coastguard Worker * Use the Timsort algorithm provided in timsort.h to sort
62*7c568831SAndroid Build Coastguard Worker * nodeset as this is a great improvement over the old Shell sort
63*7c568831SAndroid Build Coastguard Worker * used in xmlXPathNodeSetSort()
64*7c568831SAndroid Build Coastguard Worker */
65*7c568831SAndroid Build Coastguard Worker #define WITH_TIM_SORT
66*7c568831SAndroid Build Coastguard Worker
67*7c568831SAndroid Build Coastguard Worker /*
68*7c568831SAndroid Build Coastguard Worker * XP_OPTIMIZED_NON_ELEM_COMPARISON:
69*7c568831SAndroid Build Coastguard Worker * If defined, this will use xmlXPathCmpNodesExt() instead of
70*7c568831SAndroid Build Coastguard Worker * xmlXPathCmpNodes(). The new function is optimized comparison of
71*7c568831SAndroid Build Coastguard Worker * non-element nodes; actually it will speed up comparison only if
72*7c568831SAndroid Build Coastguard Worker * xmlXPathOrderDocElems() was called in order to index the elements of
73*7c568831SAndroid Build Coastguard Worker * a tree in document order; Libxslt does such an indexing, thus it will
74*7c568831SAndroid Build Coastguard Worker * benefit from this optimization.
75*7c568831SAndroid Build Coastguard Worker */
76*7c568831SAndroid Build Coastguard Worker #define XP_OPTIMIZED_NON_ELEM_COMPARISON
77*7c568831SAndroid Build Coastguard Worker
78*7c568831SAndroid Build Coastguard Worker /*
79*7c568831SAndroid Build Coastguard Worker * XP_OPTIMIZED_FILTER_FIRST:
80*7c568831SAndroid Build Coastguard Worker * If defined, this will optimize expressions like "key('foo', 'val')[b][1]"
81*7c568831SAndroid Build Coastguard Worker * in a way, that it stop evaluation at the first node.
82*7c568831SAndroid Build Coastguard Worker */
83*7c568831SAndroid Build Coastguard Worker #define XP_OPTIMIZED_FILTER_FIRST
84*7c568831SAndroid Build Coastguard Worker
85*7c568831SAndroid Build Coastguard Worker /*
86*7c568831SAndroid Build Coastguard Worker * XPATH_MAX_STEPS:
87*7c568831SAndroid Build Coastguard Worker * when compiling an XPath expression we arbitrary limit the maximum
88*7c568831SAndroid Build Coastguard Worker * number of step operation in the compiled expression. 1000000 is
89*7c568831SAndroid Build Coastguard Worker * an insanely large value which should never be reached under normal
90*7c568831SAndroid Build Coastguard Worker * circumstances
91*7c568831SAndroid Build Coastguard Worker */
92*7c568831SAndroid Build Coastguard Worker #define XPATH_MAX_STEPS 1000000
93*7c568831SAndroid Build Coastguard Worker
94*7c568831SAndroid Build Coastguard Worker /*
95*7c568831SAndroid Build Coastguard Worker * XPATH_MAX_STACK_DEPTH:
96*7c568831SAndroid Build Coastguard Worker * when evaluating an XPath expression we arbitrary limit the maximum
97*7c568831SAndroid Build Coastguard Worker * number of object allowed to be pushed on the stack. 1000000 is
98*7c568831SAndroid Build Coastguard Worker * an insanely large value which should never be reached under normal
99*7c568831SAndroid Build Coastguard Worker * circumstances
100*7c568831SAndroid Build Coastguard Worker */
101*7c568831SAndroid Build Coastguard Worker #define XPATH_MAX_STACK_DEPTH 1000000
102*7c568831SAndroid Build Coastguard Worker
103*7c568831SAndroid Build Coastguard Worker /*
104*7c568831SAndroid Build Coastguard Worker * XPATH_MAX_NODESET_LENGTH:
105*7c568831SAndroid Build Coastguard Worker * when evaluating an XPath expression nodesets are created and we
106*7c568831SAndroid Build Coastguard Worker * arbitrary limit the maximum length of those node set. 10000000 is
107*7c568831SAndroid Build Coastguard Worker * an insanely large value which should never be reached under normal
108*7c568831SAndroid Build Coastguard Worker * circumstances, one would first need to construct an in memory tree
109*7c568831SAndroid Build Coastguard Worker * with more than 10 millions nodes.
110*7c568831SAndroid Build Coastguard Worker */
111*7c568831SAndroid Build Coastguard Worker #define XPATH_MAX_NODESET_LENGTH 10000000
112*7c568831SAndroid Build Coastguard Worker
113*7c568831SAndroid Build Coastguard Worker /*
114*7c568831SAndroid Build Coastguard Worker * XPATH_MAX_RECRUSION_DEPTH:
115*7c568831SAndroid Build Coastguard Worker * Maximum amount of nested functions calls when parsing or evaluating
116*7c568831SAndroid Build Coastguard Worker * expressions
117*7c568831SAndroid Build Coastguard Worker */
118*7c568831SAndroid Build Coastguard Worker #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
119*7c568831SAndroid Build Coastguard Worker #define XPATH_MAX_RECURSION_DEPTH 500
120*7c568831SAndroid Build Coastguard Worker #elif defined(_WIN32)
121*7c568831SAndroid Build Coastguard Worker /* Windows typically limits stack size to 1MB. */
122*7c568831SAndroid Build Coastguard Worker #define XPATH_MAX_RECURSION_DEPTH 1000
123*7c568831SAndroid Build Coastguard Worker #else
124*7c568831SAndroid Build Coastguard Worker #define XPATH_MAX_RECURSION_DEPTH 5000
125*7c568831SAndroid Build Coastguard Worker #endif
126*7c568831SAndroid Build Coastguard Worker
127*7c568831SAndroid Build Coastguard Worker /*
128*7c568831SAndroid Build Coastguard Worker * TODO:
129*7c568831SAndroid Build Coastguard Worker * There are a few spots where some tests are done which depend upon ascii
130*7c568831SAndroid Build Coastguard Worker * data. These should be enhanced for full UTF8 support (see particularly
131*7c568831SAndroid Build Coastguard Worker * any use of the macros IS_ASCII_CHARACTER and IS_ASCII_DIGIT)
132*7c568831SAndroid Build Coastguard Worker */
133*7c568831SAndroid Build Coastguard Worker
134*7c568831SAndroid Build Coastguard Worker #if defined(LIBXML_XPATH_ENABLED)
135*7c568831SAndroid Build Coastguard Worker
136*7c568831SAndroid Build Coastguard Worker /************************************************************************
137*7c568831SAndroid Build Coastguard Worker * *
138*7c568831SAndroid Build Coastguard Worker * Floating point stuff *
139*7c568831SAndroid Build Coastguard Worker * *
140*7c568831SAndroid Build Coastguard Worker ************************************************************************/
141*7c568831SAndroid Build Coastguard Worker
142*7c568831SAndroid Build Coastguard Worker double xmlXPathNAN = 0.0;
143*7c568831SAndroid Build Coastguard Worker double xmlXPathPINF = 0.0;
144*7c568831SAndroid Build Coastguard Worker double xmlXPathNINF = 0.0;
145*7c568831SAndroid Build Coastguard Worker
146*7c568831SAndroid Build Coastguard Worker /**
147*7c568831SAndroid Build Coastguard Worker * xmlXPathInit:
148*7c568831SAndroid Build Coastguard Worker *
149*7c568831SAndroid Build Coastguard Worker * DEPRECATED: Alias for xmlInitParser.
150*7c568831SAndroid Build Coastguard Worker */
151*7c568831SAndroid Build Coastguard Worker void
xmlXPathInit(void)152*7c568831SAndroid Build Coastguard Worker xmlXPathInit(void) {
153*7c568831SAndroid Build Coastguard Worker xmlInitParser();
154*7c568831SAndroid Build Coastguard Worker }
155*7c568831SAndroid Build Coastguard Worker
156*7c568831SAndroid Build Coastguard Worker /**
157*7c568831SAndroid Build Coastguard Worker * xmlInitXPathInternal:
158*7c568831SAndroid Build Coastguard Worker *
159*7c568831SAndroid Build Coastguard Worker * Initialize the XPath environment
160*7c568831SAndroid Build Coastguard Worker */
161*7c568831SAndroid Build Coastguard Worker ATTRIBUTE_NO_SANITIZE("float-divide-by-zero")
162*7c568831SAndroid Build Coastguard Worker void
xmlInitXPathInternal(void)163*7c568831SAndroid Build Coastguard Worker xmlInitXPathInternal(void) {
164*7c568831SAndroid Build Coastguard Worker #if defined(NAN) && defined(INFINITY)
165*7c568831SAndroid Build Coastguard Worker xmlXPathNAN = NAN;
166*7c568831SAndroid Build Coastguard Worker xmlXPathPINF = INFINITY;
167*7c568831SAndroid Build Coastguard Worker xmlXPathNINF = -INFINITY;
168*7c568831SAndroid Build Coastguard Worker #else
169*7c568831SAndroid Build Coastguard Worker /* MSVC doesn't allow division by zero in constant expressions. */
170*7c568831SAndroid Build Coastguard Worker double zero = 0.0;
171*7c568831SAndroid Build Coastguard Worker xmlXPathNAN = 0.0 / zero;
172*7c568831SAndroid Build Coastguard Worker xmlXPathPINF = 1.0 / zero;
173*7c568831SAndroid Build Coastguard Worker xmlXPathNINF = -xmlXPathPINF;
174*7c568831SAndroid Build Coastguard Worker #endif
175*7c568831SAndroid Build Coastguard Worker }
176*7c568831SAndroid Build Coastguard Worker
177*7c568831SAndroid Build Coastguard Worker /**
178*7c568831SAndroid Build Coastguard Worker * xmlXPathIsNaN:
179*7c568831SAndroid Build Coastguard Worker * @val: a double value
180*7c568831SAndroid Build Coastguard Worker *
181*7c568831SAndroid Build Coastguard Worker * Checks whether a double is a NaN.
182*7c568831SAndroid Build Coastguard Worker *
183*7c568831SAndroid Build Coastguard Worker * Returns 1 if the value is a NaN, 0 otherwise
184*7c568831SAndroid Build Coastguard Worker */
185*7c568831SAndroid Build Coastguard Worker int
xmlXPathIsNaN(double val)186*7c568831SAndroid Build Coastguard Worker xmlXPathIsNaN(double val) {
187*7c568831SAndroid Build Coastguard Worker #ifdef isnan
188*7c568831SAndroid Build Coastguard Worker return isnan(val);
189*7c568831SAndroid Build Coastguard Worker #else
190*7c568831SAndroid Build Coastguard Worker return !(val == val);
191*7c568831SAndroid Build Coastguard Worker #endif
192*7c568831SAndroid Build Coastguard Worker }
193*7c568831SAndroid Build Coastguard Worker
194*7c568831SAndroid Build Coastguard Worker /**
195*7c568831SAndroid Build Coastguard Worker * xmlXPathIsInf:
196*7c568831SAndroid Build Coastguard Worker * @val: a double value
197*7c568831SAndroid Build Coastguard Worker *
198*7c568831SAndroid Build Coastguard Worker * Checks whether a double is an infinity.
199*7c568831SAndroid Build Coastguard Worker *
200*7c568831SAndroid Build Coastguard Worker * Returns 1 if the value is +Infinite, -1 if -Infinite, 0 otherwise
201*7c568831SAndroid Build Coastguard Worker */
202*7c568831SAndroid Build Coastguard Worker int
xmlXPathIsInf(double val)203*7c568831SAndroid Build Coastguard Worker xmlXPathIsInf(double val) {
204*7c568831SAndroid Build Coastguard Worker #ifdef isinf
205*7c568831SAndroid Build Coastguard Worker return isinf(val) ? (val > 0 ? 1 : -1) : 0;
206*7c568831SAndroid Build Coastguard Worker #else
207*7c568831SAndroid Build Coastguard Worker if (val >= xmlXPathPINF)
208*7c568831SAndroid Build Coastguard Worker return 1;
209*7c568831SAndroid Build Coastguard Worker if (val <= -xmlXPathPINF)
210*7c568831SAndroid Build Coastguard Worker return -1;
211*7c568831SAndroid Build Coastguard Worker return 0;
212*7c568831SAndroid Build Coastguard Worker #endif
213*7c568831SAndroid Build Coastguard Worker }
214*7c568831SAndroid Build Coastguard Worker
215*7c568831SAndroid Build Coastguard Worker /*
216*7c568831SAndroid Build Coastguard Worker * TODO: when compatibility allows remove all "fake node libxslt" strings
217*7c568831SAndroid Build Coastguard Worker * the test should just be name[0] = ' '
218*7c568831SAndroid Build Coastguard Worker */
219*7c568831SAndroid Build Coastguard Worker
220*7c568831SAndroid Build Coastguard Worker static const xmlNs xmlXPathXMLNamespaceStruct = {
221*7c568831SAndroid Build Coastguard Worker NULL,
222*7c568831SAndroid Build Coastguard Worker XML_NAMESPACE_DECL,
223*7c568831SAndroid Build Coastguard Worker XML_XML_NAMESPACE,
224*7c568831SAndroid Build Coastguard Worker BAD_CAST "xml",
225*7c568831SAndroid Build Coastguard Worker NULL,
226*7c568831SAndroid Build Coastguard Worker NULL
227*7c568831SAndroid Build Coastguard Worker };
228*7c568831SAndroid Build Coastguard Worker static const xmlNs *const xmlXPathXMLNamespace = &xmlXPathXMLNamespaceStruct;
229*7c568831SAndroid Build Coastguard Worker
230*7c568831SAndroid Build Coastguard Worker static void
231*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetClear(xmlNodeSetPtr set, int hasNsNodes);
232*7c568831SAndroid Build Coastguard Worker
233*7c568831SAndroid Build Coastguard Worker #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
234*7c568831SAndroid Build Coastguard Worker /**
235*7c568831SAndroid Build Coastguard Worker * xmlXPathCmpNodesExt:
236*7c568831SAndroid Build Coastguard Worker * @node1: the first node
237*7c568831SAndroid Build Coastguard Worker * @node2: the second node
238*7c568831SAndroid Build Coastguard Worker *
239*7c568831SAndroid Build Coastguard Worker * Compare two nodes w.r.t document order.
240*7c568831SAndroid Build Coastguard Worker * This one is optimized for handling of non-element nodes.
241*7c568831SAndroid Build Coastguard Worker *
242*7c568831SAndroid Build Coastguard Worker * Returns -2 in case of error 1 if first point < second point, 0 if
243*7c568831SAndroid Build Coastguard Worker * it's the same node, -1 otherwise
244*7c568831SAndroid Build Coastguard Worker */
245*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCmpNodesExt(xmlNodePtr node1,xmlNodePtr node2)246*7c568831SAndroid Build Coastguard Worker xmlXPathCmpNodesExt(xmlNodePtr node1, xmlNodePtr node2) {
247*7c568831SAndroid Build Coastguard Worker int depth1, depth2;
248*7c568831SAndroid Build Coastguard Worker int misc = 0, precedence1 = 0, precedence2 = 0;
249*7c568831SAndroid Build Coastguard Worker xmlNodePtr miscNode1 = NULL, miscNode2 = NULL;
250*7c568831SAndroid Build Coastguard Worker xmlNodePtr cur, root;
251*7c568831SAndroid Build Coastguard Worker ptrdiff_t l1, l2;
252*7c568831SAndroid Build Coastguard Worker
253*7c568831SAndroid Build Coastguard Worker if ((node1 == NULL) || (node2 == NULL))
254*7c568831SAndroid Build Coastguard Worker return(-2);
255*7c568831SAndroid Build Coastguard Worker
256*7c568831SAndroid Build Coastguard Worker if (node1 == node2)
257*7c568831SAndroid Build Coastguard Worker return(0);
258*7c568831SAndroid Build Coastguard Worker
259*7c568831SAndroid Build Coastguard Worker /*
260*7c568831SAndroid Build Coastguard Worker * a couple of optimizations which will avoid computations in most cases
261*7c568831SAndroid Build Coastguard Worker */
262*7c568831SAndroid Build Coastguard Worker switch (node1->type) {
263*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
264*7c568831SAndroid Build Coastguard Worker if (node2->type == XML_ELEMENT_NODE) {
265*7c568831SAndroid Build Coastguard Worker if ((0 > (ptrdiff_t) node1->content) &&
266*7c568831SAndroid Build Coastguard Worker (0 > (ptrdiff_t) node2->content) &&
267*7c568831SAndroid Build Coastguard Worker (node1->doc == node2->doc))
268*7c568831SAndroid Build Coastguard Worker {
269*7c568831SAndroid Build Coastguard Worker l1 = -((ptrdiff_t) node1->content);
270*7c568831SAndroid Build Coastguard Worker l2 = -((ptrdiff_t) node2->content);
271*7c568831SAndroid Build Coastguard Worker if (l1 < l2)
272*7c568831SAndroid Build Coastguard Worker return(1);
273*7c568831SAndroid Build Coastguard Worker if (l1 > l2)
274*7c568831SAndroid Build Coastguard Worker return(-1);
275*7c568831SAndroid Build Coastguard Worker } else
276*7c568831SAndroid Build Coastguard Worker goto turtle_comparison;
277*7c568831SAndroid Build Coastguard Worker }
278*7c568831SAndroid Build Coastguard Worker break;
279*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE:
280*7c568831SAndroid Build Coastguard Worker precedence1 = 1; /* element is owner */
281*7c568831SAndroid Build Coastguard Worker miscNode1 = node1;
282*7c568831SAndroid Build Coastguard Worker node1 = node1->parent;
283*7c568831SAndroid Build Coastguard Worker misc = 1;
284*7c568831SAndroid Build Coastguard Worker break;
285*7c568831SAndroid Build Coastguard Worker case XML_TEXT_NODE:
286*7c568831SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
287*7c568831SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
288*7c568831SAndroid Build Coastguard Worker case XML_PI_NODE: {
289*7c568831SAndroid Build Coastguard Worker miscNode1 = node1;
290*7c568831SAndroid Build Coastguard Worker /*
291*7c568831SAndroid Build Coastguard Worker * Find nearest element node.
292*7c568831SAndroid Build Coastguard Worker */
293*7c568831SAndroid Build Coastguard Worker if (node1->prev != NULL) {
294*7c568831SAndroid Build Coastguard Worker do {
295*7c568831SAndroid Build Coastguard Worker node1 = node1->prev;
296*7c568831SAndroid Build Coastguard Worker if (node1->type == XML_ELEMENT_NODE) {
297*7c568831SAndroid Build Coastguard Worker precedence1 = 3; /* element in prev-sibl axis */
298*7c568831SAndroid Build Coastguard Worker break;
299*7c568831SAndroid Build Coastguard Worker }
300*7c568831SAndroid Build Coastguard Worker if (node1->prev == NULL) {
301*7c568831SAndroid Build Coastguard Worker precedence1 = 2; /* element is parent */
302*7c568831SAndroid Build Coastguard Worker /*
303*7c568831SAndroid Build Coastguard Worker * URGENT TODO: Are there any cases, where the
304*7c568831SAndroid Build Coastguard Worker * parent of such a node is not an element node?
305*7c568831SAndroid Build Coastguard Worker */
306*7c568831SAndroid Build Coastguard Worker node1 = node1->parent;
307*7c568831SAndroid Build Coastguard Worker break;
308*7c568831SAndroid Build Coastguard Worker }
309*7c568831SAndroid Build Coastguard Worker } while (1);
310*7c568831SAndroid Build Coastguard Worker } else {
311*7c568831SAndroid Build Coastguard Worker precedence1 = 2; /* element is parent */
312*7c568831SAndroid Build Coastguard Worker node1 = node1->parent;
313*7c568831SAndroid Build Coastguard Worker }
314*7c568831SAndroid Build Coastguard Worker if ((node1 == NULL) || (node1->type != XML_ELEMENT_NODE) ||
315*7c568831SAndroid Build Coastguard Worker (0 <= (ptrdiff_t) node1->content)) {
316*7c568831SAndroid Build Coastguard Worker /*
317*7c568831SAndroid Build Coastguard Worker * Fallback for whatever case.
318*7c568831SAndroid Build Coastguard Worker */
319*7c568831SAndroid Build Coastguard Worker node1 = miscNode1;
320*7c568831SAndroid Build Coastguard Worker precedence1 = 0;
321*7c568831SAndroid Build Coastguard Worker } else
322*7c568831SAndroid Build Coastguard Worker misc = 1;
323*7c568831SAndroid Build Coastguard Worker }
324*7c568831SAndroid Build Coastguard Worker break;
325*7c568831SAndroid Build Coastguard Worker case XML_NAMESPACE_DECL:
326*7c568831SAndroid Build Coastguard Worker /*
327*7c568831SAndroid Build Coastguard Worker * TODO: why do we return 1 for namespace nodes?
328*7c568831SAndroid Build Coastguard Worker */
329*7c568831SAndroid Build Coastguard Worker return(1);
330*7c568831SAndroid Build Coastguard Worker default:
331*7c568831SAndroid Build Coastguard Worker break;
332*7c568831SAndroid Build Coastguard Worker }
333*7c568831SAndroid Build Coastguard Worker switch (node2->type) {
334*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
335*7c568831SAndroid Build Coastguard Worker break;
336*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE:
337*7c568831SAndroid Build Coastguard Worker precedence2 = 1; /* element is owner */
338*7c568831SAndroid Build Coastguard Worker miscNode2 = node2;
339*7c568831SAndroid Build Coastguard Worker node2 = node2->parent;
340*7c568831SAndroid Build Coastguard Worker misc = 1;
341*7c568831SAndroid Build Coastguard Worker break;
342*7c568831SAndroid Build Coastguard Worker case XML_TEXT_NODE:
343*7c568831SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
344*7c568831SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
345*7c568831SAndroid Build Coastguard Worker case XML_PI_NODE: {
346*7c568831SAndroid Build Coastguard Worker miscNode2 = node2;
347*7c568831SAndroid Build Coastguard Worker if (node2->prev != NULL) {
348*7c568831SAndroid Build Coastguard Worker do {
349*7c568831SAndroid Build Coastguard Worker node2 = node2->prev;
350*7c568831SAndroid Build Coastguard Worker if (node2->type == XML_ELEMENT_NODE) {
351*7c568831SAndroid Build Coastguard Worker precedence2 = 3; /* element in prev-sibl axis */
352*7c568831SAndroid Build Coastguard Worker break;
353*7c568831SAndroid Build Coastguard Worker }
354*7c568831SAndroid Build Coastguard Worker if (node2->prev == NULL) {
355*7c568831SAndroid Build Coastguard Worker precedence2 = 2; /* element is parent */
356*7c568831SAndroid Build Coastguard Worker node2 = node2->parent;
357*7c568831SAndroid Build Coastguard Worker break;
358*7c568831SAndroid Build Coastguard Worker }
359*7c568831SAndroid Build Coastguard Worker } while (1);
360*7c568831SAndroid Build Coastguard Worker } else {
361*7c568831SAndroid Build Coastguard Worker precedence2 = 2; /* element is parent */
362*7c568831SAndroid Build Coastguard Worker node2 = node2->parent;
363*7c568831SAndroid Build Coastguard Worker }
364*7c568831SAndroid Build Coastguard Worker if ((node2 == NULL) || (node2->type != XML_ELEMENT_NODE) ||
365*7c568831SAndroid Build Coastguard Worker (0 <= (ptrdiff_t) node2->content))
366*7c568831SAndroid Build Coastguard Worker {
367*7c568831SAndroid Build Coastguard Worker node2 = miscNode2;
368*7c568831SAndroid Build Coastguard Worker precedence2 = 0;
369*7c568831SAndroid Build Coastguard Worker } else
370*7c568831SAndroid Build Coastguard Worker misc = 1;
371*7c568831SAndroid Build Coastguard Worker }
372*7c568831SAndroid Build Coastguard Worker break;
373*7c568831SAndroid Build Coastguard Worker case XML_NAMESPACE_DECL:
374*7c568831SAndroid Build Coastguard Worker return(1);
375*7c568831SAndroid Build Coastguard Worker default:
376*7c568831SAndroid Build Coastguard Worker break;
377*7c568831SAndroid Build Coastguard Worker }
378*7c568831SAndroid Build Coastguard Worker if (misc) {
379*7c568831SAndroid Build Coastguard Worker if (node1 == node2) {
380*7c568831SAndroid Build Coastguard Worker if (precedence1 == precedence2) {
381*7c568831SAndroid Build Coastguard Worker /*
382*7c568831SAndroid Build Coastguard Worker * The ugly case; but normally there aren't many
383*7c568831SAndroid Build Coastguard Worker * adjacent non-element nodes around.
384*7c568831SAndroid Build Coastguard Worker */
385*7c568831SAndroid Build Coastguard Worker cur = miscNode2->prev;
386*7c568831SAndroid Build Coastguard Worker while (cur != NULL) {
387*7c568831SAndroid Build Coastguard Worker if (cur == miscNode1)
388*7c568831SAndroid Build Coastguard Worker return(1);
389*7c568831SAndroid Build Coastguard Worker if (cur->type == XML_ELEMENT_NODE)
390*7c568831SAndroid Build Coastguard Worker return(-1);
391*7c568831SAndroid Build Coastguard Worker cur = cur->prev;
392*7c568831SAndroid Build Coastguard Worker }
393*7c568831SAndroid Build Coastguard Worker return (-1);
394*7c568831SAndroid Build Coastguard Worker } else {
395*7c568831SAndroid Build Coastguard Worker /*
396*7c568831SAndroid Build Coastguard Worker * Evaluate based on higher precedence wrt to the element.
397*7c568831SAndroid Build Coastguard Worker * TODO: This assumes attributes are sorted before content.
398*7c568831SAndroid Build Coastguard Worker * Is this 100% correct?
399*7c568831SAndroid Build Coastguard Worker */
400*7c568831SAndroid Build Coastguard Worker if (precedence1 < precedence2)
401*7c568831SAndroid Build Coastguard Worker return(1);
402*7c568831SAndroid Build Coastguard Worker else
403*7c568831SAndroid Build Coastguard Worker return(-1);
404*7c568831SAndroid Build Coastguard Worker }
405*7c568831SAndroid Build Coastguard Worker }
406*7c568831SAndroid Build Coastguard Worker /*
407*7c568831SAndroid Build Coastguard Worker * Special case: One of the helper-elements is contained by the other.
408*7c568831SAndroid Build Coastguard Worker * <foo>
409*7c568831SAndroid Build Coastguard Worker * <node2>
410*7c568831SAndroid Build Coastguard Worker * <node1>Text-1(precedence1 == 2)</node1>
411*7c568831SAndroid Build Coastguard Worker * </node2>
412*7c568831SAndroid Build Coastguard Worker * Text-6(precedence2 == 3)
413*7c568831SAndroid Build Coastguard Worker * </foo>
414*7c568831SAndroid Build Coastguard Worker */
415*7c568831SAndroid Build Coastguard Worker if ((precedence2 == 3) && (precedence1 > 1)) {
416*7c568831SAndroid Build Coastguard Worker cur = node1->parent;
417*7c568831SAndroid Build Coastguard Worker while (cur) {
418*7c568831SAndroid Build Coastguard Worker if (cur == node2)
419*7c568831SAndroid Build Coastguard Worker return(1);
420*7c568831SAndroid Build Coastguard Worker cur = cur->parent;
421*7c568831SAndroid Build Coastguard Worker }
422*7c568831SAndroid Build Coastguard Worker }
423*7c568831SAndroid Build Coastguard Worker if ((precedence1 == 3) && (precedence2 > 1)) {
424*7c568831SAndroid Build Coastguard Worker cur = node2->parent;
425*7c568831SAndroid Build Coastguard Worker while (cur) {
426*7c568831SAndroid Build Coastguard Worker if (cur == node1)
427*7c568831SAndroid Build Coastguard Worker return(-1);
428*7c568831SAndroid Build Coastguard Worker cur = cur->parent;
429*7c568831SAndroid Build Coastguard Worker }
430*7c568831SAndroid Build Coastguard Worker }
431*7c568831SAndroid Build Coastguard Worker }
432*7c568831SAndroid Build Coastguard Worker
433*7c568831SAndroid Build Coastguard Worker /*
434*7c568831SAndroid Build Coastguard Worker * Speedup using document order if available.
435*7c568831SAndroid Build Coastguard Worker */
436*7c568831SAndroid Build Coastguard Worker if ((node1->type == XML_ELEMENT_NODE) &&
437*7c568831SAndroid Build Coastguard Worker (node2->type == XML_ELEMENT_NODE) &&
438*7c568831SAndroid Build Coastguard Worker (0 > (ptrdiff_t) node1->content) &&
439*7c568831SAndroid Build Coastguard Worker (0 > (ptrdiff_t) node2->content) &&
440*7c568831SAndroid Build Coastguard Worker (node1->doc == node2->doc)) {
441*7c568831SAndroid Build Coastguard Worker
442*7c568831SAndroid Build Coastguard Worker l1 = -((ptrdiff_t) node1->content);
443*7c568831SAndroid Build Coastguard Worker l2 = -((ptrdiff_t) node2->content);
444*7c568831SAndroid Build Coastguard Worker if (l1 < l2)
445*7c568831SAndroid Build Coastguard Worker return(1);
446*7c568831SAndroid Build Coastguard Worker if (l1 > l2)
447*7c568831SAndroid Build Coastguard Worker return(-1);
448*7c568831SAndroid Build Coastguard Worker }
449*7c568831SAndroid Build Coastguard Worker
450*7c568831SAndroid Build Coastguard Worker turtle_comparison:
451*7c568831SAndroid Build Coastguard Worker
452*7c568831SAndroid Build Coastguard Worker if (node1 == node2->prev)
453*7c568831SAndroid Build Coastguard Worker return(1);
454*7c568831SAndroid Build Coastguard Worker if (node1 == node2->next)
455*7c568831SAndroid Build Coastguard Worker return(-1);
456*7c568831SAndroid Build Coastguard Worker /*
457*7c568831SAndroid Build Coastguard Worker * compute depth to root
458*7c568831SAndroid Build Coastguard Worker */
459*7c568831SAndroid Build Coastguard Worker for (depth2 = 0, cur = node2; cur->parent != NULL; cur = cur->parent) {
460*7c568831SAndroid Build Coastguard Worker if (cur->parent == node1)
461*7c568831SAndroid Build Coastguard Worker return(1);
462*7c568831SAndroid Build Coastguard Worker depth2++;
463*7c568831SAndroid Build Coastguard Worker }
464*7c568831SAndroid Build Coastguard Worker root = cur;
465*7c568831SAndroid Build Coastguard Worker for (depth1 = 0, cur = node1; cur->parent != NULL; cur = cur->parent) {
466*7c568831SAndroid Build Coastguard Worker if (cur->parent == node2)
467*7c568831SAndroid Build Coastguard Worker return(-1);
468*7c568831SAndroid Build Coastguard Worker depth1++;
469*7c568831SAndroid Build Coastguard Worker }
470*7c568831SAndroid Build Coastguard Worker /*
471*7c568831SAndroid Build Coastguard Worker * Distinct document (or distinct entities :-( ) case.
472*7c568831SAndroid Build Coastguard Worker */
473*7c568831SAndroid Build Coastguard Worker if (root != cur) {
474*7c568831SAndroid Build Coastguard Worker return(-2);
475*7c568831SAndroid Build Coastguard Worker }
476*7c568831SAndroid Build Coastguard Worker /*
477*7c568831SAndroid Build Coastguard Worker * get the nearest common ancestor.
478*7c568831SAndroid Build Coastguard Worker */
479*7c568831SAndroid Build Coastguard Worker while (depth1 > depth2) {
480*7c568831SAndroid Build Coastguard Worker depth1--;
481*7c568831SAndroid Build Coastguard Worker node1 = node1->parent;
482*7c568831SAndroid Build Coastguard Worker }
483*7c568831SAndroid Build Coastguard Worker while (depth2 > depth1) {
484*7c568831SAndroid Build Coastguard Worker depth2--;
485*7c568831SAndroid Build Coastguard Worker node2 = node2->parent;
486*7c568831SAndroid Build Coastguard Worker }
487*7c568831SAndroid Build Coastguard Worker while (node1->parent != node2->parent) {
488*7c568831SAndroid Build Coastguard Worker node1 = node1->parent;
489*7c568831SAndroid Build Coastguard Worker node2 = node2->parent;
490*7c568831SAndroid Build Coastguard Worker /* should not happen but just in case ... */
491*7c568831SAndroid Build Coastguard Worker if ((node1 == NULL) || (node2 == NULL))
492*7c568831SAndroid Build Coastguard Worker return(-2);
493*7c568831SAndroid Build Coastguard Worker }
494*7c568831SAndroid Build Coastguard Worker /*
495*7c568831SAndroid Build Coastguard Worker * Find who's first.
496*7c568831SAndroid Build Coastguard Worker */
497*7c568831SAndroid Build Coastguard Worker if (node1 == node2->prev)
498*7c568831SAndroid Build Coastguard Worker return(1);
499*7c568831SAndroid Build Coastguard Worker if (node1 == node2->next)
500*7c568831SAndroid Build Coastguard Worker return(-1);
501*7c568831SAndroid Build Coastguard Worker /*
502*7c568831SAndroid Build Coastguard Worker * Speedup using document order if available.
503*7c568831SAndroid Build Coastguard Worker */
504*7c568831SAndroid Build Coastguard Worker if ((node1->type == XML_ELEMENT_NODE) &&
505*7c568831SAndroid Build Coastguard Worker (node2->type == XML_ELEMENT_NODE) &&
506*7c568831SAndroid Build Coastguard Worker (0 > (ptrdiff_t) node1->content) &&
507*7c568831SAndroid Build Coastguard Worker (0 > (ptrdiff_t) node2->content) &&
508*7c568831SAndroid Build Coastguard Worker (node1->doc == node2->doc)) {
509*7c568831SAndroid Build Coastguard Worker
510*7c568831SAndroid Build Coastguard Worker l1 = -((ptrdiff_t) node1->content);
511*7c568831SAndroid Build Coastguard Worker l2 = -((ptrdiff_t) node2->content);
512*7c568831SAndroid Build Coastguard Worker if (l1 < l2)
513*7c568831SAndroid Build Coastguard Worker return(1);
514*7c568831SAndroid Build Coastguard Worker if (l1 > l2)
515*7c568831SAndroid Build Coastguard Worker return(-1);
516*7c568831SAndroid Build Coastguard Worker }
517*7c568831SAndroid Build Coastguard Worker
518*7c568831SAndroid Build Coastguard Worker for (cur = node1->next;cur != NULL;cur = cur->next)
519*7c568831SAndroid Build Coastguard Worker if (cur == node2)
520*7c568831SAndroid Build Coastguard Worker return(1);
521*7c568831SAndroid Build Coastguard Worker return(-1); /* assume there is no sibling list corruption */
522*7c568831SAndroid Build Coastguard Worker }
523*7c568831SAndroid Build Coastguard Worker #endif /* XP_OPTIMIZED_NON_ELEM_COMPARISON */
524*7c568831SAndroid Build Coastguard Worker
525*7c568831SAndroid Build Coastguard Worker /*
526*7c568831SAndroid Build Coastguard Worker * Wrapper for the Timsort algorithm from timsort.h
527*7c568831SAndroid Build Coastguard Worker */
528*7c568831SAndroid Build Coastguard Worker #ifdef WITH_TIM_SORT
529*7c568831SAndroid Build Coastguard Worker #define SORT_NAME libxml_domnode
530*7c568831SAndroid Build Coastguard Worker #define SORT_TYPE xmlNodePtr
531*7c568831SAndroid Build Coastguard Worker /**
532*7c568831SAndroid Build Coastguard Worker * wrap_cmp:
533*7c568831SAndroid Build Coastguard Worker * @x: a node
534*7c568831SAndroid Build Coastguard Worker * @y: another node
535*7c568831SAndroid Build Coastguard Worker *
536*7c568831SAndroid Build Coastguard Worker * Comparison function for the Timsort implementation
537*7c568831SAndroid Build Coastguard Worker *
538*7c568831SAndroid Build Coastguard Worker * Returns -2 in case of error -1 if first point < second point, 0 if
539*7c568831SAndroid Build Coastguard Worker * it's the same node, +1 otherwise
540*7c568831SAndroid Build Coastguard Worker */
541*7c568831SAndroid Build Coastguard Worker static
542*7c568831SAndroid Build Coastguard Worker int wrap_cmp( xmlNodePtr x, xmlNodePtr y );
543*7c568831SAndroid Build Coastguard Worker #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
wrap_cmp(xmlNodePtr x,xmlNodePtr y)544*7c568831SAndroid Build Coastguard Worker static int wrap_cmp( xmlNodePtr x, xmlNodePtr y )
545*7c568831SAndroid Build Coastguard Worker {
546*7c568831SAndroid Build Coastguard Worker int res = xmlXPathCmpNodesExt(x, y);
547*7c568831SAndroid Build Coastguard Worker return res == -2 ? res : -res;
548*7c568831SAndroid Build Coastguard Worker }
549*7c568831SAndroid Build Coastguard Worker #else
wrap_cmp(xmlNodePtr x,xmlNodePtr y)550*7c568831SAndroid Build Coastguard Worker static int wrap_cmp( xmlNodePtr x, xmlNodePtr y )
551*7c568831SAndroid Build Coastguard Worker {
552*7c568831SAndroid Build Coastguard Worker int res = xmlXPathCmpNodes(x, y);
553*7c568831SAndroid Build Coastguard Worker return res == -2 ? res : -res;
554*7c568831SAndroid Build Coastguard Worker }
555*7c568831SAndroid Build Coastguard Worker #endif
556*7c568831SAndroid Build Coastguard Worker #define SORT_CMP(x, y) (wrap_cmp(x, y))
557*7c568831SAndroid Build Coastguard Worker #include "timsort.h"
558*7c568831SAndroid Build Coastguard Worker #endif /* WITH_TIM_SORT */
559*7c568831SAndroid Build Coastguard Worker
560*7c568831SAndroid Build Coastguard Worker /************************************************************************
561*7c568831SAndroid Build Coastguard Worker * *
562*7c568831SAndroid Build Coastguard Worker * Error handling routines *
563*7c568831SAndroid Build Coastguard Worker * *
564*7c568831SAndroid Build Coastguard Worker ************************************************************************/
565*7c568831SAndroid Build Coastguard Worker
566*7c568831SAndroid Build Coastguard Worker /**
567*7c568831SAndroid Build Coastguard Worker * XP_ERRORNULL:
568*7c568831SAndroid Build Coastguard Worker * @X: the error code
569*7c568831SAndroid Build Coastguard Worker *
570*7c568831SAndroid Build Coastguard Worker * Macro to raise an XPath error and return NULL.
571*7c568831SAndroid Build Coastguard Worker */
572*7c568831SAndroid Build Coastguard Worker #define XP_ERRORNULL(X) \
573*7c568831SAndroid Build Coastguard Worker { xmlXPathErr(ctxt, X); return(NULL); }
574*7c568831SAndroid Build Coastguard Worker
575*7c568831SAndroid Build Coastguard Worker /*
576*7c568831SAndroid Build Coastguard Worker * The array xmlXPathErrorMessages corresponds to the enum xmlXPathError
577*7c568831SAndroid Build Coastguard Worker */
578*7c568831SAndroid Build Coastguard Worker static const char* const xmlXPathErrorMessages[] = {
579*7c568831SAndroid Build Coastguard Worker "Ok\n",
580*7c568831SAndroid Build Coastguard Worker "Number encoding\n",
581*7c568831SAndroid Build Coastguard Worker "Unfinished literal\n",
582*7c568831SAndroid Build Coastguard Worker "Start of literal\n",
583*7c568831SAndroid Build Coastguard Worker "Expected $ for variable reference\n",
584*7c568831SAndroid Build Coastguard Worker "Undefined variable\n",
585*7c568831SAndroid Build Coastguard Worker "Invalid predicate\n",
586*7c568831SAndroid Build Coastguard Worker "Invalid expression\n",
587*7c568831SAndroid Build Coastguard Worker "Missing closing curly brace\n",
588*7c568831SAndroid Build Coastguard Worker "Unregistered function\n",
589*7c568831SAndroid Build Coastguard Worker "Invalid operand\n",
590*7c568831SAndroid Build Coastguard Worker "Invalid type\n",
591*7c568831SAndroid Build Coastguard Worker "Invalid number of arguments\n",
592*7c568831SAndroid Build Coastguard Worker "Invalid context size\n",
593*7c568831SAndroid Build Coastguard Worker "Invalid context position\n",
594*7c568831SAndroid Build Coastguard Worker "Memory allocation error\n",
595*7c568831SAndroid Build Coastguard Worker "Syntax error\n",
596*7c568831SAndroid Build Coastguard Worker "Resource error\n",
597*7c568831SAndroid Build Coastguard Worker "Sub resource error\n",
598*7c568831SAndroid Build Coastguard Worker "Undefined namespace prefix\n",
599*7c568831SAndroid Build Coastguard Worker "Encoding error\n",
600*7c568831SAndroid Build Coastguard Worker "Char out of XML range\n",
601*7c568831SAndroid Build Coastguard Worker "Invalid or incomplete context\n",
602*7c568831SAndroid Build Coastguard Worker "Stack usage error\n",
603*7c568831SAndroid Build Coastguard Worker "Forbidden variable\n",
604*7c568831SAndroid Build Coastguard Worker "Operation limit exceeded\n",
605*7c568831SAndroid Build Coastguard Worker "Recursion limit exceeded\n",
606*7c568831SAndroid Build Coastguard Worker "?? Unknown error ??\n" /* Must be last in the list! */
607*7c568831SAndroid Build Coastguard Worker };
608*7c568831SAndroid Build Coastguard Worker #define MAXERRNO ((int)(sizeof(xmlXPathErrorMessages) / \
609*7c568831SAndroid Build Coastguard Worker sizeof(xmlXPathErrorMessages[0])) - 1)
610*7c568831SAndroid Build Coastguard Worker /**
611*7c568831SAndroid Build Coastguard Worker * xmlXPathErrMemory:
612*7c568831SAndroid Build Coastguard Worker * @ctxt: an XPath context
613*7c568831SAndroid Build Coastguard Worker *
614*7c568831SAndroid Build Coastguard Worker * Handle a memory allocation failure.
615*7c568831SAndroid Build Coastguard Worker */
616*7c568831SAndroid Build Coastguard Worker void
xmlXPathErrMemory(xmlXPathContextPtr ctxt)617*7c568831SAndroid Build Coastguard Worker xmlXPathErrMemory(xmlXPathContextPtr ctxt)
618*7c568831SAndroid Build Coastguard Worker {
619*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
620*7c568831SAndroid Build Coastguard Worker return;
621*7c568831SAndroid Build Coastguard Worker xmlRaiseMemoryError(ctxt->error, NULL, ctxt->userData, XML_FROM_XPATH,
622*7c568831SAndroid Build Coastguard Worker &ctxt->lastError);
623*7c568831SAndroid Build Coastguard Worker }
624*7c568831SAndroid Build Coastguard Worker
625*7c568831SAndroid Build Coastguard Worker /**
626*7c568831SAndroid Build Coastguard Worker * xmlXPathPErrMemory:
627*7c568831SAndroid Build Coastguard Worker * @ctxt: an XPath parser context
628*7c568831SAndroid Build Coastguard Worker *
629*7c568831SAndroid Build Coastguard Worker * Handle a memory allocation failure.
630*7c568831SAndroid Build Coastguard Worker */
631*7c568831SAndroid Build Coastguard Worker void
xmlXPathPErrMemory(xmlXPathParserContextPtr ctxt)632*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(xmlXPathParserContextPtr ctxt)
633*7c568831SAndroid Build Coastguard Worker {
634*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
635*7c568831SAndroid Build Coastguard Worker return;
636*7c568831SAndroid Build Coastguard Worker ctxt->error = XPATH_MEMORY_ERROR;
637*7c568831SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt->context);
638*7c568831SAndroid Build Coastguard Worker }
639*7c568831SAndroid Build Coastguard Worker
640*7c568831SAndroid Build Coastguard Worker /**
641*7c568831SAndroid Build Coastguard Worker * xmlXPathErr:
642*7c568831SAndroid Build Coastguard Worker * @ctxt: a XPath parser context
643*7c568831SAndroid Build Coastguard Worker * @code: the error code
644*7c568831SAndroid Build Coastguard Worker *
645*7c568831SAndroid Build Coastguard Worker * Handle an XPath error
646*7c568831SAndroid Build Coastguard Worker */
647*7c568831SAndroid Build Coastguard Worker void
xmlXPathErr(xmlXPathParserContextPtr ctxt,int code)648*7c568831SAndroid Build Coastguard Worker xmlXPathErr(xmlXPathParserContextPtr ctxt, int code)
649*7c568831SAndroid Build Coastguard Worker {
650*7c568831SAndroid Build Coastguard Worker xmlStructuredErrorFunc schannel = NULL;
651*7c568831SAndroid Build Coastguard Worker xmlGenericErrorFunc channel = NULL;
652*7c568831SAndroid Build Coastguard Worker void *data = NULL;
653*7c568831SAndroid Build Coastguard Worker xmlNodePtr node = NULL;
654*7c568831SAndroid Build Coastguard Worker int res;
655*7c568831SAndroid Build Coastguard Worker
656*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
657*7c568831SAndroid Build Coastguard Worker return;
658*7c568831SAndroid Build Coastguard Worker if ((code < 0) || (code > MAXERRNO))
659*7c568831SAndroid Build Coastguard Worker code = MAXERRNO;
660*7c568831SAndroid Build Coastguard Worker /* Only report the first error */
661*7c568831SAndroid Build Coastguard Worker if (ctxt->error != 0)
662*7c568831SAndroid Build Coastguard Worker return;
663*7c568831SAndroid Build Coastguard Worker
664*7c568831SAndroid Build Coastguard Worker ctxt->error = code;
665*7c568831SAndroid Build Coastguard Worker
666*7c568831SAndroid Build Coastguard Worker if (ctxt->context != NULL) {
667*7c568831SAndroid Build Coastguard Worker xmlErrorPtr err = &ctxt->context->lastError;
668*7c568831SAndroid Build Coastguard Worker
669*7c568831SAndroid Build Coastguard Worker /* Don't overwrite memory error. */
670*7c568831SAndroid Build Coastguard Worker if (err->code == XML_ERR_NO_MEMORY)
671*7c568831SAndroid Build Coastguard Worker return;
672*7c568831SAndroid Build Coastguard Worker
673*7c568831SAndroid Build Coastguard Worker /* cleanup current last error */
674*7c568831SAndroid Build Coastguard Worker xmlResetError(err);
675*7c568831SAndroid Build Coastguard Worker
676*7c568831SAndroid Build Coastguard Worker err->domain = XML_FROM_XPATH;
677*7c568831SAndroid Build Coastguard Worker err->code = code + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK;
678*7c568831SAndroid Build Coastguard Worker err->level = XML_ERR_ERROR;
679*7c568831SAndroid Build Coastguard Worker if (ctxt->base != NULL) {
680*7c568831SAndroid Build Coastguard Worker err->str1 = (char *) xmlStrdup(ctxt->base);
681*7c568831SAndroid Build Coastguard Worker if (err->str1 == NULL) {
682*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
683*7c568831SAndroid Build Coastguard Worker return;
684*7c568831SAndroid Build Coastguard Worker }
685*7c568831SAndroid Build Coastguard Worker }
686*7c568831SAndroid Build Coastguard Worker err->int1 = ctxt->cur - ctxt->base;
687*7c568831SAndroid Build Coastguard Worker err->node = ctxt->context->debugNode;
688*7c568831SAndroid Build Coastguard Worker
689*7c568831SAndroid Build Coastguard Worker schannel = ctxt->context->error;
690*7c568831SAndroid Build Coastguard Worker data = ctxt->context->userData;
691*7c568831SAndroid Build Coastguard Worker node = ctxt->context->debugNode;
692*7c568831SAndroid Build Coastguard Worker }
693*7c568831SAndroid Build Coastguard Worker
694*7c568831SAndroid Build Coastguard Worker if (schannel == NULL) {
695*7c568831SAndroid Build Coastguard Worker channel = xmlGenericError;
696*7c568831SAndroid Build Coastguard Worker data = xmlGenericErrorContext;
697*7c568831SAndroid Build Coastguard Worker }
698*7c568831SAndroid Build Coastguard Worker
699*7c568831SAndroid Build Coastguard Worker res = xmlRaiseError(schannel, channel, data, NULL, node, XML_FROM_XPATH,
700*7c568831SAndroid Build Coastguard Worker code + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK,
701*7c568831SAndroid Build Coastguard Worker XML_ERR_ERROR, NULL, 0,
702*7c568831SAndroid Build Coastguard Worker (const char *) ctxt->base, NULL, NULL,
703*7c568831SAndroid Build Coastguard Worker ctxt->cur - ctxt->base, 0,
704*7c568831SAndroid Build Coastguard Worker "%s", xmlXPathErrorMessages[code]);
705*7c568831SAndroid Build Coastguard Worker if (res < 0)
706*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
707*7c568831SAndroid Build Coastguard Worker }
708*7c568831SAndroid Build Coastguard Worker
709*7c568831SAndroid Build Coastguard Worker /**
710*7c568831SAndroid Build Coastguard Worker * xmlXPatherror:
711*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
712*7c568831SAndroid Build Coastguard Worker * @file: the file name
713*7c568831SAndroid Build Coastguard Worker * @line: the line number
714*7c568831SAndroid Build Coastguard Worker * @no: the error number
715*7c568831SAndroid Build Coastguard Worker *
716*7c568831SAndroid Build Coastguard Worker * Formats an error message.
717*7c568831SAndroid Build Coastguard Worker */
718*7c568831SAndroid Build Coastguard Worker void
xmlXPatherror(xmlXPathParserContextPtr ctxt,const char * file ATTRIBUTE_UNUSED,int line ATTRIBUTE_UNUSED,int no)719*7c568831SAndroid Build Coastguard Worker xmlXPatherror(xmlXPathParserContextPtr ctxt, const char *file ATTRIBUTE_UNUSED,
720*7c568831SAndroid Build Coastguard Worker int line ATTRIBUTE_UNUSED, int no) {
721*7c568831SAndroid Build Coastguard Worker xmlXPathErr(ctxt, no);
722*7c568831SAndroid Build Coastguard Worker }
723*7c568831SAndroid Build Coastguard Worker
724*7c568831SAndroid Build Coastguard Worker /**
725*7c568831SAndroid Build Coastguard Worker * xmlXPathCheckOpLimit:
726*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
727*7c568831SAndroid Build Coastguard Worker * @opCount: the number of operations to be added
728*7c568831SAndroid Build Coastguard Worker *
729*7c568831SAndroid Build Coastguard Worker * Adds opCount to the running total of operations and returns -1 if the
730*7c568831SAndroid Build Coastguard Worker * operation limit is exceeded. Returns 0 otherwise.
731*7c568831SAndroid Build Coastguard Worker */
732*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCheckOpLimit(xmlXPathParserContextPtr ctxt,unsigned long opCount)733*7c568831SAndroid Build Coastguard Worker xmlXPathCheckOpLimit(xmlXPathParserContextPtr ctxt, unsigned long opCount) {
734*7c568831SAndroid Build Coastguard Worker xmlXPathContextPtr xpctxt = ctxt->context;
735*7c568831SAndroid Build Coastguard Worker
736*7c568831SAndroid Build Coastguard Worker if ((opCount > xpctxt->opLimit) ||
737*7c568831SAndroid Build Coastguard Worker (xpctxt->opCount > xpctxt->opLimit - opCount)) {
738*7c568831SAndroid Build Coastguard Worker xpctxt->opCount = xpctxt->opLimit;
739*7c568831SAndroid Build Coastguard Worker xmlXPathErr(ctxt, XPATH_OP_LIMIT_EXCEEDED);
740*7c568831SAndroid Build Coastguard Worker return(-1);
741*7c568831SAndroid Build Coastguard Worker }
742*7c568831SAndroid Build Coastguard Worker
743*7c568831SAndroid Build Coastguard Worker xpctxt->opCount += opCount;
744*7c568831SAndroid Build Coastguard Worker return(0);
745*7c568831SAndroid Build Coastguard Worker }
746*7c568831SAndroid Build Coastguard Worker
747*7c568831SAndroid Build Coastguard Worker #define OP_LIMIT_EXCEEDED(ctxt, n) \
748*7c568831SAndroid Build Coastguard Worker ((ctxt->context->opLimit != 0) && (xmlXPathCheckOpLimit(ctxt, n) < 0))
749*7c568831SAndroid Build Coastguard Worker
750*7c568831SAndroid Build Coastguard Worker /************************************************************************
751*7c568831SAndroid Build Coastguard Worker * *
752*7c568831SAndroid Build Coastguard Worker * Parser Types *
753*7c568831SAndroid Build Coastguard Worker * *
754*7c568831SAndroid Build Coastguard Worker ************************************************************************/
755*7c568831SAndroid Build Coastguard Worker
756*7c568831SAndroid Build Coastguard Worker /*
757*7c568831SAndroid Build Coastguard Worker * Types are private:
758*7c568831SAndroid Build Coastguard Worker */
759*7c568831SAndroid Build Coastguard Worker
760*7c568831SAndroid Build Coastguard Worker typedef enum {
761*7c568831SAndroid Build Coastguard Worker XPATH_OP_END=0,
762*7c568831SAndroid Build Coastguard Worker XPATH_OP_AND,
763*7c568831SAndroid Build Coastguard Worker XPATH_OP_OR,
764*7c568831SAndroid Build Coastguard Worker XPATH_OP_EQUAL,
765*7c568831SAndroid Build Coastguard Worker XPATH_OP_CMP,
766*7c568831SAndroid Build Coastguard Worker XPATH_OP_PLUS,
767*7c568831SAndroid Build Coastguard Worker XPATH_OP_MULT,
768*7c568831SAndroid Build Coastguard Worker XPATH_OP_UNION,
769*7c568831SAndroid Build Coastguard Worker XPATH_OP_ROOT,
770*7c568831SAndroid Build Coastguard Worker XPATH_OP_NODE,
771*7c568831SAndroid Build Coastguard Worker XPATH_OP_COLLECT,
772*7c568831SAndroid Build Coastguard Worker XPATH_OP_VALUE, /* 11 */
773*7c568831SAndroid Build Coastguard Worker XPATH_OP_VARIABLE,
774*7c568831SAndroid Build Coastguard Worker XPATH_OP_FUNCTION,
775*7c568831SAndroid Build Coastguard Worker XPATH_OP_ARG,
776*7c568831SAndroid Build Coastguard Worker XPATH_OP_PREDICATE,
777*7c568831SAndroid Build Coastguard Worker XPATH_OP_FILTER, /* 16 */
778*7c568831SAndroid Build Coastguard Worker XPATH_OP_SORT /* 17 */
779*7c568831SAndroid Build Coastguard Worker } xmlXPathOp;
780*7c568831SAndroid Build Coastguard Worker
781*7c568831SAndroid Build Coastguard Worker typedef enum {
782*7c568831SAndroid Build Coastguard Worker AXIS_ANCESTOR = 1,
783*7c568831SAndroid Build Coastguard Worker AXIS_ANCESTOR_OR_SELF,
784*7c568831SAndroid Build Coastguard Worker AXIS_ATTRIBUTE,
785*7c568831SAndroid Build Coastguard Worker AXIS_CHILD,
786*7c568831SAndroid Build Coastguard Worker AXIS_DESCENDANT,
787*7c568831SAndroid Build Coastguard Worker AXIS_DESCENDANT_OR_SELF,
788*7c568831SAndroid Build Coastguard Worker AXIS_FOLLOWING,
789*7c568831SAndroid Build Coastguard Worker AXIS_FOLLOWING_SIBLING,
790*7c568831SAndroid Build Coastguard Worker AXIS_NAMESPACE,
791*7c568831SAndroid Build Coastguard Worker AXIS_PARENT,
792*7c568831SAndroid Build Coastguard Worker AXIS_PRECEDING,
793*7c568831SAndroid Build Coastguard Worker AXIS_PRECEDING_SIBLING,
794*7c568831SAndroid Build Coastguard Worker AXIS_SELF
795*7c568831SAndroid Build Coastguard Worker } xmlXPathAxisVal;
796*7c568831SAndroid Build Coastguard Worker
797*7c568831SAndroid Build Coastguard Worker typedef enum {
798*7c568831SAndroid Build Coastguard Worker NODE_TEST_NONE = 0,
799*7c568831SAndroid Build Coastguard Worker NODE_TEST_TYPE = 1,
800*7c568831SAndroid Build Coastguard Worker NODE_TEST_PI = 2,
801*7c568831SAndroid Build Coastguard Worker NODE_TEST_ALL = 3,
802*7c568831SAndroid Build Coastguard Worker NODE_TEST_NS = 4,
803*7c568831SAndroid Build Coastguard Worker NODE_TEST_NAME = 5
804*7c568831SAndroid Build Coastguard Worker } xmlXPathTestVal;
805*7c568831SAndroid Build Coastguard Worker
806*7c568831SAndroid Build Coastguard Worker typedef enum {
807*7c568831SAndroid Build Coastguard Worker NODE_TYPE_NODE = 0,
808*7c568831SAndroid Build Coastguard Worker NODE_TYPE_COMMENT = XML_COMMENT_NODE,
809*7c568831SAndroid Build Coastguard Worker NODE_TYPE_TEXT = XML_TEXT_NODE,
810*7c568831SAndroid Build Coastguard Worker NODE_TYPE_PI = XML_PI_NODE
811*7c568831SAndroid Build Coastguard Worker } xmlXPathTypeVal;
812*7c568831SAndroid Build Coastguard Worker
813*7c568831SAndroid Build Coastguard Worker typedef struct _xmlXPathStepOp xmlXPathStepOp;
814*7c568831SAndroid Build Coastguard Worker typedef xmlXPathStepOp *xmlXPathStepOpPtr;
815*7c568831SAndroid Build Coastguard Worker struct _xmlXPathStepOp {
816*7c568831SAndroid Build Coastguard Worker xmlXPathOp op; /* The identifier of the operation */
817*7c568831SAndroid Build Coastguard Worker int ch1; /* First child */
818*7c568831SAndroid Build Coastguard Worker int ch2; /* Second child */
819*7c568831SAndroid Build Coastguard Worker int value;
820*7c568831SAndroid Build Coastguard Worker int value2;
821*7c568831SAndroid Build Coastguard Worker int value3;
822*7c568831SAndroid Build Coastguard Worker void *value4;
823*7c568831SAndroid Build Coastguard Worker void *value5;
824*7c568831SAndroid Build Coastguard Worker xmlXPathFunction cache;
825*7c568831SAndroid Build Coastguard Worker void *cacheURI;
826*7c568831SAndroid Build Coastguard Worker };
827*7c568831SAndroid Build Coastguard Worker
828*7c568831SAndroid Build Coastguard Worker struct _xmlXPathCompExpr {
829*7c568831SAndroid Build Coastguard Worker int nbStep; /* Number of steps in this expression */
830*7c568831SAndroid Build Coastguard Worker int maxStep; /* Maximum number of steps allocated */
831*7c568831SAndroid Build Coastguard Worker xmlXPathStepOp *steps; /* ops for computation of this expression */
832*7c568831SAndroid Build Coastguard Worker int last; /* index of last step in expression */
833*7c568831SAndroid Build Coastguard Worker xmlChar *expr; /* the expression being computed */
834*7c568831SAndroid Build Coastguard Worker xmlDictPtr dict; /* the dictionary to use if any */
835*7c568831SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
836*7c568831SAndroid Build Coastguard Worker xmlPatternPtr stream;
837*7c568831SAndroid Build Coastguard Worker #endif
838*7c568831SAndroid Build Coastguard Worker };
839*7c568831SAndroid Build Coastguard Worker
840*7c568831SAndroid Build Coastguard Worker /************************************************************************
841*7c568831SAndroid Build Coastguard Worker * *
842*7c568831SAndroid Build Coastguard Worker * Forward declarations *
843*7c568831SAndroid Build Coastguard Worker * *
844*7c568831SAndroid Build Coastguard Worker ************************************************************************/
845*7c568831SAndroid Build Coastguard Worker
846*7c568831SAndroid Build Coastguard Worker static void
847*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj);
848*7c568831SAndroid Build Coastguard Worker static int
849*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt,
850*7c568831SAndroid Build Coastguard Worker xmlXPathStepOpPtr op, xmlNodePtr *first);
851*7c568831SAndroid Build Coastguard Worker static int
852*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalToBoolean(xmlXPathParserContextPtr ctxt,
853*7c568831SAndroid Build Coastguard Worker xmlXPathStepOpPtr op,
854*7c568831SAndroid Build Coastguard Worker int isPredicate);
855*7c568831SAndroid Build Coastguard Worker static void
856*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObjectEntry(void *obj, const xmlChar *name);
857*7c568831SAndroid Build Coastguard Worker
858*7c568831SAndroid Build Coastguard Worker /************************************************************************
859*7c568831SAndroid Build Coastguard Worker * *
860*7c568831SAndroid Build Coastguard Worker * Parser Type functions *
861*7c568831SAndroid Build Coastguard Worker * *
862*7c568831SAndroid Build Coastguard Worker ************************************************************************/
863*7c568831SAndroid Build Coastguard Worker
864*7c568831SAndroid Build Coastguard Worker /**
865*7c568831SAndroid Build Coastguard Worker * xmlXPathNewCompExpr:
866*7c568831SAndroid Build Coastguard Worker *
867*7c568831SAndroid Build Coastguard Worker * Create a new Xpath component
868*7c568831SAndroid Build Coastguard Worker *
869*7c568831SAndroid Build Coastguard Worker * Returns the newly allocated xmlXPathCompExprPtr or NULL in case of error
870*7c568831SAndroid Build Coastguard Worker */
871*7c568831SAndroid Build Coastguard Worker static xmlXPathCompExprPtr
xmlXPathNewCompExpr(void)872*7c568831SAndroid Build Coastguard Worker xmlXPathNewCompExpr(void) {
873*7c568831SAndroid Build Coastguard Worker xmlXPathCompExprPtr cur;
874*7c568831SAndroid Build Coastguard Worker
875*7c568831SAndroid Build Coastguard Worker cur = (xmlXPathCompExprPtr) xmlMalloc(sizeof(xmlXPathCompExpr));
876*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
877*7c568831SAndroid Build Coastguard Worker return(NULL);
878*7c568831SAndroid Build Coastguard Worker memset(cur, 0, sizeof(xmlXPathCompExpr));
879*7c568831SAndroid Build Coastguard Worker cur->maxStep = 10;
880*7c568831SAndroid Build Coastguard Worker cur->nbStep = 0;
881*7c568831SAndroid Build Coastguard Worker cur->steps = (xmlXPathStepOp *) xmlMalloc(cur->maxStep *
882*7c568831SAndroid Build Coastguard Worker sizeof(xmlXPathStepOp));
883*7c568831SAndroid Build Coastguard Worker if (cur->steps == NULL) {
884*7c568831SAndroid Build Coastguard Worker xmlFree(cur);
885*7c568831SAndroid Build Coastguard Worker return(NULL);
886*7c568831SAndroid Build Coastguard Worker }
887*7c568831SAndroid Build Coastguard Worker memset(cur->steps, 0, cur->maxStep * sizeof(xmlXPathStepOp));
888*7c568831SAndroid Build Coastguard Worker cur->last = -1;
889*7c568831SAndroid Build Coastguard Worker return(cur);
890*7c568831SAndroid Build Coastguard Worker }
891*7c568831SAndroid Build Coastguard Worker
892*7c568831SAndroid Build Coastguard Worker /**
893*7c568831SAndroid Build Coastguard Worker * xmlXPathFreeCompExpr:
894*7c568831SAndroid Build Coastguard Worker * @comp: an XPATH comp
895*7c568831SAndroid Build Coastguard Worker *
896*7c568831SAndroid Build Coastguard Worker * Free up the memory allocated by @comp
897*7c568831SAndroid Build Coastguard Worker */
898*7c568831SAndroid Build Coastguard Worker void
xmlXPathFreeCompExpr(xmlXPathCompExprPtr comp)899*7c568831SAndroid Build Coastguard Worker xmlXPathFreeCompExpr(xmlXPathCompExprPtr comp)
900*7c568831SAndroid Build Coastguard Worker {
901*7c568831SAndroid Build Coastguard Worker xmlXPathStepOpPtr op;
902*7c568831SAndroid Build Coastguard Worker int i;
903*7c568831SAndroid Build Coastguard Worker
904*7c568831SAndroid Build Coastguard Worker if (comp == NULL)
905*7c568831SAndroid Build Coastguard Worker return;
906*7c568831SAndroid Build Coastguard Worker if (comp->dict == NULL) {
907*7c568831SAndroid Build Coastguard Worker for (i = 0; i < comp->nbStep; i++) {
908*7c568831SAndroid Build Coastguard Worker op = &comp->steps[i];
909*7c568831SAndroid Build Coastguard Worker if (op->value4 != NULL) {
910*7c568831SAndroid Build Coastguard Worker if (op->op == XPATH_OP_VALUE)
911*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(op->value4);
912*7c568831SAndroid Build Coastguard Worker else
913*7c568831SAndroid Build Coastguard Worker xmlFree(op->value4);
914*7c568831SAndroid Build Coastguard Worker }
915*7c568831SAndroid Build Coastguard Worker if (op->value5 != NULL)
916*7c568831SAndroid Build Coastguard Worker xmlFree(op->value5);
917*7c568831SAndroid Build Coastguard Worker }
918*7c568831SAndroid Build Coastguard Worker } else {
919*7c568831SAndroid Build Coastguard Worker for (i = 0; i < comp->nbStep; i++) {
920*7c568831SAndroid Build Coastguard Worker op = &comp->steps[i];
921*7c568831SAndroid Build Coastguard Worker if (op->value4 != NULL) {
922*7c568831SAndroid Build Coastguard Worker if (op->op == XPATH_OP_VALUE)
923*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(op->value4);
924*7c568831SAndroid Build Coastguard Worker }
925*7c568831SAndroid Build Coastguard Worker }
926*7c568831SAndroid Build Coastguard Worker xmlDictFree(comp->dict);
927*7c568831SAndroid Build Coastguard Worker }
928*7c568831SAndroid Build Coastguard Worker if (comp->steps != NULL) {
929*7c568831SAndroid Build Coastguard Worker xmlFree(comp->steps);
930*7c568831SAndroid Build Coastguard Worker }
931*7c568831SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
932*7c568831SAndroid Build Coastguard Worker if (comp->stream != NULL) {
933*7c568831SAndroid Build Coastguard Worker xmlFreePatternList(comp->stream);
934*7c568831SAndroid Build Coastguard Worker }
935*7c568831SAndroid Build Coastguard Worker #endif
936*7c568831SAndroid Build Coastguard Worker if (comp->expr != NULL) {
937*7c568831SAndroid Build Coastguard Worker xmlFree(comp->expr);
938*7c568831SAndroid Build Coastguard Worker }
939*7c568831SAndroid Build Coastguard Worker
940*7c568831SAndroid Build Coastguard Worker xmlFree(comp);
941*7c568831SAndroid Build Coastguard Worker }
942*7c568831SAndroid Build Coastguard Worker
943*7c568831SAndroid Build Coastguard Worker /**
944*7c568831SAndroid Build Coastguard Worker * xmlXPathCompExprAdd:
945*7c568831SAndroid Build Coastguard Worker * @comp: the compiled expression
946*7c568831SAndroid Build Coastguard Worker * @ch1: first child index
947*7c568831SAndroid Build Coastguard Worker * @ch2: second child index
948*7c568831SAndroid Build Coastguard Worker * @op: an op
949*7c568831SAndroid Build Coastguard Worker * @value: the first int value
950*7c568831SAndroid Build Coastguard Worker * @value2: the second int value
951*7c568831SAndroid Build Coastguard Worker * @value3: the third int value
952*7c568831SAndroid Build Coastguard Worker * @value4: the first string value
953*7c568831SAndroid Build Coastguard Worker * @value5: the second string value
954*7c568831SAndroid Build Coastguard Worker *
955*7c568831SAndroid Build Coastguard Worker * Add a step to an XPath Compiled Expression
956*7c568831SAndroid Build Coastguard Worker *
957*7c568831SAndroid Build Coastguard Worker * Returns -1 in case of failure, the index otherwise
958*7c568831SAndroid Build Coastguard Worker */
959*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCompExprAdd(xmlXPathParserContextPtr ctxt,int ch1,int ch2,xmlXPathOp op,int value,int value2,int value3,void * value4,void * value5)960*7c568831SAndroid Build Coastguard Worker xmlXPathCompExprAdd(xmlXPathParserContextPtr ctxt, int ch1, int ch2,
961*7c568831SAndroid Build Coastguard Worker xmlXPathOp op, int value,
962*7c568831SAndroid Build Coastguard Worker int value2, int value3, void *value4, void *value5) {
963*7c568831SAndroid Build Coastguard Worker xmlXPathCompExprPtr comp = ctxt->comp;
964*7c568831SAndroid Build Coastguard Worker if (comp->nbStep >= comp->maxStep) {
965*7c568831SAndroid Build Coastguard Worker xmlXPathStepOp *real;
966*7c568831SAndroid Build Coastguard Worker
967*7c568831SAndroid Build Coastguard Worker if (comp->maxStep >= XPATH_MAX_STEPS) {
968*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
969*7c568831SAndroid Build Coastguard Worker return(-1);
970*7c568831SAndroid Build Coastguard Worker }
971*7c568831SAndroid Build Coastguard Worker comp->maxStep *= 2;
972*7c568831SAndroid Build Coastguard Worker real = (xmlXPathStepOp *) xmlRealloc(comp->steps,
973*7c568831SAndroid Build Coastguard Worker comp->maxStep * sizeof(xmlXPathStepOp));
974*7c568831SAndroid Build Coastguard Worker if (real == NULL) {
975*7c568831SAndroid Build Coastguard Worker comp->maxStep /= 2;
976*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
977*7c568831SAndroid Build Coastguard Worker return(-1);
978*7c568831SAndroid Build Coastguard Worker }
979*7c568831SAndroid Build Coastguard Worker comp->steps = real;
980*7c568831SAndroid Build Coastguard Worker }
981*7c568831SAndroid Build Coastguard Worker comp->last = comp->nbStep;
982*7c568831SAndroid Build Coastguard Worker comp->steps[comp->nbStep].ch1 = ch1;
983*7c568831SAndroid Build Coastguard Worker comp->steps[comp->nbStep].ch2 = ch2;
984*7c568831SAndroid Build Coastguard Worker comp->steps[comp->nbStep].op = op;
985*7c568831SAndroid Build Coastguard Worker comp->steps[comp->nbStep].value = value;
986*7c568831SAndroid Build Coastguard Worker comp->steps[comp->nbStep].value2 = value2;
987*7c568831SAndroid Build Coastguard Worker comp->steps[comp->nbStep].value3 = value3;
988*7c568831SAndroid Build Coastguard Worker if ((comp->dict != NULL) &&
989*7c568831SAndroid Build Coastguard Worker ((op == XPATH_OP_FUNCTION) || (op == XPATH_OP_VARIABLE) ||
990*7c568831SAndroid Build Coastguard Worker (op == XPATH_OP_COLLECT))) {
991*7c568831SAndroid Build Coastguard Worker if (value4 != NULL) {
992*7c568831SAndroid Build Coastguard Worker comp->steps[comp->nbStep].value4 = (xmlChar *)
993*7c568831SAndroid Build Coastguard Worker (void *)xmlDictLookup(comp->dict, value4, -1);
994*7c568831SAndroid Build Coastguard Worker xmlFree(value4);
995*7c568831SAndroid Build Coastguard Worker } else
996*7c568831SAndroid Build Coastguard Worker comp->steps[comp->nbStep].value4 = NULL;
997*7c568831SAndroid Build Coastguard Worker if (value5 != NULL) {
998*7c568831SAndroid Build Coastguard Worker comp->steps[comp->nbStep].value5 = (xmlChar *)
999*7c568831SAndroid Build Coastguard Worker (void *)xmlDictLookup(comp->dict, value5, -1);
1000*7c568831SAndroid Build Coastguard Worker xmlFree(value5);
1001*7c568831SAndroid Build Coastguard Worker } else
1002*7c568831SAndroid Build Coastguard Worker comp->steps[comp->nbStep].value5 = NULL;
1003*7c568831SAndroid Build Coastguard Worker } else {
1004*7c568831SAndroid Build Coastguard Worker comp->steps[comp->nbStep].value4 = value4;
1005*7c568831SAndroid Build Coastguard Worker comp->steps[comp->nbStep].value5 = value5;
1006*7c568831SAndroid Build Coastguard Worker }
1007*7c568831SAndroid Build Coastguard Worker comp->steps[comp->nbStep].cache = NULL;
1008*7c568831SAndroid Build Coastguard Worker return(comp->nbStep++);
1009*7c568831SAndroid Build Coastguard Worker }
1010*7c568831SAndroid Build Coastguard Worker
1011*7c568831SAndroid Build Coastguard Worker #define PUSH_FULL_EXPR(op, op1, op2, val, val2, val3, val4, val5) \
1012*7c568831SAndroid Build Coastguard Worker xmlXPathCompExprAdd(ctxt, (op1), (op2), \
1013*7c568831SAndroid Build Coastguard Worker (op), (val), (val2), (val3), (val4), (val5))
1014*7c568831SAndroid Build Coastguard Worker #define PUSH_LONG_EXPR(op, val, val2, val3, val4, val5) \
1015*7c568831SAndroid Build Coastguard Worker xmlXPathCompExprAdd(ctxt, ctxt->comp->last, -1, \
1016*7c568831SAndroid Build Coastguard Worker (op), (val), (val2), (val3), (val4), (val5))
1017*7c568831SAndroid Build Coastguard Worker
1018*7c568831SAndroid Build Coastguard Worker #define PUSH_LEAVE_EXPR(op, val, val2) \
1019*7c568831SAndroid Build Coastguard Worker xmlXPathCompExprAdd(ctxt, -1, -1, (op), (val), (val2), 0 ,NULL ,NULL)
1020*7c568831SAndroid Build Coastguard Worker
1021*7c568831SAndroid Build Coastguard Worker #define PUSH_UNARY_EXPR(op, ch, val, val2) \
1022*7c568831SAndroid Build Coastguard Worker xmlXPathCompExprAdd(ctxt, (ch), -1, (op), (val), (val2), 0 ,NULL ,NULL)
1023*7c568831SAndroid Build Coastguard Worker
1024*7c568831SAndroid Build Coastguard Worker #define PUSH_BINARY_EXPR(op, ch1, ch2, val, val2) \
1025*7c568831SAndroid Build Coastguard Worker xmlXPathCompExprAdd(ctxt, (ch1), (ch2), (op), \
1026*7c568831SAndroid Build Coastguard Worker (val), (val2), 0 ,NULL ,NULL)
1027*7c568831SAndroid Build Coastguard Worker
1028*7c568831SAndroid Build Coastguard Worker /************************************************************************
1029*7c568831SAndroid Build Coastguard Worker * *
1030*7c568831SAndroid Build Coastguard Worker * XPath object cache structures *
1031*7c568831SAndroid Build Coastguard Worker * *
1032*7c568831SAndroid Build Coastguard Worker ************************************************************************/
1033*7c568831SAndroid Build Coastguard Worker
1034*7c568831SAndroid Build Coastguard Worker /* #define XP_DEFAULT_CACHE_ON */
1035*7c568831SAndroid Build Coastguard Worker
1036*7c568831SAndroid Build Coastguard Worker typedef struct _xmlXPathContextCache xmlXPathContextCache;
1037*7c568831SAndroid Build Coastguard Worker typedef xmlXPathContextCache *xmlXPathContextCachePtr;
1038*7c568831SAndroid Build Coastguard Worker struct _xmlXPathContextCache {
1039*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr nodesetObjs; /* stringval points to next */
1040*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr miscObjs; /* stringval points to next */
1041*7c568831SAndroid Build Coastguard Worker int numNodeset;
1042*7c568831SAndroid Build Coastguard Worker int maxNodeset;
1043*7c568831SAndroid Build Coastguard Worker int numMisc;
1044*7c568831SAndroid Build Coastguard Worker int maxMisc;
1045*7c568831SAndroid Build Coastguard Worker };
1046*7c568831SAndroid Build Coastguard Worker
1047*7c568831SAndroid Build Coastguard Worker /************************************************************************
1048*7c568831SAndroid Build Coastguard Worker * *
1049*7c568831SAndroid Build Coastguard Worker * Debugging related functions *
1050*7c568831SAndroid Build Coastguard Worker * *
1051*7c568831SAndroid Build Coastguard Worker ************************************************************************/
1052*7c568831SAndroid Build Coastguard Worker
1053*7c568831SAndroid Build Coastguard Worker #ifdef LIBXML_DEBUG_ENABLED
1054*7c568831SAndroid Build Coastguard Worker static void
xmlXPathDebugDumpNode(FILE * output,xmlNodePtr cur,int depth)1055*7c568831SAndroid Build Coastguard Worker xmlXPathDebugDumpNode(FILE *output, xmlNodePtr cur, int depth) {
1056*7c568831SAndroid Build Coastguard Worker int i;
1057*7c568831SAndroid Build Coastguard Worker char shift[100];
1058*7c568831SAndroid Build Coastguard Worker
1059*7c568831SAndroid Build Coastguard Worker for (i = 0;((i < depth) && (i < 25));i++)
1060*7c568831SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = ' ';
1061*7c568831SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = 0;
1062*7c568831SAndroid Build Coastguard Worker if (cur == NULL) {
1063*7c568831SAndroid Build Coastguard Worker fprintf(output, "%s", shift);
1064*7c568831SAndroid Build Coastguard Worker fprintf(output, "Node is NULL !\n");
1065*7c568831SAndroid Build Coastguard Worker return;
1066*7c568831SAndroid Build Coastguard Worker
1067*7c568831SAndroid Build Coastguard Worker }
1068*7c568831SAndroid Build Coastguard Worker
1069*7c568831SAndroid Build Coastguard Worker if ((cur->type == XML_DOCUMENT_NODE) ||
1070*7c568831SAndroid Build Coastguard Worker (cur->type == XML_HTML_DOCUMENT_NODE)) {
1071*7c568831SAndroid Build Coastguard Worker fprintf(output, "%s", shift);
1072*7c568831SAndroid Build Coastguard Worker fprintf(output, " /\n");
1073*7c568831SAndroid Build Coastguard Worker } else if (cur->type == XML_ATTRIBUTE_NODE)
1074*7c568831SAndroid Build Coastguard Worker xmlDebugDumpAttr(output, (xmlAttrPtr)cur, depth);
1075*7c568831SAndroid Build Coastguard Worker else
1076*7c568831SAndroid Build Coastguard Worker xmlDebugDumpOneNode(output, cur, depth);
1077*7c568831SAndroid Build Coastguard Worker }
1078*7c568831SAndroid Build Coastguard Worker static void
xmlXPathDebugDumpNodeList(FILE * output,xmlNodePtr cur,int depth)1079*7c568831SAndroid Build Coastguard Worker xmlXPathDebugDumpNodeList(FILE *output, xmlNodePtr cur, int depth) {
1080*7c568831SAndroid Build Coastguard Worker xmlNodePtr tmp;
1081*7c568831SAndroid Build Coastguard Worker int i;
1082*7c568831SAndroid Build Coastguard Worker char shift[100];
1083*7c568831SAndroid Build Coastguard Worker
1084*7c568831SAndroid Build Coastguard Worker for (i = 0;((i < depth) && (i < 25));i++)
1085*7c568831SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = ' ';
1086*7c568831SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = 0;
1087*7c568831SAndroid Build Coastguard Worker if (cur == NULL) {
1088*7c568831SAndroid Build Coastguard Worker fprintf(output, "%s", shift);
1089*7c568831SAndroid Build Coastguard Worker fprintf(output, "Node is NULL !\n");
1090*7c568831SAndroid Build Coastguard Worker return;
1091*7c568831SAndroid Build Coastguard Worker
1092*7c568831SAndroid Build Coastguard Worker }
1093*7c568831SAndroid Build Coastguard Worker
1094*7c568831SAndroid Build Coastguard Worker while (cur != NULL) {
1095*7c568831SAndroid Build Coastguard Worker tmp = cur;
1096*7c568831SAndroid Build Coastguard Worker cur = cur->next;
1097*7c568831SAndroid Build Coastguard Worker xmlDebugDumpOneNode(output, tmp, depth);
1098*7c568831SAndroid Build Coastguard Worker }
1099*7c568831SAndroid Build Coastguard Worker }
1100*7c568831SAndroid Build Coastguard Worker
1101*7c568831SAndroid Build Coastguard Worker static void
xmlXPathDebugDumpNodeSet(FILE * output,xmlNodeSetPtr cur,int depth)1102*7c568831SAndroid Build Coastguard Worker xmlXPathDebugDumpNodeSet(FILE *output, xmlNodeSetPtr cur, int depth) {
1103*7c568831SAndroid Build Coastguard Worker int i;
1104*7c568831SAndroid Build Coastguard Worker char shift[100];
1105*7c568831SAndroid Build Coastguard Worker
1106*7c568831SAndroid Build Coastguard Worker for (i = 0;((i < depth) && (i < 25));i++)
1107*7c568831SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = ' ';
1108*7c568831SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = 0;
1109*7c568831SAndroid Build Coastguard Worker
1110*7c568831SAndroid Build Coastguard Worker if (cur == NULL) {
1111*7c568831SAndroid Build Coastguard Worker fprintf(output, "%s", shift);
1112*7c568831SAndroid Build Coastguard Worker fprintf(output, "NodeSet is NULL !\n");
1113*7c568831SAndroid Build Coastguard Worker return;
1114*7c568831SAndroid Build Coastguard Worker
1115*7c568831SAndroid Build Coastguard Worker }
1116*7c568831SAndroid Build Coastguard Worker
1117*7c568831SAndroid Build Coastguard Worker if (cur != NULL) {
1118*7c568831SAndroid Build Coastguard Worker fprintf(output, "Set contains %d nodes:\n", cur->nodeNr);
1119*7c568831SAndroid Build Coastguard Worker for (i = 0;i < cur->nodeNr;i++) {
1120*7c568831SAndroid Build Coastguard Worker fprintf(output, "%s", shift);
1121*7c568831SAndroid Build Coastguard Worker fprintf(output, "%d", i + 1);
1122*7c568831SAndroid Build Coastguard Worker xmlXPathDebugDumpNode(output, cur->nodeTab[i], depth + 1);
1123*7c568831SAndroid Build Coastguard Worker }
1124*7c568831SAndroid Build Coastguard Worker }
1125*7c568831SAndroid Build Coastguard Worker }
1126*7c568831SAndroid Build Coastguard Worker
1127*7c568831SAndroid Build Coastguard Worker static void
xmlXPathDebugDumpValueTree(FILE * output,xmlNodeSetPtr cur,int depth)1128*7c568831SAndroid Build Coastguard Worker xmlXPathDebugDumpValueTree(FILE *output, xmlNodeSetPtr cur, int depth) {
1129*7c568831SAndroid Build Coastguard Worker int i;
1130*7c568831SAndroid Build Coastguard Worker char shift[100];
1131*7c568831SAndroid Build Coastguard Worker
1132*7c568831SAndroid Build Coastguard Worker for (i = 0;((i < depth) && (i < 25));i++)
1133*7c568831SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = ' ';
1134*7c568831SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = 0;
1135*7c568831SAndroid Build Coastguard Worker
1136*7c568831SAndroid Build Coastguard Worker if ((cur == NULL) || (cur->nodeNr == 0) || (cur->nodeTab[0] == NULL)) {
1137*7c568831SAndroid Build Coastguard Worker fprintf(output, "%s", shift);
1138*7c568831SAndroid Build Coastguard Worker fprintf(output, "Value Tree is NULL !\n");
1139*7c568831SAndroid Build Coastguard Worker return;
1140*7c568831SAndroid Build Coastguard Worker
1141*7c568831SAndroid Build Coastguard Worker }
1142*7c568831SAndroid Build Coastguard Worker
1143*7c568831SAndroid Build Coastguard Worker fprintf(output, "%s", shift);
1144*7c568831SAndroid Build Coastguard Worker fprintf(output, "%d", i + 1);
1145*7c568831SAndroid Build Coastguard Worker xmlXPathDebugDumpNodeList(output, cur->nodeTab[0]->children, depth + 1);
1146*7c568831SAndroid Build Coastguard Worker }
1147*7c568831SAndroid Build Coastguard Worker
1148*7c568831SAndroid Build Coastguard Worker /**
1149*7c568831SAndroid Build Coastguard Worker * xmlXPathDebugDumpObject:
1150*7c568831SAndroid Build Coastguard Worker * @output: the FILE * to dump the output
1151*7c568831SAndroid Build Coastguard Worker * @cur: the object to inspect
1152*7c568831SAndroid Build Coastguard Worker * @depth: indentation level
1153*7c568831SAndroid Build Coastguard Worker *
1154*7c568831SAndroid Build Coastguard Worker * Dump the content of the object for debugging purposes
1155*7c568831SAndroid Build Coastguard Worker */
1156*7c568831SAndroid Build Coastguard Worker void
xmlXPathDebugDumpObject(FILE * output,xmlXPathObjectPtr cur,int depth)1157*7c568831SAndroid Build Coastguard Worker xmlXPathDebugDumpObject(FILE *output, xmlXPathObjectPtr cur, int depth) {
1158*7c568831SAndroid Build Coastguard Worker int i;
1159*7c568831SAndroid Build Coastguard Worker char shift[100];
1160*7c568831SAndroid Build Coastguard Worker
1161*7c568831SAndroid Build Coastguard Worker if (output == NULL) return;
1162*7c568831SAndroid Build Coastguard Worker
1163*7c568831SAndroid Build Coastguard Worker for (i = 0;((i < depth) && (i < 25));i++)
1164*7c568831SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = ' ';
1165*7c568831SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = 0;
1166*7c568831SAndroid Build Coastguard Worker
1167*7c568831SAndroid Build Coastguard Worker
1168*7c568831SAndroid Build Coastguard Worker fprintf(output, "%s", shift);
1169*7c568831SAndroid Build Coastguard Worker
1170*7c568831SAndroid Build Coastguard Worker if (cur == NULL) {
1171*7c568831SAndroid Build Coastguard Worker fprintf(output, "Object is empty (NULL)\n");
1172*7c568831SAndroid Build Coastguard Worker return;
1173*7c568831SAndroid Build Coastguard Worker }
1174*7c568831SAndroid Build Coastguard Worker switch(cur->type) {
1175*7c568831SAndroid Build Coastguard Worker case XPATH_UNDEFINED:
1176*7c568831SAndroid Build Coastguard Worker fprintf(output, "Object is uninitialized\n");
1177*7c568831SAndroid Build Coastguard Worker break;
1178*7c568831SAndroid Build Coastguard Worker case XPATH_NODESET:
1179*7c568831SAndroid Build Coastguard Worker fprintf(output, "Object is a Node Set :\n");
1180*7c568831SAndroid Build Coastguard Worker xmlXPathDebugDumpNodeSet(output, cur->nodesetval, depth);
1181*7c568831SAndroid Build Coastguard Worker break;
1182*7c568831SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
1183*7c568831SAndroid Build Coastguard Worker fprintf(output, "Object is an XSLT value tree :\n");
1184*7c568831SAndroid Build Coastguard Worker xmlXPathDebugDumpValueTree(output, cur->nodesetval, depth);
1185*7c568831SAndroid Build Coastguard Worker break;
1186*7c568831SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
1187*7c568831SAndroid Build Coastguard Worker fprintf(output, "Object is a Boolean : ");
1188*7c568831SAndroid Build Coastguard Worker if (cur->boolval) fprintf(output, "true\n");
1189*7c568831SAndroid Build Coastguard Worker else fprintf(output, "false\n");
1190*7c568831SAndroid Build Coastguard Worker break;
1191*7c568831SAndroid Build Coastguard Worker case XPATH_NUMBER:
1192*7c568831SAndroid Build Coastguard Worker switch (xmlXPathIsInf(cur->floatval)) {
1193*7c568831SAndroid Build Coastguard Worker case 1:
1194*7c568831SAndroid Build Coastguard Worker fprintf(output, "Object is a number : Infinity\n");
1195*7c568831SAndroid Build Coastguard Worker break;
1196*7c568831SAndroid Build Coastguard Worker case -1:
1197*7c568831SAndroid Build Coastguard Worker fprintf(output, "Object is a number : -Infinity\n");
1198*7c568831SAndroid Build Coastguard Worker break;
1199*7c568831SAndroid Build Coastguard Worker default:
1200*7c568831SAndroid Build Coastguard Worker if (xmlXPathIsNaN(cur->floatval)) {
1201*7c568831SAndroid Build Coastguard Worker fprintf(output, "Object is a number : NaN\n");
1202*7c568831SAndroid Build Coastguard Worker } else if (cur->floatval == 0) {
1203*7c568831SAndroid Build Coastguard Worker /* Omit sign for negative zero. */
1204*7c568831SAndroid Build Coastguard Worker fprintf(output, "Object is a number : 0\n");
1205*7c568831SAndroid Build Coastguard Worker } else {
1206*7c568831SAndroid Build Coastguard Worker fprintf(output, "Object is a number : %0g\n", cur->floatval);
1207*7c568831SAndroid Build Coastguard Worker }
1208*7c568831SAndroid Build Coastguard Worker }
1209*7c568831SAndroid Build Coastguard Worker break;
1210*7c568831SAndroid Build Coastguard Worker case XPATH_STRING:
1211*7c568831SAndroid Build Coastguard Worker fprintf(output, "Object is a string : ");
1212*7c568831SAndroid Build Coastguard Worker xmlDebugDumpString(output, cur->stringval);
1213*7c568831SAndroid Build Coastguard Worker fprintf(output, "\n");
1214*7c568831SAndroid Build Coastguard Worker break;
1215*7c568831SAndroid Build Coastguard Worker case XPATH_USERS:
1216*7c568831SAndroid Build Coastguard Worker fprintf(output, "Object is user defined\n");
1217*7c568831SAndroid Build Coastguard Worker break;
1218*7c568831SAndroid Build Coastguard Worker }
1219*7c568831SAndroid Build Coastguard Worker }
1220*7c568831SAndroid Build Coastguard Worker
1221*7c568831SAndroid Build Coastguard Worker static void
xmlXPathDebugDumpStepOp(FILE * output,xmlXPathCompExprPtr comp,xmlXPathStepOpPtr op,int depth)1222*7c568831SAndroid Build Coastguard Worker xmlXPathDebugDumpStepOp(FILE *output, xmlXPathCompExprPtr comp,
1223*7c568831SAndroid Build Coastguard Worker xmlXPathStepOpPtr op, int depth) {
1224*7c568831SAndroid Build Coastguard Worker int i;
1225*7c568831SAndroid Build Coastguard Worker char shift[100];
1226*7c568831SAndroid Build Coastguard Worker
1227*7c568831SAndroid Build Coastguard Worker for (i = 0;((i < depth) && (i < 25));i++)
1228*7c568831SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = ' ';
1229*7c568831SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = 0;
1230*7c568831SAndroid Build Coastguard Worker
1231*7c568831SAndroid Build Coastguard Worker fprintf(output, "%s", shift);
1232*7c568831SAndroid Build Coastguard Worker if (op == NULL) {
1233*7c568831SAndroid Build Coastguard Worker fprintf(output, "Step is NULL\n");
1234*7c568831SAndroid Build Coastguard Worker return;
1235*7c568831SAndroid Build Coastguard Worker }
1236*7c568831SAndroid Build Coastguard Worker switch (op->op) {
1237*7c568831SAndroid Build Coastguard Worker case XPATH_OP_END:
1238*7c568831SAndroid Build Coastguard Worker fprintf(output, "END"); break;
1239*7c568831SAndroid Build Coastguard Worker case XPATH_OP_AND:
1240*7c568831SAndroid Build Coastguard Worker fprintf(output, "AND"); break;
1241*7c568831SAndroid Build Coastguard Worker case XPATH_OP_OR:
1242*7c568831SAndroid Build Coastguard Worker fprintf(output, "OR"); break;
1243*7c568831SAndroid Build Coastguard Worker case XPATH_OP_EQUAL:
1244*7c568831SAndroid Build Coastguard Worker if (op->value)
1245*7c568831SAndroid Build Coastguard Worker fprintf(output, "EQUAL =");
1246*7c568831SAndroid Build Coastguard Worker else
1247*7c568831SAndroid Build Coastguard Worker fprintf(output, "EQUAL !=");
1248*7c568831SAndroid Build Coastguard Worker break;
1249*7c568831SAndroid Build Coastguard Worker case XPATH_OP_CMP:
1250*7c568831SAndroid Build Coastguard Worker if (op->value)
1251*7c568831SAndroid Build Coastguard Worker fprintf(output, "CMP <");
1252*7c568831SAndroid Build Coastguard Worker else
1253*7c568831SAndroid Build Coastguard Worker fprintf(output, "CMP >");
1254*7c568831SAndroid Build Coastguard Worker if (!op->value2)
1255*7c568831SAndroid Build Coastguard Worker fprintf(output, "=");
1256*7c568831SAndroid Build Coastguard Worker break;
1257*7c568831SAndroid Build Coastguard Worker case XPATH_OP_PLUS:
1258*7c568831SAndroid Build Coastguard Worker if (op->value == 0)
1259*7c568831SAndroid Build Coastguard Worker fprintf(output, "PLUS -");
1260*7c568831SAndroid Build Coastguard Worker else if (op->value == 1)
1261*7c568831SAndroid Build Coastguard Worker fprintf(output, "PLUS +");
1262*7c568831SAndroid Build Coastguard Worker else if (op->value == 2)
1263*7c568831SAndroid Build Coastguard Worker fprintf(output, "PLUS unary -");
1264*7c568831SAndroid Build Coastguard Worker else if (op->value == 3)
1265*7c568831SAndroid Build Coastguard Worker fprintf(output, "PLUS unary - -");
1266*7c568831SAndroid Build Coastguard Worker break;
1267*7c568831SAndroid Build Coastguard Worker case XPATH_OP_MULT:
1268*7c568831SAndroid Build Coastguard Worker if (op->value == 0)
1269*7c568831SAndroid Build Coastguard Worker fprintf(output, "MULT *");
1270*7c568831SAndroid Build Coastguard Worker else if (op->value == 1)
1271*7c568831SAndroid Build Coastguard Worker fprintf(output, "MULT div");
1272*7c568831SAndroid Build Coastguard Worker else
1273*7c568831SAndroid Build Coastguard Worker fprintf(output, "MULT mod");
1274*7c568831SAndroid Build Coastguard Worker break;
1275*7c568831SAndroid Build Coastguard Worker case XPATH_OP_UNION:
1276*7c568831SAndroid Build Coastguard Worker fprintf(output, "UNION"); break;
1277*7c568831SAndroid Build Coastguard Worker case XPATH_OP_ROOT:
1278*7c568831SAndroid Build Coastguard Worker fprintf(output, "ROOT"); break;
1279*7c568831SAndroid Build Coastguard Worker case XPATH_OP_NODE:
1280*7c568831SAndroid Build Coastguard Worker fprintf(output, "NODE"); break;
1281*7c568831SAndroid Build Coastguard Worker case XPATH_OP_SORT:
1282*7c568831SAndroid Build Coastguard Worker fprintf(output, "SORT"); break;
1283*7c568831SAndroid Build Coastguard Worker case XPATH_OP_COLLECT: {
1284*7c568831SAndroid Build Coastguard Worker xmlXPathAxisVal axis = (xmlXPathAxisVal)op->value;
1285*7c568831SAndroid Build Coastguard Worker xmlXPathTestVal test = (xmlXPathTestVal)op->value2;
1286*7c568831SAndroid Build Coastguard Worker xmlXPathTypeVal type = (xmlXPathTypeVal)op->value3;
1287*7c568831SAndroid Build Coastguard Worker const xmlChar *prefix = op->value4;
1288*7c568831SAndroid Build Coastguard Worker const xmlChar *name = op->value5;
1289*7c568831SAndroid Build Coastguard Worker
1290*7c568831SAndroid Build Coastguard Worker fprintf(output, "COLLECT ");
1291*7c568831SAndroid Build Coastguard Worker switch (axis) {
1292*7c568831SAndroid Build Coastguard Worker case AXIS_ANCESTOR:
1293*7c568831SAndroid Build Coastguard Worker fprintf(output, " 'ancestors' "); break;
1294*7c568831SAndroid Build Coastguard Worker case AXIS_ANCESTOR_OR_SELF:
1295*7c568831SAndroid Build Coastguard Worker fprintf(output, " 'ancestors-or-self' "); break;
1296*7c568831SAndroid Build Coastguard Worker case AXIS_ATTRIBUTE:
1297*7c568831SAndroid Build Coastguard Worker fprintf(output, " 'attributes' "); break;
1298*7c568831SAndroid Build Coastguard Worker case AXIS_CHILD:
1299*7c568831SAndroid Build Coastguard Worker fprintf(output, " 'child' "); break;
1300*7c568831SAndroid Build Coastguard Worker case AXIS_DESCENDANT:
1301*7c568831SAndroid Build Coastguard Worker fprintf(output, " 'descendant' "); break;
1302*7c568831SAndroid Build Coastguard Worker case AXIS_DESCENDANT_OR_SELF:
1303*7c568831SAndroid Build Coastguard Worker fprintf(output, " 'descendant-or-self' "); break;
1304*7c568831SAndroid Build Coastguard Worker case AXIS_FOLLOWING:
1305*7c568831SAndroid Build Coastguard Worker fprintf(output, " 'following' "); break;
1306*7c568831SAndroid Build Coastguard Worker case AXIS_FOLLOWING_SIBLING:
1307*7c568831SAndroid Build Coastguard Worker fprintf(output, " 'following-siblings' "); break;
1308*7c568831SAndroid Build Coastguard Worker case AXIS_NAMESPACE:
1309*7c568831SAndroid Build Coastguard Worker fprintf(output, " 'namespace' "); break;
1310*7c568831SAndroid Build Coastguard Worker case AXIS_PARENT:
1311*7c568831SAndroid Build Coastguard Worker fprintf(output, " 'parent' "); break;
1312*7c568831SAndroid Build Coastguard Worker case AXIS_PRECEDING:
1313*7c568831SAndroid Build Coastguard Worker fprintf(output, " 'preceding' "); break;
1314*7c568831SAndroid Build Coastguard Worker case AXIS_PRECEDING_SIBLING:
1315*7c568831SAndroid Build Coastguard Worker fprintf(output, " 'preceding-sibling' "); break;
1316*7c568831SAndroid Build Coastguard Worker case AXIS_SELF:
1317*7c568831SAndroid Build Coastguard Worker fprintf(output, " 'self' "); break;
1318*7c568831SAndroid Build Coastguard Worker }
1319*7c568831SAndroid Build Coastguard Worker switch (test) {
1320*7c568831SAndroid Build Coastguard Worker case NODE_TEST_NONE:
1321*7c568831SAndroid Build Coastguard Worker fprintf(output, "'none' "); break;
1322*7c568831SAndroid Build Coastguard Worker case NODE_TEST_TYPE:
1323*7c568831SAndroid Build Coastguard Worker fprintf(output, "'type' "); break;
1324*7c568831SAndroid Build Coastguard Worker case NODE_TEST_PI:
1325*7c568831SAndroid Build Coastguard Worker fprintf(output, "'PI' "); break;
1326*7c568831SAndroid Build Coastguard Worker case NODE_TEST_ALL:
1327*7c568831SAndroid Build Coastguard Worker fprintf(output, "'all' "); break;
1328*7c568831SAndroid Build Coastguard Worker case NODE_TEST_NS:
1329*7c568831SAndroid Build Coastguard Worker fprintf(output, "'namespace' "); break;
1330*7c568831SAndroid Build Coastguard Worker case NODE_TEST_NAME:
1331*7c568831SAndroid Build Coastguard Worker fprintf(output, "'name' "); break;
1332*7c568831SAndroid Build Coastguard Worker }
1333*7c568831SAndroid Build Coastguard Worker switch (type) {
1334*7c568831SAndroid Build Coastguard Worker case NODE_TYPE_NODE:
1335*7c568831SAndroid Build Coastguard Worker fprintf(output, "'node' "); break;
1336*7c568831SAndroid Build Coastguard Worker case NODE_TYPE_COMMENT:
1337*7c568831SAndroid Build Coastguard Worker fprintf(output, "'comment' "); break;
1338*7c568831SAndroid Build Coastguard Worker case NODE_TYPE_TEXT:
1339*7c568831SAndroid Build Coastguard Worker fprintf(output, "'text' "); break;
1340*7c568831SAndroid Build Coastguard Worker case NODE_TYPE_PI:
1341*7c568831SAndroid Build Coastguard Worker fprintf(output, "'PI' "); break;
1342*7c568831SAndroid Build Coastguard Worker }
1343*7c568831SAndroid Build Coastguard Worker if (prefix != NULL)
1344*7c568831SAndroid Build Coastguard Worker fprintf(output, "%s:", prefix);
1345*7c568831SAndroid Build Coastguard Worker if (name != NULL)
1346*7c568831SAndroid Build Coastguard Worker fprintf(output, "%s", (const char *) name);
1347*7c568831SAndroid Build Coastguard Worker break;
1348*7c568831SAndroid Build Coastguard Worker
1349*7c568831SAndroid Build Coastguard Worker }
1350*7c568831SAndroid Build Coastguard Worker case XPATH_OP_VALUE: {
1351*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr object = (xmlXPathObjectPtr) op->value4;
1352*7c568831SAndroid Build Coastguard Worker
1353*7c568831SAndroid Build Coastguard Worker fprintf(output, "ELEM ");
1354*7c568831SAndroid Build Coastguard Worker xmlXPathDebugDumpObject(output, object, 0);
1355*7c568831SAndroid Build Coastguard Worker goto finish;
1356*7c568831SAndroid Build Coastguard Worker }
1357*7c568831SAndroid Build Coastguard Worker case XPATH_OP_VARIABLE: {
1358*7c568831SAndroid Build Coastguard Worker const xmlChar *prefix = op->value5;
1359*7c568831SAndroid Build Coastguard Worker const xmlChar *name = op->value4;
1360*7c568831SAndroid Build Coastguard Worker
1361*7c568831SAndroid Build Coastguard Worker if (prefix != NULL)
1362*7c568831SAndroid Build Coastguard Worker fprintf(output, "VARIABLE %s:%s", prefix, name);
1363*7c568831SAndroid Build Coastguard Worker else
1364*7c568831SAndroid Build Coastguard Worker fprintf(output, "VARIABLE %s", name);
1365*7c568831SAndroid Build Coastguard Worker break;
1366*7c568831SAndroid Build Coastguard Worker }
1367*7c568831SAndroid Build Coastguard Worker case XPATH_OP_FUNCTION: {
1368*7c568831SAndroid Build Coastguard Worker int nbargs = op->value;
1369*7c568831SAndroid Build Coastguard Worker const xmlChar *prefix = op->value5;
1370*7c568831SAndroid Build Coastguard Worker const xmlChar *name = op->value4;
1371*7c568831SAndroid Build Coastguard Worker
1372*7c568831SAndroid Build Coastguard Worker if (prefix != NULL)
1373*7c568831SAndroid Build Coastguard Worker fprintf(output, "FUNCTION %s:%s(%d args)",
1374*7c568831SAndroid Build Coastguard Worker prefix, name, nbargs);
1375*7c568831SAndroid Build Coastguard Worker else
1376*7c568831SAndroid Build Coastguard Worker fprintf(output, "FUNCTION %s(%d args)", name, nbargs);
1377*7c568831SAndroid Build Coastguard Worker break;
1378*7c568831SAndroid Build Coastguard Worker }
1379*7c568831SAndroid Build Coastguard Worker case XPATH_OP_ARG: fprintf(output, "ARG"); break;
1380*7c568831SAndroid Build Coastguard Worker case XPATH_OP_PREDICATE: fprintf(output, "PREDICATE"); break;
1381*7c568831SAndroid Build Coastguard Worker case XPATH_OP_FILTER: fprintf(output, "FILTER"); break;
1382*7c568831SAndroid Build Coastguard Worker default:
1383*7c568831SAndroid Build Coastguard Worker fprintf(output, "UNKNOWN %d\n", op->op); return;
1384*7c568831SAndroid Build Coastguard Worker }
1385*7c568831SAndroid Build Coastguard Worker fprintf(output, "\n");
1386*7c568831SAndroid Build Coastguard Worker finish:
1387*7c568831SAndroid Build Coastguard Worker if (op->ch1 >= 0)
1388*7c568831SAndroid Build Coastguard Worker xmlXPathDebugDumpStepOp(output, comp, &comp->steps[op->ch1], depth + 1);
1389*7c568831SAndroid Build Coastguard Worker if (op->ch2 >= 0)
1390*7c568831SAndroid Build Coastguard Worker xmlXPathDebugDumpStepOp(output, comp, &comp->steps[op->ch2], depth + 1);
1391*7c568831SAndroid Build Coastguard Worker }
1392*7c568831SAndroid Build Coastguard Worker
1393*7c568831SAndroid Build Coastguard Worker /**
1394*7c568831SAndroid Build Coastguard Worker * xmlXPathDebugDumpCompExpr:
1395*7c568831SAndroid Build Coastguard Worker * @output: the FILE * for the output
1396*7c568831SAndroid Build Coastguard Worker * @comp: the precompiled XPath expression
1397*7c568831SAndroid Build Coastguard Worker * @depth: the indentation level.
1398*7c568831SAndroid Build Coastguard Worker *
1399*7c568831SAndroid Build Coastguard Worker * Dumps the tree of the compiled XPath expression.
1400*7c568831SAndroid Build Coastguard Worker */
1401*7c568831SAndroid Build Coastguard Worker void
xmlXPathDebugDumpCompExpr(FILE * output,xmlXPathCompExprPtr comp,int depth)1402*7c568831SAndroid Build Coastguard Worker xmlXPathDebugDumpCompExpr(FILE *output, xmlXPathCompExprPtr comp,
1403*7c568831SAndroid Build Coastguard Worker int depth) {
1404*7c568831SAndroid Build Coastguard Worker int i;
1405*7c568831SAndroid Build Coastguard Worker char shift[100];
1406*7c568831SAndroid Build Coastguard Worker
1407*7c568831SAndroid Build Coastguard Worker if ((output == NULL) || (comp == NULL)) return;
1408*7c568831SAndroid Build Coastguard Worker
1409*7c568831SAndroid Build Coastguard Worker for (i = 0;((i < depth) && (i < 25));i++)
1410*7c568831SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = ' ';
1411*7c568831SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = 0;
1412*7c568831SAndroid Build Coastguard Worker
1413*7c568831SAndroid Build Coastguard Worker fprintf(output, "%s", shift);
1414*7c568831SAndroid Build Coastguard Worker
1415*7c568831SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
1416*7c568831SAndroid Build Coastguard Worker if (comp->stream) {
1417*7c568831SAndroid Build Coastguard Worker fprintf(output, "Streaming Expression\n");
1418*7c568831SAndroid Build Coastguard Worker } else
1419*7c568831SAndroid Build Coastguard Worker #endif
1420*7c568831SAndroid Build Coastguard Worker {
1421*7c568831SAndroid Build Coastguard Worker fprintf(output, "Compiled Expression : %d elements\n",
1422*7c568831SAndroid Build Coastguard Worker comp->nbStep);
1423*7c568831SAndroid Build Coastguard Worker i = comp->last;
1424*7c568831SAndroid Build Coastguard Worker xmlXPathDebugDumpStepOp(output, comp, &comp->steps[i], depth + 1);
1425*7c568831SAndroid Build Coastguard Worker }
1426*7c568831SAndroid Build Coastguard Worker }
1427*7c568831SAndroid Build Coastguard Worker
1428*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_DEBUG_ENABLED */
1429*7c568831SAndroid Build Coastguard Worker
1430*7c568831SAndroid Build Coastguard Worker /************************************************************************
1431*7c568831SAndroid Build Coastguard Worker * *
1432*7c568831SAndroid Build Coastguard Worker * XPath object caching *
1433*7c568831SAndroid Build Coastguard Worker * *
1434*7c568831SAndroid Build Coastguard Worker ************************************************************************/
1435*7c568831SAndroid Build Coastguard Worker
1436*7c568831SAndroid Build Coastguard Worker /**
1437*7c568831SAndroid Build Coastguard Worker * xmlXPathNewCache:
1438*7c568831SAndroid Build Coastguard Worker *
1439*7c568831SAndroid Build Coastguard Worker * Create a new object cache
1440*7c568831SAndroid Build Coastguard Worker *
1441*7c568831SAndroid Build Coastguard Worker * Returns the xmlXPathCache just allocated.
1442*7c568831SAndroid Build Coastguard Worker */
1443*7c568831SAndroid Build Coastguard Worker static xmlXPathContextCachePtr
xmlXPathNewCache(void)1444*7c568831SAndroid Build Coastguard Worker xmlXPathNewCache(void)
1445*7c568831SAndroid Build Coastguard Worker {
1446*7c568831SAndroid Build Coastguard Worker xmlXPathContextCachePtr ret;
1447*7c568831SAndroid Build Coastguard Worker
1448*7c568831SAndroid Build Coastguard Worker ret = (xmlXPathContextCachePtr) xmlMalloc(sizeof(xmlXPathContextCache));
1449*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
1450*7c568831SAndroid Build Coastguard Worker return(NULL);
1451*7c568831SAndroid Build Coastguard Worker memset(ret, 0 , sizeof(xmlXPathContextCache));
1452*7c568831SAndroid Build Coastguard Worker ret->maxNodeset = 100;
1453*7c568831SAndroid Build Coastguard Worker ret->maxMisc = 100;
1454*7c568831SAndroid Build Coastguard Worker return(ret);
1455*7c568831SAndroid Build Coastguard Worker }
1456*7c568831SAndroid Build Coastguard Worker
1457*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCacheFreeObjectList(xmlXPathObjectPtr list)1458*7c568831SAndroid Build Coastguard Worker xmlXPathCacheFreeObjectList(xmlXPathObjectPtr list)
1459*7c568831SAndroid Build Coastguard Worker {
1460*7c568831SAndroid Build Coastguard Worker while (list != NULL) {
1461*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr next;
1462*7c568831SAndroid Build Coastguard Worker
1463*7c568831SAndroid Build Coastguard Worker next = (void *) list->stringval;
1464*7c568831SAndroid Build Coastguard Worker
1465*7c568831SAndroid Build Coastguard Worker if (list->nodesetval != NULL) {
1466*7c568831SAndroid Build Coastguard Worker if (list->nodesetval->nodeTab != NULL)
1467*7c568831SAndroid Build Coastguard Worker xmlFree(list->nodesetval->nodeTab);
1468*7c568831SAndroid Build Coastguard Worker xmlFree(list->nodesetval);
1469*7c568831SAndroid Build Coastguard Worker }
1470*7c568831SAndroid Build Coastguard Worker xmlFree(list);
1471*7c568831SAndroid Build Coastguard Worker
1472*7c568831SAndroid Build Coastguard Worker list = next;
1473*7c568831SAndroid Build Coastguard Worker }
1474*7c568831SAndroid Build Coastguard Worker }
1475*7c568831SAndroid Build Coastguard Worker
1476*7c568831SAndroid Build Coastguard Worker static void
xmlXPathFreeCache(xmlXPathContextCachePtr cache)1477*7c568831SAndroid Build Coastguard Worker xmlXPathFreeCache(xmlXPathContextCachePtr cache)
1478*7c568831SAndroid Build Coastguard Worker {
1479*7c568831SAndroid Build Coastguard Worker if (cache == NULL)
1480*7c568831SAndroid Build Coastguard Worker return;
1481*7c568831SAndroid Build Coastguard Worker if (cache->nodesetObjs)
1482*7c568831SAndroid Build Coastguard Worker xmlXPathCacheFreeObjectList(cache->nodesetObjs);
1483*7c568831SAndroid Build Coastguard Worker if (cache->miscObjs)
1484*7c568831SAndroid Build Coastguard Worker xmlXPathCacheFreeObjectList(cache->miscObjs);
1485*7c568831SAndroid Build Coastguard Worker xmlFree(cache);
1486*7c568831SAndroid Build Coastguard Worker }
1487*7c568831SAndroid Build Coastguard Worker
1488*7c568831SAndroid Build Coastguard Worker /**
1489*7c568831SAndroid Build Coastguard Worker * xmlXPathContextSetCache:
1490*7c568831SAndroid Build Coastguard Worker *
1491*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath context
1492*7c568831SAndroid Build Coastguard Worker * @active: enables/disables (creates/frees) the cache
1493*7c568831SAndroid Build Coastguard Worker * @value: a value with semantics dependent on @options
1494*7c568831SAndroid Build Coastguard Worker * @options: options (currently only the value 0 is used)
1495*7c568831SAndroid Build Coastguard Worker *
1496*7c568831SAndroid Build Coastguard Worker * Creates/frees an object cache on the XPath context.
1497*7c568831SAndroid Build Coastguard Worker * If activates XPath objects (xmlXPathObject) will be cached internally
1498*7c568831SAndroid Build Coastguard Worker * to be reused.
1499*7c568831SAndroid Build Coastguard Worker * @options:
1500*7c568831SAndroid Build Coastguard Worker * 0: This will set the XPath object caching:
1501*7c568831SAndroid Build Coastguard Worker * @value:
1502*7c568831SAndroid Build Coastguard Worker * This will set the maximum number of XPath objects
1503*7c568831SAndroid Build Coastguard Worker * to be cached per slot
1504*7c568831SAndroid Build Coastguard Worker * There are two slots for node-set and misc objects.
1505*7c568831SAndroid Build Coastguard Worker * Use <0 for the default number (100).
1506*7c568831SAndroid Build Coastguard Worker * Other values for @options have currently no effect.
1507*7c568831SAndroid Build Coastguard Worker *
1508*7c568831SAndroid Build Coastguard Worker * Returns 0 if the setting succeeded, and -1 on API or internal errors.
1509*7c568831SAndroid Build Coastguard Worker */
1510*7c568831SAndroid Build Coastguard Worker int
xmlXPathContextSetCache(xmlXPathContextPtr ctxt,int active,int value,int options)1511*7c568831SAndroid Build Coastguard Worker xmlXPathContextSetCache(xmlXPathContextPtr ctxt,
1512*7c568831SAndroid Build Coastguard Worker int active,
1513*7c568831SAndroid Build Coastguard Worker int value,
1514*7c568831SAndroid Build Coastguard Worker int options)
1515*7c568831SAndroid Build Coastguard Worker {
1516*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
1517*7c568831SAndroid Build Coastguard Worker return(-1);
1518*7c568831SAndroid Build Coastguard Worker if (active) {
1519*7c568831SAndroid Build Coastguard Worker xmlXPathContextCachePtr cache;
1520*7c568831SAndroid Build Coastguard Worker
1521*7c568831SAndroid Build Coastguard Worker if (ctxt->cache == NULL) {
1522*7c568831SAndroid Build Coastguard Worker ctxt->cache = xmlXPathNewCache();
1523*7c568831SAndroid Build Coastguard Worker if (ctxt->cache == NULL) {
1524*7c568831SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt);
1525*7c568831SAndroid Build Coastguard Worker return(-1);
1526*7c568831SAndroid Build Coastguard Worker }
1527*7c568831SAndroid Build Coastguard Worker }
1528*7c568831SAndroid Build Coastguard Worker cache = (xmlXPathContextCachePtr) ctxt->cache;
1529*7c568831SAndroid Build Coastguard Worker if (options == 0) {
1530*7c568831SAndroid Build Coastguard Worker if (value < 0)
1531*7c568831SAndroid Build Coastguard Worker value = 100;
1532*7c568831SAndroid Build Coastguard Worker cache->maxNodeset = value;
1533*7c568831SAndroid Build Coastguard Worker cache->maxMisc = value;
1534*7c568831SAndroid Build Coastguard Worker }
1535*7c568831SAndroid Build Coastguard Worker } else if (ctxt->cache != NULL) {
1536*7c568831SAndroid Build Coastguard Worker xmlXPathFreeCache((xmlXPathContextCachePtr) ctxt->cache);
1537*7c568831SAndroid Build Coastguard Worker ctxt->cache = NULL;
1538*7c568831SAndroid Build Coastguard Worker }
1539*7c568831SAndroid Build Coastguard Worker return(0);
1540*7c568831SAndroid Build Coastguard Worker }
1541*7c568831SAndroid Build Coastguard Worker
1542*7c568831SAndroid Build Coastguard Worker /**
1543*7c568831SAndroid Build Coastguard Worker * xmlXPathCacheWrapNodeSet:
1544*7c568831SAndroid Build Coastguard Worker * @pctxt: the XPath context
1545*7c568831SAndroid Build Coastguard Worker * @val: the NodePtr value
1546*7c568831SAndroid Build Coastguard Worker *
1547*7c568831SAndroid Build Coastguard Worker * This is the cached version of xmlXPathWrapNodeSet().
1548*7c568831SAndroid Build Coastguard Worker * Wrap the Nodeset @val in a new xmlXPathObjectPtr
1549*7c568831SAndroid Build Coastguard Worker *
1550*7c568831SAndroid Build Coastguard Worker * Returns the created or reused object.
1551*7c568831SAndroid Build Coastguard Worker *
1552*7c568831SAndroid Build Coastguard Worker * In case of error the node set is destroyed and NULL is returned.
1553*7c568831SAndroid Build Coastguard Worker */
1554*7c568831SAndroid Build Coastguard Worker static xmlXPathObjectPtr
xmlXPathCacheWrapNodeSet(xmlXPathParserContextPtr pctxt,xmlNodeSetPtr val)1555*7c568831SAndroid Build Coastguard Worker xmlXPathCacheWrapNodeSet(xmlXPathParserContextPtr pctxt, xmlNodeSetPtr val)
1556*7c568831SAndroid Build Coastguard Worker {
1557*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
1558*7c568831SAndroid Build Coastguard Worker xmlXPathContextPtr ctxt = pctxt->context;
1559*7c568831SAndroid Build Coastguard Worker
1560*7c568831SAndroid Build Coastguard Worker if ((ctxt != NULL) && (ctxt->cache != NULL)) {
1561*7c568831SAndroid Build Coastguard Worker xmlXPathContextCachePtr cache =
1562*7c568831SAndroid Build Coastguard Worker (xmlXPathContextCachePtr) ctxt->cache;
1563*7c568831SAndroid Build Coastguard Worker
1564*7c568831SAndroid Build Coastguard Worker if (cache->miscObjs != NULL) {
1565*7c568831SAndroid Build Coastguard Worker ret = cache->miscObjs;
1566*7c568831SAndroid Build Coastguard Worker cache->miscObjs = (void *) ret->stringval;
1567*7c568831SAndroid Build Coastguard Worker cache->numMisc -= 1;
1568*7c568831SAndroid Build Coastguard Worker ret->stringval = NULL;
1569*7c568831SAndroid Build Coastguard Worker ret->type = XPATH_NODESET;
1570*7c568831SAndroid Build Coastguard Worker ret->nodesetval = val;
1571*7c568831SAndroid Build Coastguard Worker return(ret);
1572*7c568831SAndroid Build Coastguard Worker }
1573*7c568831SAndroid Build Coastguard Worker }
1574*7c568831SAndroid Build Coastguard Worker
1575*7c568831SAndroid Build Coastguard Worker ret = xmlXPathWrapNodeSet(val);
1576*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
1577*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
1578*7c568831SAndroid Build Coastguard Worker return(ret);
1579*7c568831SAndroid Build Coastguard Worker }
1580*7c568831SAndroid Build Coastguard Worker
1581*7c568831SAndroid Build Coastguard Worker /**
1582*7c568831SAndroid Build Coastguard Worker * xmlXPathCacheWrapString:
1583*7c568831SAndroid Build Coastguard Worker * @pctxt the XPath context
1584*7c568831SAndroid Build Coastguard Worker * @val: the xmlChar * value
1585*7c568831SAndroid Build Coastguard Worker *
1586*7c568831SAndroid Build Coastguard Worker * This is the cached version of xmlXPathWrapString().
1587*7c568831SAndroid Build Coastguard Worker * Wraps the @val string into an XPath object.
1588*7c568831SAndroid Build Coastguard Worker *
1589*7c568831SAndroid Build Coastguard Worker * Returns the created or reused object.
1590*7c568831SAndroid Build Coastguard Worker */
1591*7c568831SAndroid Build Coastguard Worker static xmlXPathObjectPtr
xmlXPathCacheWrapString(xmlXPathParserContextPtr pctxt,xmlChar * val)1592*7c568831SAndroid Build Coastguard Worker xmlXPathCacheWrapString(xmlXPathParserContextPtr pctxt, xmlChar *val)
1593*7c568831SAndroid Build Coastguard Worker {
1594*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
1595*7c568831SAndroid Build Coastguard Worker xmlXPathContextPtr ctxt = pctxt->context;
1596*7c568831SAndroid Build Coastguard Worker
1597*7c568831SAndroid Build Coastguard Worker if ((ctxt != NULL) && (ctxt->cache != NULL)) {
1598*7c568831SAndroid Build Coastguard Worker xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
1599*7c568831SAndroid Build Coastguard Worker
1600*7c568831SAndroid Build Coastguard Worker if (cache->miscObjs != NULL) {
1601*7c568831SAndroid Build Coastguard Worker ret = cache->miscObjs;
1602*7c568831SAndroid Build Coastguard Worker cache->miscObjs = (void *) ret->stringval;
1603*7c568831SAndroid Build Coastguard Worker cache->numMisc -= 1;
1604*7c568831SAndroid Build Coastguard Worker ret->type = XPATH_STRING;
1605*7c568831SAndroid Build Coastguard Worker ret->stringval = val;
1606*7c568831SAndroid Build Coastguard Worker return(ret);
1607*7c568831SAndroid Build Coastguard Worker }
1608*7c568831SAndroid Build Coastguard Worker }
1609*7c568831SAndroid Build Coastguard Worker
1610*7c568831SAndroid Build Coastguard Worker ret = xmlXPathWrapString(val);
1611*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
1612*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
1613*7c568831SAndroid Build Coastguard Worker return(ret);
1614*7c568831SAndroid Build Coastguard Worker }
1615*7c568831SAndroid Build Coastguard Worker
1616*7c568831SAndroid Build Coastguard Worker /**
1617*7c568831SAndroid Build Coastguard Worker * xmlXPathCacheNewNodeSet:
1618*7c568831SAndroid Build Coastguard Worker * @pctxt the XPath context
1619*7c568831SAndroid Build Coastguard Worker * @val: the NodePtr value
1620*7c568831SAndroid Build Coastguard Worker *
1621*7c568831SAndroid Build Coastguard Worker * This is the cached version of xmlXPathNewNodeSet().
1622*7c568831SAndroid Build Coastguard Worker * Acquire an xmlXPathObjectPtr of type NodeSet and initialize
1623*7c568831SAndroid Build Coastguard Worker * it with the single Node @val
1624*7c568831SAndroid Build Coastguard Worker *
1625*7c568831SAndroid Build Coastguard Worker * Returns the created or reused object.
1626*7c568831SAndroid Build Coastguard Worker */
1627*7c568831SAndroid Build Coastguard Worker static xmlXPathObjectPtr
xmlXPathCacheNewNodeSet(xmlXPathParserContextPtr pctxt,xmlNodePtr val)1628*7c568831SAndroid Build Coastguard Worker xmlXPathCacheNewNodeSet(xmlXPathParserContextPtr pctxt, xmlNodePtr val)
1629*7c568831SAndroid Build Coastguard Worker {
1630*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
1631*7c568831SAndroid Build Coastguard Worker xmlXPathContextPtr ctxt = pctxt->context;
1632*7c568831SAndroid Build Coastguard Worker
1633*7c568831SAndroid Build Coastguard Worker if ((ctxt != NULL) && (ctxt->cache != NULL)) {
1634*7c568831SAndroid Build Coastguard Worker xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
1635*7c568831SAndroid Build Coastguard Worker
1636*7c568831SAndroid Build Coastguard Worker if (cache->nodesetObjs != NULL) {
1637*7c568831SAndroid Build Coastguard Worker /*
1638*7c568831SAndroid Build Coastguard Worker * Use the nodeset-cache.
1639*7c568831SAndroid Build Coastguard Worker */
1640*7c568831SAndroid Build Coastguard Worker ret = cache->nodesetObjs;
1641*7c568831SAndroid Build Coastguard Worker cache->nodesetObjs = (void *) ret->stringval;
1642*7c568831SAndroid Build Coastguard Worker cache->numNodeset -= 1;
1643*7c568831SAndroid Build Coastguard Worker ret->stringval = NULL;
1644*7c568831SAndroid Build Coastguard Worker ret->type = XPATH_NODESET;
1645*7c568831SAndroid Build Coastguard Worker ret->boolval = 0;
1646*7c568831SAndroid Build Coastguard Worker if (val) {
1647*7c568831SAndroid Build Coastguard Worker if ((ret->nodesetval->nodeMax == 0) ||
1648*7c568831SAndroid Build Coastguard Worker (val->type == XML_NAMESPACE_DECL))
1649*7c568831SAndroid Build Coastguard Worker {
1650*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetAddUnique(ret->nodesetval, val) < 0)
1651*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
1652*7c568831SAndroid Build Coastguard Worker } else {
1653*7c568831SAndroid Build Coastguard Worker ret->nodesetval->nodeTab[0] = val;
1654*7c568831SAndroid Build Coastguard Worker ret->nodesetval->nodeNr = 1;
1655*7c568831SAndroid Build Coastguard Worker }
1656*7c568831SAndroid Build Coastguard Worker }
1657*7c568831SAndroid Build Coastguard Worker return(ret);
1658*7c568831SAndroid Build Coastguard Worker } else if (cache->miscObjs != NULL) {
1659*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr set;
1660*7c568831SAndroid Build Coastguard Worker /*
1661*7c568831SAndroid Build Coastguard Worker * Fallback to misc-cache.
1662*7c568831SAndroid Build Coastguard Worker */
1663*7c568831SAndroid Build Coastguard Worker
1664*7c568831SAndroid Build Coastguard Worker set = xmlXPathNodeSetCreate(val);
1665*7c568831SAndroid Build Coastguard Worker if (set == NULL) {
1666*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
1667*7c568831SAndroid Build Coastguard Worker return(NULL);
1668*7c568831SAndroid Build Coastguard Worker }
1669*7c568831SAndroid Build Coastguard Worker
1670*7c568831SAndroid Build Coastguard Worker ret = cache->miscObjs;
1671*7c568831SAndroid Build Coastguard Worker cache->miscObjs = (void *) ret->stringval;
1672*7c568831SAndroid Build Coastguard Worker cache->numMisc -= 1;
1673*7c568831SAndroid Build Coastguard Worker ret->stringval = NULL;
1674*7c568831SAndroid Build Coastguard Worker ret->type = XPATH_NODESET;
1675*7c568831SAndroid Build Coastguard Worker ret->boolval = 0;
1676*7c568831SAndroid Build Coastguard Worker ret->nodesetval = set;
1677*7c568831SAndroid Build Coastguard Worker return(ret);
1678*7c568831SAndroid Build Coastguard Worker }
1679*7c568831SAndroid Build Coastguard Worker }
1680*7c568831SAndroid Build Coastguard Worker ret = xmlXPathNewNodeSet(val);
1681*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
1682*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
1683*7c568831SAndroid Build Coastguard Worker return(ret);
1684*7c568831SAndroid Build Coastguard Worker }
1685*7c568831SAndroid Build Coastguard Worker
1686*7c568831SAndroid Build Coastguard Worker /**
1687*7c568831SAndroid Build Coastguard Worker * xmlXPathCacheNewString:
1688*7c568831SAndroid Build Coastguard Worker * @pctxt the XPath context
1689*7c568831SAndroid Build Coastguard Worker * @val: the xmlChar * value
1690*7c568831SAndroid Build Coastguard Worker *
1691*7c568831SAndroid Build Coastguard Worker * This is the cached version of xmlXPathNewString().
1692*7c568831SAndroid Build Coastguard Worker * Acquire an xmlXPathObjectPtr of type string and of value @val
1693*7c568831SAndroid Build Coastguard Worker *
1694*7c568831SAndroid Build Coastguard Worker * Returns the created or reused object.
1695*7c568831SAndroid Build Coastguard Worker */
1696*7c568831SAndroid Build Coastguard Worker static xmlXPathObjectPtr
xmlXPathCacheNewString(xmlXPathParserContextPtr pctxt,const xmlChar * val)1697*7c568831SAndroid Build Coastguard Worker xmlXPathCacheNewString(xmlXPathParserContextPtr pctxt, const xmlChar *val)
1698*7c568831SAndroid Build Coastguard Worker {
1699*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
1700*7c568831SAndroid Build Coastguard Worker xmlXPathContextPtr ctxt = pctxt->context;
1701*7c568831SAndroid Build Coastguard Worker
1702*7c568831SAndroid Build Coastguard Worker if ((ctxt != NULL) && (ctxt->cache != NULL)) {
1703*7c568831SAndroid Build Coastguard Worker xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
1704*7c568831SAndroid Build Coastguard Worker
1705*7c568831SAndroid Build Coastguard Worker if (cache->miscObjs != NULL) {
1706*7c568831SAndroid Build Coastguard Worker xmlChar *copy;
1707*7c568831SAndroid Build Coastguard Worker
1708*7c568831SAndroid Build Coastguard Worker if (val == NULL)
1709*7c568831SAndroid Build Coastguard Worker val = BAD_CAST "";
1710*7c568831SAndroid Build Coastguard Worker copy = xmlStrdup(val);
1711*7c568831SAndroid Build Coastguard Worker if (copy == NULL) {
1712*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
1713*7c568831SAndroid Build Coastguard Worker return(NULL);
1714*7c568831SAndroid Build Coastguard Worker }
1715*7c568831SAndroid Build Coastguard Worker
1716*7c568831SAndroid Build Coastguard Worker ret = cache->miscObjs;
1717*7c568831SAndroid Build Coastguard Worker cache->miscObjs = (void *) ret->stringval;
1718*7c568831SAndroid Build Coastguard Worker cache->numMisc -= 1;
1719*7c568831SAndroid Build Coastguard Worker ret->type = XPATH_STRING;
1720*7c568831SAndroid Build Coastguard Worker ret->stringval = copy;
1721*7c568831SAndroid Build Coastguard Worker return(ret);
1722*7c568831SAndroid Build Coastguard Worker }
1723*7c568831SAndroid Build Coastguard Worker }
1724*7c568831SAndroid Build Coastguard Worker
1725*7c568831SAndroid Build Coastguard Worker ret = xmlXPathNewString(val);
1726*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
1727*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
1728*7c568831SAndroid Build Coastguard Worker return(ret);
1729*7c568831SAndroid Build Coastguard Worker }
1730*7c568831SAndroid Build Coastguard Worker
1731*7c568831SAndroid Build Coastguard Worker /**
1732*7c568831SAndroid Build Coastguard Worker * xmlXPathCacheNewCString:
1733*7c568831SAndroid Build Coastguard Worker * @pctxt the XPath context
1734*7c568831SAndroid Build Coastguard Worker * @val: the char * value
1735*7c568831SAndroid Build Coastguard Worker *
1736*7c568831SAndroid Build Coastguard Worker * This is the cached version of xmlXPathNewCString().
1737*7c568831SAndroid Build Coastguard Worker * Acquire an xmlXPathObjectPtr of type string and of value @val
1738*7c568831SAndroid Build Coastguard Worker *
1739*7c568831SAndroid Build Coastguard Worker * Returns the created or reused object.
1740*7c568831SAndroid Build Coastguard Worker */
1741*7c568831SAndroid Build Coastguard Worker static xmlXPathObjectPtr
xmlXPathCacheNewCString(xmlXPathParserContextPtr pctxt,const char * val)1742*7c568831SAndroid Build Coastguard Worker xmlXPathCacheNewCString(xmlXPathParserContextPtr pctxt, const char *val)
1743*7c568831SAndroid Build Coastguard Worker {
1744*7c568831SAndroid Build Coastguard Worker return xmlXPathCacheNewString(pctxt, BAD_CAST val);
1745*7c568831SAndroid Build Coastguard Worker }
1746*7c568831SAndroid Build Coastguard Worker
1747*7c568831SAndroid Build Coastguard Worker /**
1748*7c568831SAndroid Build Coastguard Worker * xmlXPathCacheNewBoolean:
1749*7c568831SAndroid Build Coastguard Worker * @pctxt the XPath context
1750*7c568831SAndroid Build Coastguard Worker * @val: the boolean value
1751*7c568831SAndroid Build Coastguard Worker *
1752*7c568831SAndroid Build Coastguard Worker * This is the cached version of xmlXPathNewBoolean().
1753*7c568831SAndroid Build Coastguard Worker * Acquires an xmlXPathObjectPtr of type boolean and of value @val
1754*7c568831SAndroid Build Coastguard Worker *
1755*7c568831SAndroid Build Coastguard Worker * Returns the created or reused object.
1756*7c568831SAndroid Build Coastguard Worker */
1757*7c568831SAndroid Build Coastguard Worker static xmlXPathObjectPtr
xmlXPathCacheNewBoolean(xmlXPathParserContextPtr pctxt,int val)1758*7c568831SAndroid Build Coastguard Worker xmlXPathCacheNewBoolean(xmlXPathParserContextPtr pctxt, int val)
1759*7c568831SAndroid Build Coastguard Worker {
1760*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
1761*7c568831SAndroid Build Coastguard Worker xmlXPathContextPtr ctxt = pctxt->context;
1762*7c568831SAndroid Build Coastguard Worker
1763*7c568831SAndroid Build Coastguard Worker if ((ctxt != NULL) && (ctxt->cache != NULL)) {
1764*7c568831SAndroid Build Coastguard Worker xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
1765*7c568831SAndroid Build Coastguard Worker
1766*7c568831SAndroid Build Coastguard Worker if (cache->miscObjs != NULL) {
1767*7c568831SAndroid Build Coastguard Worker ret = cache->miscObjs;
1768*7c568831SAndroid Build Coastguard Worker cache->miscObjs = (void *) ret->stringval;
1769*7c568831SAndroid Build Coastguard Worker cache->numMisc -= 1;
1770*7c568831SAndroid Build Coastguard Worker ret->stringval = NULL;
1771*7c568831SAndroid Build Coastguard Worker ret->type = XPATH_BOOLEAN;
1772*7c568831SAndroid Build Coastguard Worker ret->boolval = (val != 0);
1773*7c568831SAndroid Build Coastguard Worker return(ret);
1774*7c568831SAndroid Build Coastguard Worker }
1775*7c568831SAndroid Build Coastguard Worker }
1776*7c568831SAndroid Build Coastguard Worker
1777*7c568831SAndroid Build Coastguard Worker ret = xmlXPathNewBoolean(val);
1778*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
1779*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
1780*7c568831SAndroid Build Coastguard Worker return(ret);
1781*7c568831SAndroid Build Coastguard Worker }
1782*7c568831SAndroid Build Coastguard Worker
1783*7c568831SAndroid Build Coastguard Worker /**
1784*7c568831SAndroid Build Coastguard Worker * xmlXPathCacheNewFloat:
1785*7c568831SAndroid Build Coastguard Worker * @pctxt the XPath context
1786*7c568831SAndroid Build Coastguard Worker * @val: the double value
1787*7c568831SAndroid Build Coastguard Worker *
1788*7c568831SAndroid Build Coastguard Worker * This is the cached version of xmlXPathNewFloat().
1789*7c568831SAndroid Build Coastguard Worker * Acquires an xmlXPathObjectPtr of type double and of value @val
1790*7c568831SAndroid Build Coastguard Worker *
1791*7c568831SAndroid Build Coastguard Worker * Returns the created or reused object.
1792*7c568831SAndroid Build Coastguard Worker */
1793*7c568831SAndroid Build Coastguard Worker static xmlXPathObjectPtr
xmlXPathCacheNewFloat(xmlXPathParserContextPtr pctxt,double val)1794*7c568831SAndroid Build Coastguard Worker xmlXPathCacheNewFloat(xmlXPathParserContextPtr pctxt, double val)
1795*7c568831SAndroid Build Coastguard Worker {
1796*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
1797*7c568831SAndroid Build Coastguard Worker xmlXPathContextPtr ctxt = pctxt->context;
1798*7c568831SAndroid Build Coastguard Worker
1799*7c568831SAndroid Build Coastguard Worker if ((ctxt != NULL) && (ctxt->cache != NULL)) {
1800*7c568831SAndroid Build Coastguard Worker xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
1801*7c568831SAndroid Build Coastguard Worker
1802*7c568831SAndroid Build Coastguard Worker if (cache->miscObjs != NULL) {
1803*7c568831SAndroid Build Coastguard Worker ret = cache->miscObjs;
1804*7c568831SAndroid Build Coastguard Worker cache->miscObjs = (void *) ret->stringval;
1805*7c568831SAndroid Build Coastguard Worker cache->numMisc -= 1;
1806*7c568831SAndroid Build Coastguard Worker ret->stringval = NULL;
1807*7c568831SAndroid Build Coastguard Worker ret->type = XPATH_NUMBER;
1808*7c568831SAndroid Build Coastguard Worker ret->floatval = val;
1809*7c568831SAndroid Build Coastguard Worker return(ret);
1810*7c568831SAndroid Build Coastguard Worker }
1811*7c568831SAndroid Build Coastguard Worker }
1812*7c568831SAndroid Build Coastguard Worker
1813*7c568831SAndroid Build Coastguard Worker ret = xmlXPathNewFloat(val);
1814*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
1815*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
1816*7c568831SAndroid Build Coastguard Worker return(ret);
1817*7c568831SAndroid Build Coastguard Worker }
1818*7c568831SAndroid Build Coastguard Worker
1819*7c568831SAndroid Build Coastguard Worker /**
1820*7c568831SAndroid Build Coastguard Worker * xmlXPathCacheObjectCopy:
1821*7c568831SAndroid Build Coastguard Worker * @pctxt the XPath context
1822*7c568831SAndroid Build Coastguard Worker * @val: the original object
1823*7c568831SAndroid Build Coastguard Worker *
1824*7c568831SAndroid Build Coastguard Worker * This is the cached version of xmlXPathObjectCopy().
1825*7c568831SAndroid Build Coastguard Worker * Acquire a copy of a given object
1826*7c568831SAndroid Build Coastguard Worker *
1827*7c568831SAndroid Build Coastguard Worker * Returns a created or reused created object.
1828*7c568831SAndroid Build Coastguard Worker */
1829*7c568831SAndroid Build Coastguard Worker static xmlXPathObjectPtr
xmlXPathCacheObjectCopy(xmlXPathParserContextPtr pctxt,xmlXPathObjectPtr val)1830*7c568831SAndroid Build Coastguard Worker xmlXPathCacheObjectCopy(xmlXPathParserContextPtr pctxt, xmlXPathObjectPtr val)
1831*7c568831SAndroid Build Coastguard Worker {
1832*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
1833*7c568831SAndroid Build Coastguard Worker xmlXPathContextPtr ctxt = pctxt->context;
1834*7c568831SAndroid Build Coastguard Worker
1835*7c568831SAndroid Build Coastguard Worker if (val == NULL)
1836*7c568831SAndroid Build Coastguard Worker return(NULL);
1837*7c568831SAndroid Build Coastguard Worker
1838*7c568831SAndroid Build Coastguard Worker if ((ctxt != NULL) && (ctxt->cache != NULL)) {
1839*7c568831SAndroid Build Coastguard Worker switch (val->type) {
1840*7c568831SAndroid Build Coastguard Worker case XPATH_NODESET: {
1841*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr set;
1842*7c568831SAndroid Build Coastguard Worker
1843*7c568831SAndroid Build Coastguard Worker set = xmlXPathNodeSetMerge(NULL, val->nodesetval);
1844*7c568831SAndroid Build Coastguard Worker if (set == NULL) {
1845*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
1846*7c568831SAndroid Build Coastguard Worker return(NULL);
1847*7c568831SAndroid Build Coastguard Worker }
1848*7c568831SAndroid Build Coastguard Worker return(xmlXPathCacheWrapNodeSet(pctxt, set));
1849*7c568831SAndroid Build Coastguard Worker }
1850*7c568831SAndroid Build Coastguard Worker case XPATH_STRING:
1851*7c568831SAndroid Build Coastguard Worker return(xmlXPathCacheNewString(pctxt, val->stringval));
1852*7c568831SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
1853*7c568831SAndroid Build Coastguard Worker return(xmlXPathCacheNewBoolean(pctxt, val->boolval));
1854*7c568831SAndroid Build Coastguard Worker case XPATH_NUMBER:
1855*7c568831SAndroid Build Coastguard Worker return(xmlXPathCacheNewFloat(pctxt, val->floatval));
1856*7c568831SAndroid Build Coastguard Worker default:
1857*7c568831SAndroid Build Coastguard Worker break;
1858*7c568831SAndroid Build Coastguard Worker }
1859*7c568831SAndroid Build Coastguard Worker }
1860*7c568831SAndroid Build Coastguard Worker ret = xmlXPathObjectCopy(val);
1861*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
1862*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
1863*7c568831SAndroid Build Coastguard Worker return(ret);
1864*7c568831SAndroid Build Coastguard Worker }
1865*7c568831SAndroid Build Coastguard Worker
1866*7c568831SAndroid Build Coastguard Worker /************************************************************************
1867*7c568831SAndroid Build Coastguard Worker * *
1868*7c568831SAndroid Build Coastguard Worker * Parser stacks related functions and macros *
1869*7c568831SAndroid Build Coastguard Worker * *
1870*7c568831SAndroid Build Coastguard Worker ************************************************************************/
1871*7c568831SAndroid Build Coastguard Worker
1872*7c568831SAndroid Build Coastguard Worker /**
1873*7c568831SAndroid Build Coastguard Worker * xmlXPathCastToNumberInternal:
1874*7c568831SAndroid Build Coastguard Worker * @ctxt: parser context
1875*7c568831SAndroid Build Coastguard Worker * @val: an XPath object
1876*7c568831SAndroid Build Coastguard Worker *
1877*7c568831SAndroid Build Coastguard Worker * Converts an XPath object to its number value
1878*7c568831SAndroid Build Coastguard Worker *
1879*7c568831SAndroid Build Coastguard Worker * Returns the number value
1880*7c568831SAndroid Build Coastguard Worker */
1881*7c568831SAndroid Build Coastguard Worker static double
xmlXPathCastToNumberInternal(xmlXPathParserContextPtr ctxt,xmlXPathObjectPtr val)1882*7c568831SAndroid Build Coastguard Worker xmlXPathCastToNumberInternal(xmlXPathParserContextPtr ctxt,
1883*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr val) {
1884*7c568831SAndroid Build Coastguard Worker double ret = 0.0;
1885*7c568831SAndroid Build Coastguard Worker
1886*7c568831SAndroid Build Coastguard Worker if (val == NULL)
1887*7c568831SAndroid Build Coastguard Worker return(xmlXPathNAN);
1888*7c568831SAndroid Build Coastguard Worker switch (val->type) {
1889*7c568831SAndroid Build Coastguard Worker case XPATH_UNDEFINED:
1890*7c568831SAndroid Build Coastguard Worker ret = xmlXPathNAN;
1891*7c568831SAndroid Build Coastguard Worker break;
1892*7c568831SAndroid Build Coastguard Worker case XPATH_NODESET:
1893*7c568831SAndroid Build Coastguard Worker case XPATH_XSLT_TREE: {
1894*7c568831SAndroid Build Coastguard Worker xmlChar *str;
1895*7c568831SAndroid Build Coastguard Worker
1896*7c568831SAndroid Build Coastguard Worker str = xmlXPathCastNodeSetToString(val->nodesetval);
1897*7c568831SAndroid Build Coastguard Worker if (str == NULL) {
1898*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
1899*7c568831SAndroid Build Coastguard Worker ret = xmlXPathNAN;
1900*7c568831SAndroid Build Coastguard Worker } else {
1901*7c568831SAndroid Build Coastguard Worker ret = xmlXPathCastStringToNumber(str);
1902*7c568831SAndroid Build Coastguard Worker xmlFree(str);
1903*7c568831SAndroid Build Coastguard Worker }
1904*7c568831SAndroid Build Coastguard Worker break;
1905*7c568831SAndroid Build Coastguard Worker }
1906*7c568831SAndroid Build Coastguard Worker case XPATH_STRING:
1907*7c568831SAndroid Build Coastguard Worker ret = xmlXPathCastStringToNumber(val->stringval);
1908*7c568831SAndroid Build Coastguard Worker break;
1909*7c568831SAndroid Build Coastguard Worker case XPATH_NUMBER:
1910*7c568831SAndroid Build Coastguard Worker ret = val->floatval;
1911*7c568831SAndroid Build Coastguard Worker break;
1912*7c568831SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
1913*7c568831SAndroid Build Coastguard Worker ret = xmlXPathCastBooleanToNumber(val->boolval);
1914*7c568831SAndroid Build Coastguard Worker break;
1915*7c568831SAndroid Build Coastguard Worker case XPATH_USERS:
1916*7c568831SAndroid Build Coastguard Worker /* TODO */
1917*7c568831SAndroid Build Coastguard Worker ret = xmlXPathNAN;
1918*7c568831SAndroid Build Coastguard Worker break;
1919*7c568831SAndroid Build Coastguard Worker }
1920*7c568831SAndroid Build Coastguard Worker return(ret);
1921*7c568831SAndroid Build Coastguard Worker }
1922*7c568831SAndroid Build Coastguard Worker
1923*7c568831SAndroid Build Coastguard Worker /**
1924*7c568831SAndroid Build Coastguard Worker * valuePop:
1925*7c568831SAndroid Build Coastguard Worker * @ctxt: an XPath evaluation context
1926*7c568831SAndroid Build Coastguard Worker *
1927*7c568831SAndroid Build Coastguard Worker * Pops the top XPath object from the value stack
1928*7c568831SAndroid Build Coastguard Worker *
1929*7c568831SAndroid Build Coastguard Worker * Returns the XPath object just removed
1930*7c568831SAndroid Build Coastguard Worker */
1931*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
valuePop(xmlXPathParserContextPtr ctxt)1932*7c568831SAndroid Build Coastguard Worker valuePop(xmlXPathParserContextPtr ctxt)
1933*7c568831SAndroid Build Coastguard Worker {
1934*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
1935*7c568831SAndroid Build Coastguard Worker
1936*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->valueNr <= 0))
1937*7c568831SAndroid Build Coastguard Worker return (NULL);
1938*7c568831SAndroid Build Coastguard Worker
1939*7c568831SAndroid Build Coastguard Worker ctxt->valueNr--;
1940*7c568831SAndroid Build Coastguard Worker if (ctxt->valueNr > 0)
1941*7c568831SAndroid Build Coastguard Worker ctxt->value = ctxt->valueTab[ctxt->valueNr - 1];
1942*7c568831SAndroid Build Coastguard Worker else
1943*7c568831SAndroid Build Coastguard Worker ctxt->value = NULL;
1944*7c568831SAndroid Build Coastguard Worker ret = ctxt->valueTab[ctxt->valueNr];
1945*7c568831SAndroid Build Coastguard Worker ctxt->valueTab[ctxt->valueNr] = NULL;
1946*7c568831SAndroid Build Coastguard Worker return (ret);
1947*7c568831SAndroid Build Coastguard Worker }
1948*7c568831SAndroid Build Coastguard Worker /**
1949*7c568831SAndroid Build Coastguard Worker * valuePush:
1950*7c568831SAndroid Build Coastguard Worker * @ctxt: an XPath evaluation context
1951*7c568831SAndroid Build Coastguard Worker * @value: the XPath object
1952*7c568831SAndroid Build Coastguard Worker *
1953*7c568831SAndroid Build Coastguard Worker * Pushes a new XPath object on top of the value stack. If value is NULL,
1954*7c568831SAndroid Build Coastguard Worker * a memory error is recorded in the parser context.
1955*7c568831SAndroid Build Coastguard Worker *
1956*7c568831SAndroid Build Coastguard Worker * Returns the number of items on the value stack, or -1 in case of error.
1957*7c568831SAndroid Build Coastguard Worker *
1958*7c568831SAndroid Build Coastguard Worker * The object is destroyed in case of error.
1959*7c568831SAndroid Build Coastguard Worker */
1960*7c568831SAndroid Build Coastguard Worker int
valuePush(xmlXPathParserContextPtr ctxt,xmlXPathObjectPtr value)1961*7c568831SAndroid Build Coastguard Worker valuePush(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value)
1962*7c568831SAndroid Build Coastguard Worker {
1963*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL) return(-1);
1964*7c568831SAndroid Build Coastguard Worker if (value == NULL) {
1965*7c568831SAndroid Build Coastguard Worker /*
1966*7c568831SAndroid Build Coastguard Worker * A NULL value typically indicates that a memory allocation failed.
1967*7c568831SAndroid Build Coastguard Worker */
1968*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
1969*7c568831SAndroid Build Coastguard Worker return(-1);
1970*7c568831SAndroid Build Coastguard Worker }
1971*7c568831SAndroid Build Coastguard Worker if (ctxt->valueNr >= ctxt->valueMax) {
1972*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr *tmp;
1973*7c568831SAndroid Build Coastguard Worker
1974*7c568831SAndroid Build Coastguard Worker if (ctxt->valueMax >= XPATH_MAX_STACK_DEPTH) {
1975*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
1976*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(value);
1977*7c568831SAndroid Build Coastguard Worker return (-1);
1978*7c568831SAndroid Build Coastguard Worker }
1979*7c568831SAndroid Build Coastguard Worker tmp = (xmlXPathObjectPtr *) xmlRealloc(ctxt->valueTab,
1980*7c568831SAndroid Build Coastguard Worker 2 * ctxt->valueMax *
1981*7c568831SAndroid Build Coastguard Worker sizeof(ctxt->valueTab[0]));
1982*7c568831SAndroid Build Coastguard Worker if (tmp == NULL) {
1983*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
1984*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(value);
1985*7c568831SAndroid Build Coastguard Worker return (-1);
1986*7c568831SAndroid Build Coastguard Worker }
1987*7c568831SAndroid Build Coastguard Worker ctxt->valueMax *= 2;
1988*7c568831SAndroid Build Coastguard Worker ctxt->valueTab = tmp;
1989*7c568831SAndroid Build Coastguard Worker }
1990*7c568831SAndroid Build Coastguard Worker ctxt->valueTab[ctxt->valueNr] = value;
1991*7c568831SAndroid Build Coastguard Worker ctxt->value = value;
1992*7c568831SAndroid Build Coastguard Worker return (ctxt->valueNr++);
1993*7c568831SAndroid Build Coastguard Worker }
1994*7c568831SAndroid Build Coastguard Worker
1995*7c568831SAndroid Build Coastguard Worker /**
1996*7c568831SAndroid Build Coastguard Worker * xmlXPathPopBoolean:
1997*7c568831SAndroid Build Coastguard Worker * @ctxt: an XPath parser context
1998*7c568831SAndroid Build Coastguard Worker *
1999*7c568831SAndroid Build Coastguard Worker * Pops a boolean from the stack, handling conversion if needed.
2000*7c568831SAndroid Build Coastguard Worker * Check error with #xmlXPathCheckError.
2001*7c568831SAndroid Build Coastguard Worker *
2002*7c568831SAndroid Build Coastguard Worker * Returns the boolean
2003*7c568831SAndroid Build Coastguard Worker */
2004*7c568831SAndroid Build Coastguard Worker int
xmlXPathPopBoolean(xmlXPathParserContextPtr ctxt)2005*7c568831SAndroid Build Coastguard Worker xmlXPathPopBoolean (xmlXPathParserContextPtr ctxt) {
2006*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr obj;
2007*7c568831SAndroid Build Coastguard Worker int ret;
2008*7c568831SAndroid Build Coastguard Worker
2009*7c568831SAndroid Build Coastguard Worker obj = valuePop(ctxt);
2010*7c568831SAndroid Build Coastguard Worker if (obj == NULL) {
2011*7c568831SAndroid Build Coastguard Worker xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
2012*7c568831SAndroid Build Coastguard Worker return(0);
2013*7c568831SAndroid Build Coastguard Worker }
2014*7c568831SAndroid Build Coastguard Worker if (obj->type != XPATH_BOOLEAN)
2015*7c568831SAndroid Build Coastguard Worker ret = xmlXPathCastToBoolean(obj);
2016*7c568831SAndroid Build Coastguard Worker else
2017*7c568831SAndroid Build Coastguard Worker ret = obj->boolval;
2018*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, obj);
2019*7c568831SAndroid Build Coastguard Worker return(ret);
2020*7c568831SAndroid Build Coastguard Worker }
2021*7c568831SAndroid Build Coastguard Worker
2022*7c568831SAndroid Build Coastguard Worker /**
2023*7c568831SAndroid Build Coastguard Worker * xmlXPathPopNumber:
2024*7c568831SAndroid Build Coastguard Worker * @ctxt: an XPath parser context
2025*7c568831SAndroid Build Coastguard Worker *
2026*7c568831SAndroid Build Coastguard Worker * Pops a number from the stack, handling conversion if needed.
2027*7c568831SAndroid Build Coastguard Worker * Check error with #xmlXPathCheckError.
2028*7c568831SAndroid Build Coastguard Worker *
2029*7c568831SAndroid Build Coastguard Worker * Returns the number
2030*7c568831SAndroid Build Coastguard Worker */
2031*7c568831SAndroid Build Coastguard Worker double
xmlXPathPopNumber(xmlXPathParserContextPtr ctxt)2032*7c568831SAndroid Build Coastguard Worker xmlXPathPopNumber (xmlXPathParserContextPtr ctxt) {
2033*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr obj;
2034*7c568831SAndroid Build Coastguard Worker double ret;
2035*7c568831SAndroid Build Coastguard Worker
2036*7c568831SAndroid Build Coastguard Worker obj = valuePop(ctxt);
2037*7c568831SAndroid Build Coastguard Worker if (obj == NULL) {
2038*7c568831SAndroid Build Coastguard Worker xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
2039*7c568831SAndroid Build Coastguard Worker return(0);
2040*7c568831SAndroid Build Coastguard Worker }
2041*7c568831SAndroid Build Coastguard Worker if (obj->type != XPATH_NUMBER)
2042*7c568831SAndroid Build Coastguard Worker ret = xmlXPathCastToNumberInternal(ctxt, obj);
2043*7c568831SAndroid Build Coastguard Worker else
2044*7c568831SAndroid Build Coastguard Worker ret = obj->floatval;
2045*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, obj);
2046*7c568831SAndroid Build Coastguard Worker return(ret);
2047*7c568831SAndroid Build Coastguard Worker }
2048*7c568831SAndroid Build Coastguard Worker
2049*7c568831SAndroid Build Coastguard Worker /**
2050*7c568831SAndroid Build Coastguard Worker * xmlXPathPopString:
2051*7c568831SAndroid Build Coastguard Worker * @ctxt: an XPath parser context
2052*7c568831SAndroid Build Coastguard Worker *
2053*7c568831SAndroid Build Coastguard Worker * Pops a string from the stack, handling conversion if needed.
2054*7c568831SAndroid Build Coastguard Worker * Check error with #xmlXPathCheckError.
2055*7c568831SAndroid Build Coastguard Worker *
2056*7c568831SAndroid Build Coastguard Worker * Returns the string
2057*7c568831SAndroid Build Coastguard Worker */
2058*7c568831SAndroid Build Coastguard Worker xmlChar *
xmlXPathPopString(xmlXPathParserContextPtr ctxt)2059*7c568831SAndroid Build Coastguard Worker xmlXPathPopString (xmlXPathParserContextPtr ctxt) {
2060*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr obj;
2061*7c568831SAndroid Build Coastguard Worker xmlChar * ret;
2062*7c568831SAndroid Build Coastguard Worker
2063*7c568831SAndroid Build Coastguard Worker obj = valuePop(ctxt);
2064*7c568831SAndroid Build Coastguard Worker if (obj == NULL) {
2065*7c568831SAndroid Build Coastguard Worker xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
2066*7c568831SAndroid Build Coastguard Worker return(NULL);
2067*7c568831SAndroid Build Coastguard Worker }
2068*7c568831SAndroid Build Coastguard Worker ret = xmlXPathCastToString(obj);
2069*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
2070*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
2071*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, obj);
2072*7c568831SAndroid Build Coastguard Worker return(ret);
2073*7c568831SAndroid Build Coastguard Worker }
2074*7c568831SAndroid Build Coastguard Worker
2075*7c568831SAndroid Build Coastguard Worker /**
2076*7c568831SAndroid Build Coastguard Worker * xmlXPathPopNodeSet:
2077*7c568831SAndroid Build Coastguard Worker * @ctxt: an XPath parser context
2078*7c568831SAndroid Build Coastguard Worker *
2079*7c568831SAndroid Build Coastguard Worker * Pops a node-set from the stack, handling conversion if needed.
2080*7c568831SAndroid Build Coastguard Worker * Check error with #xmlXPathCheckError.
2081*7c568831SAndroid Build Coastguard Worker *
2082*7c568831SAndroid Build Coastguard Worker * Returns the node-set
2083*7c568831SAndroid Build Coastguard Worker */
2084*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathPopNodeSet(xmlXPathParserContextPtr ctxt)2085*7c568831SAndroid Build Coastguard Worker xmlXPathPopNodeSet (xmlXPathParserContextPtr ctxt) {
2086*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr obj;
2087*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr ret;
2088*7c568831SAndroid Build Coastguard Worker
2089*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL) return(NULL);
2090*7c568831SAndroid Build Coastguard Worker if (ctxt->value == NULL) {
2091*7c568831SAndroid Build Coastguard Worker xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
2092*7c568831SAndroid Build Coastguard Worker return(NULL);
2093*7c568831SAndroid Build Coastguard Worker }
2094*7c568831SAndroid Build Coastguard Worker if (!xmlXPathStackIsNodeSet(ctxt)) {
2095*7c568831SAndroid Build Coastguard Worker xmlXPathSetTypeError(ctxt);
2096*7c568831SAndroid Build Coastguard Worker return(NULL);
2097*7c568831SAndroid Build Coastguard Worker }
2098*7c568831SAndroid Build Coastguard Worker obj = valuePop(ctxt);
2099*7c568831SAndroid Build Coastguard Worker ret = obj->nodesetval;
2100*7c568831SAndroid Build Coastguard Worker obj->nodesetval = NULL;
2101*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, obj);
2102*7c568831SAndroid Build Coastguard Worker return(ret);
2103*7c568831SAndroid Build Coastguard Worker }
2104*7c568831SAndroid Build Coastguard Worker
2105*7c568831SAndroid Build Coastguard Worker /**
2106*7c568831SAndroid Build Coastguard Worker * xmlXPathPopExternal:
2107*7c568831SAndroid Build Coastguard Worker * @ctxt: an XPath parser context
2108*7c568831SAndroid Build Coastguard Worker *
2109*7c568831SAndroid Build Coastguard Worker * Pops an external object from the stack, handling conversion if needed.
2110*7c568831SAndroid Build Coastguard Worker * Check error with #xmlXPathCheckError.
2111*7c568831SAndroid Build Coastguard Worker *
2112*7c568831SAndroid Build Coastguard Worker * Returns the object
2113*7c568831SAndroid Build Coastguard Worker */
2114*7c568831SAndroid Build Coastguard Worker void *
xmlXPathPopExternal(xmlXPathParserContextPtr ctxt)2115*7c568831SAndroid Build Coastguard Worker xmlXPathPopExternal (xmlXPathParserContextPtr ctxt) {
2116*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr obj;
2117*7c568831SAndroid Build Coastguard Worker void * ret;
2118*7c568831SAndroid Build Coastguard Worker
2119*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->value == NULL)) {
2120*7c568831SAndroid Build Coastguard Worker xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
2121*7c568831SAndroid Build Coastguard Worker return(NULL);
2122*7c568831SAndroid Build Coastguard Worker }
2123*7c568831SAndroid Build Coastguard Worker if (ctxt->value->type != XPATH_USERS) {
2124*7c568831SAndroid Build Coastguard Worker xmlXPathSetTypeError(ctxt);
2125*7c568831SAndroid Build Coastguard Worker return(NULL);
2126*7c568831SAndroid Build Coastguard Worker }
2127*7c568831SAndroid Build Coastguard Worker obj = valuePop(ctxt);
2128*7c568831SAndroid Build Coastguard Worker ret = obj->user;
2129*7c568831SAndroid Build Coastguard Worker obj->user = NULL;
2130*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, obj);
2131*7c568831SAndroid Build Coastguard Worker return(ret);
2132*7c568831SAndroid Build Coastguard Worker }
2133*7c568831SAndroid Build Coastguard Worker
2134*7c568831SAndroid Build Coastguard Worker /*
2135*7c568831SAndroid Build Coastguard Worker * Macros for accessing the content. Those should be used only by the parser,
2136*7c568831SAndroid Build Coastguard Worker * and not exported.
2137*7c568831SAndroid Build Coastguard Worker *
2138*7c568831SAndroid Build Coastguard Worker * Dirty macros, i.e. one need to make assumption on the context to use them
2139*7c568831SAndroid Build Coastguard Worker *
2140*7c568831SAndroid Build Coastguard Worker * CUR_PTR return the current pointer to the xmlChar to be parsed.
2141*7c568831SAndroid Build Coastguard Worker * CUR returns the current xmlChar value, i.e. a 8 bit value
2142*7c568831SAndroid Build Coastguard Worker * in ISO-Latin or UTF-8.
2143*7c568831SAndroid Build Coastguard Worker * This should be used internally by the parser
2144*7c568831SAndroid Build Coastguard Worker * only to compare to ASCII values otherwise it would break when
2145*7c568831SAndroid Build Coastguard Worker * running with UTF-8 encoding.
2146*7c568831SAndroid Build Coastguard Worker * NXT(n) returns the n'th next xmlChar. Same as CUR is should be used only
2147*7c568831SAndroid Build Coastguard Worker * to compare on ASCII based substring.
2148*7c568831SAndroid Build Coastguard Worker * SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
2149*7c568831SAndroid Build Coastguard Worker * strings within the parser.
2150*7c568831SAndroid Build Coastguard Worker * CURRENT Returns the current char value, with the full decoding of
2151*7c568831SAndroid Build Coastguard Worker * UTF-8 if we are using this mode. It returns an int.
2152*7c568831SAndroid Build Coastguard Worker * NEXT Skip to the next character, this does the proper decoding
2153*7c568831SAndroid Build Coastguard Worker * in UTF-8 mode. It also pop-up unfinished entities on the fly.
2154*7c568831SAndroid Build Coastguard Worker * It returns the pointer to the current xmlChar.
2155*7c568831SAndroid Build Coastguard Worker */
2156*7c568831SAndroid Build Coastguard Worker
2157*7c568831SAndroid Build Coastguard Worker #define CUR (*ctxt->cur)
2158*7c568831SAndroid Build Coastguard Worker #define SKIP(val) ctxt->cur += (val)
2159*7c568831SAndroid Build Coastguard Worker #define NXT(val) ctxt->cur[(val)]
2160*7c568831SAndroid Build Coastguard Worker #define CUR_PTR ctxt->cur
2161*7c568831SAndroid Build Coastguard Worker #define CUR_CHAR(l) xmlXPathCurrentChar(ctxt, &l)
2162*7c568831SAndroid Build Coastguard Worker
2163*7c568831SAndroid Build Coastguard Worker #define COPY_BUF(b, i, v) \
2164*7c568831SAndroid Build Coastguard Worker if (v < 0x80) b[i++] = v; \
2165*7c568831SAndroid Build Coastguard Worker else i += xmlCopyCharMultiByte(&b[i],v)
2166*7c568831SAndroid Build Coastguard Worker
2167*7c568831SAndroid Build Coastguard Worker #define NEXTL(l) ctxt->cur += l
2168*7c568831SAndroid Build Coastguard Worker
2169*7c568831SAndroid Build Coastguard Worker #define SKIP_BLANKS \
2170*7c568831SAndroid Build Coastguard Worker while (IS_BLANK_CH(*(ctxt->cur))) NEXT
2171*7c568831SAndroid Build Coastguard Worker
2172*7c568831SAndroid Build Coastguard Worker #define CURRENT (*ctxt->cur)
2173*7c568831SAndroid Build Coastguard Worker #define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur)
2174*7c568831SAndroid Build Coastguard Worker
2175*7c568831SAndroid Build Coastguard Worker
2176*7c568831SAndroid Build Coastguard Worker #ifndef DBL_DIG
2177*7c568831SAndroid Build Coastguard Worker #define DBL_DIG 16
2178*7c568831SAndroid Build Coastguard Worker #endif
2179*7c568831SAndroid Build Coastguard Worker #ifndef DBL_EPSILON
2180*7c568831SAndroid Build Coastguard Worker #define DBL_EPSILON 1E-9
2181*7c568831SAndroid Build Coastguard Worker #endif
2182*7c568831SAndroid Build Coastguard Worker
2183*7c568831SAndroid Build Coastguard Worker #define UPPER_DOUBLE 1E9
2184*7c568831SAndroid Build Coastguard Worker #define LOWER_DOUBLE 1E-5
2185*7c568831SAndroid Build Coastguard Worker #define LOWER_DOUBLE_EXP 5
2186*7c568831SAndroid Build Coastguard Worker
2187*7c568831SAndroid Build Coastguard Worker #define INTEGER_DIGITS DBL_DIG
2188*7c568831SAndroid Build Coastguard Worker #define FRACTION_DIGITS (DBL_DIG + 1 + (LOWER_DOUBLE_EXP))
2189*7c568831SAndroid Build Coastguard Worker #define EXPONENT_DIGITS (3 + 2)
2190*7c568831SAndroid Build Coastguard Worker
2191*7c568831SAndroid Build Coastguard Worker /**
2192*7c568831SAndroid Build Coastguard Worker * xmlXPathFormatNumber:
2193*7c568831SAndroid Build Coastguard Worker * @number: number to format
2194*7c568831SAndroid Build Coastguard Worker * @buffer: output buffer
2195*7c568831SAndroid Build Coastguard Worker * @buffersize: size of output buffer
2196*7c568831SAndroid Build Coastguard Worker *
2197*7c568831SAndroid Build Coastguard Worker * Convert the number into a string representation.
2198*7c568831SAndroid Build Coastguard Worker */
2199*7c568831SAndroid Build Coastguard Worker static void
xmlXPathFormatNumber(double number,char buffer[],int buffersize)2200*7c568831SAndroid Build Coastguard Worker xmlXPathFormatNumber(double number, char buffer[], int buffersize)
2201*7c568831SAndroid Build Coastguard Worker {
2202*7c568831SAndroid Build Coastguard Worker switch (xmlXPathIsInf(number)) {
2203*7c568831SAndroid Build Coastguard Worker case 1:
2204*7c568831SAndroid Build Coastguard Worker if (buffersize > (int)sizeof("Infinity"))
2205*7c568831SAndroid Build Coastguard Worker snprintf(buffer, buffersize, "Infinity");
2206*7c568831SAndroid Build Coastguard Worker break;
2207*7c568831SAndroid Build Coastguard Worker case -1:
2208*7c568831SAndroid Build Coastguard Worker if (buffersize > (int)sizeof("-Infinity"))
2209*7c568831SAndroid Build Coastguard Worker snprintf(buffer, buffersize, "-Infinity");
2210*7c568831SAndroid Build Coastguard Worker break;
2211*7c568831SAndroid Build Coastguard Worker default:
2212*7c568831SAndroid Build Coastguard Worker if (xmlXPathIsNaN(number)) {
2213*7c568831SAndroid Build Coastguard Worker if (buffersize > (int)sizeof("NaN"))
2214*7c568831SAndroid Build Coastguard Worker snprintf(buffer, buffersize, "NaN");
2215*7c568831SAndroid Build Coastguard Worker } else if (number == 0) {
2216*7c568831SAndroid Build Coastguard Worker /* Omit sign for negative zero. */
2217*7c568831SAndroid Build Coastguard Worker snprintf(buffer, buffersize, "0");
2218*7c568831SAndroid Build Coastguard Worker } else if ((number > INT_MIN) && (number < INT_MAX) &&
2219*7c568831SAndroid Build Coastguard Worker (number == (int) number)) {
2220*7c568831SAndroid Build Coastguard Worker char work[30];
2221*7c568831SAndroid Build Coastguard Worker char *ptr, *cur;
2222*7c568831SAndroid Build Coastguard Worker int value = (int) number;
2223*7c568831SAndroid Build Coastguard Worker
2224*7c568831SAndroid Build Coastguard Worker ptr = &buffer[0];
2225*7c568831SAndroid Build Coastguard Worker if (value == 0) {
2226*7c568831SAndroid Build Coastguard Worker *ptr++ = '0';
2227*7c568831SAndroid Build Coastguard Worker } else {
2228*7c568831SAndroid Build Coastguard Worker snprintf(work, 29, "%d", value);
2229*7c568831SAndroid Build Coastguard Worker cur = &work[0];
2230*7c568831SAndroid Build Coastguard Worker while ((*cur) && (ptr - buffer < buffersize)) {
2231*7c568831SAndroid Build Coastguard Worker *ptr++ = *cur++;
2232*7c568831SAndroid Build Coastguard Worker }
2233*7c568831SAndroid Build Coastguard Worker }
2234*7c568831SAndroid Build Coastguard Worker if (ptr - buffer < buffersize) {
2235*7c568831SAndroid Build Coastguard Worker *ptr = 0;
2236*7c568831SAndroid Build Coastguard Worker } else if (buffersize > 0) {
2237*7c568831SAndroid Build Coastguard Worker ptr--;
2238*7c568831SAndroid Build Coastguard Worker *ptr = 0;
2239*7c568831SAndroid Build Coastguard Worker }
2240*7c568831SAndroid Build Coastguard Worker } else {
2241*7c568831SAndroid Build Coastguard Worker /*
2242*7c568831SAndroid Build Coastguard Worker For the dimension of work,
2243*7c568831SAndroid Build Coastguard Worker DBL_DIG is number of significant digits
2244*7c568831SAndroid Build Coastguard Worker EXPONENT is only needed for "scientific notation"
2245*7c568831SAndroid Build Coastguard Worker 3 is sign, decimal point, and terminating zero
2246*7c568831SAndroid Build Coastguard Worker LOWER_DOUBLE_EXP is max number of leading zeroes in fraction
2247*7c568831SAndroid Build Coastguard Worker Note that this dimension is slightly (a few characters)
2248*7c568831SAndroid Build Coastguard Worker larger than actually necessary.
2249*7c568831SAndroid Build Coastguard Worker */
2250*7c568831SAndroid Build Coastguard Worker char work[DBL_DIG + EXPONENT_DIGITS + 3 + LOWER_DOUBLE_EXP];
2251*7c568831SAndroid Build Coastguard Worker int integer_place, fraction_place;
2252*7c568831SAndroid Build Coastguard Worker char *ptr;
2253*7c568831SAndroid Build Coastguard Worker char *after_fraction;
2254*7c568831SAndroid Build Coastguard Worker double absolute_value;
2255*7c568831SAndroid Build Coastguard Worker int size;
2256*7c568831SAndroid Build Coastguard Worker
2257*7c568831SAndroid Build Coastguard Worker absolute_value = fabs(number);
2258*7c568831SAndroid Build Coastguard Worker
2259*7c568831SAndroid Build Coastguard Worker /*
2260*7c568831SAndroid Build Coastguard Worker * First choose format - scientific or regular floating point.
2261*7c568831SAndroid Build Coastguard Worker * In either case, result is in work, and after_fraction points
2262*7c568831SAndroid Build Coastguard Worker * just past the fractional part.
2263*7c568831SAndroid Build Coastguard Worker */
2264*7c568831SAndroid Build Coastguard Worker if ( ((absolute_value > UPPER_DOUBLE) ||
2265*7c568831SAndroid Build Coastguard Worker (absolute_value < LOWER_DOUBLE)) &&
2266*7c568831SAndroid Build Coastguard Worker (absolute_value != 0.0) ) {
2267*7c568831SAndroid Build Coastguard Worker /* Use scientific notation */
2268*7c568831SAndroid Build Coastguard Worker integer_place = DBL_DIG + EXPONENT_DIGITS + 1;
2269*7c568831SAndroid Build Coastguard Worker fraction_place = DBL_DIG - 1;
2270*7c568831SAndroid Build Coastguard Worker size = snprintf(work, sizeof(work),"%*.*e",
2271*7c568831SAndroid Build Coastguard Worker integer_place, fraction_place, number);
2272*7c568831SAndroid Build Coastguard Worker while ((size > 0) && (work[size] != 'e')) size--;
2273*7c568831SAndroid Build Coastguard Worker
2274*7c568831SAndroid Build Coastguard Worker }
2275*7c568831SAndroid Build Coastguard Worker else {
2276*7c568831SAndroid Build Coastguard Worker /* Use regular notation */
2277*7c568831SAndroid Build Coastguard Worker if (absolute_value > 0.0) {
2278*7c568831SAndroid Build Coastguard Worker integer_place = (int)log10(absolute_value);
2279*7c568831SAndroid Build Coastguard Worker if (integer_place > 0)
2280*7c568831SAndroid Build Coastguard Worker fraction_place = DBL_DIG - integer_place - 1;
2281*7c568831SAndroid Build Coastguard Worker else
2282*7c568831SAndroid Build Coastguard Worker fraction_place = DBL_DIG - integer_place;
2283*7c568831SAndroid Build Coastguard Worker } else {
2284*7c568831SAndroid Build Coastguard Worker fraction_place = 1;
2285*7c568831SAndroid Build Coastguard Worker }
2286*7c568831SAndroid Build Coastguard Worker size = snprintf(work, sizeof(work), "%0.*f",
2287*7c568831SAndroid Build Coastguard Worker fraction_place, number);
2288*7c568831SAndroid Build Coastguard Worker }
2289*7c568831SAndroid Build Coastguard Worker
2290*7c568831SAndroid Build Coastguard Worker /* Remove leading spaces sometimes inserted by snprintf */
2291*7c568831SAndroid Build Coastguard Worker while (work[0] == ' ') {
2292*7c568831SAndroid Build Coastguard Worker for (ptr = &work[0];(ptr[0] = ptr[1]);ptr++);
2293*7c568831SAndroid Build Coastguard Worker size--;
2294*7c568831SAndroid Build Coastguard Worker }
2295*7c568831SAndroid Build Coastguard Worker
2296*7c568831SAndroid Build Coastguard Worker /* Remove fractional trailing zeroes */
2297*7c568831SAndroid Build Coastguard Worker after_fraction = work + size;
2298*7c568831SAndroid Build Coastguard Worker ptr = after_fraction;
2299*7c568831SAndroid Build Coastguard Worker while (*(--ptr) == '0')
2300*7c568831SAndroid Build Coastguard Worker ;
2301*7c568831SAndroid Build Coastguard Worker if (*ptr != '.')
2302*7c568831SAndroid Build Coastguard Worker ptr++;
2303*7c568831SAndroid Build Coastguard Worker while ((*ptr++ = *after_fraction++) != 0);
2304*7c568831SAndroid Build Coastguard Worker
2305*7c568831SAndroid Build Coastguard Worker /* Finally copy result back to caller */
2306*7c568831SAndroid Build Coastguard Worker size = strlen(work) + 1;
2307*7c568831SAndroid Build Coastguard Worker if (size > buffersize) {
2308*7c568831SAndroid Build Coastguard Worker work[buffersize - 1] = 0;
2309*7c568831SAndroid Build Coastguard Worker size = buffersize;
2310*7c568831SAndroid Build Coastguard Worker }
2311*7c568831SAndroid Build Coastguard Worker memmove(buffer, work, size);
2312*7c568831SAndroid Build Coastguard Worker }
2313*7c568831SAndroid Build Coastguard Worker break;
2314*7c568831SAndroid Build Coastguard Worker }
2315*7c568831SAndroid Build Coastguard Worker }
2316*7c568831SAndroid Build Coastguard Worker
2317*7c568831SAndroid Build Coastguard Worker
2318*7c568831SAndroid Build Coastguard Worker /************************************************************************
2319*7c568831SAndroid Build Coastguard Worker * *
2320*7c568831SAndroid Build Coastguard Worker * Routines to handle NodeSets *
2321*7c568831SAndroid Build Coastguard Worker * *
2322*7c568831SAndroid Build Coastguard Worker ************************************************************************/
2323*7c568831SAndroid Build Coastguard Worker
2324*7c568831SAndroid Build Coastguard Worker /**
2325*7c568831SAndroid Build Coastguard Worker * xmlXPathOrderDocElems:
2326*7c568831SAndroid Build Coastguard Worker * @doc: an input document
2327*7c568831SAndroid Build Coastguard Worker *
2328*7c568831SAndroid Build Coastguard Worker * Call this routine to speed up XPath computation on static documents.
2329*7c568831SAndroid Build Coastguard Worker * This stamps all the element nodes with the document order
2330*7c568831SAndroid Build Coastguard Worker * Like for line information, the order is kept in the element->content
2331*7c568831SAndroid Build Coastguard Worker * field, the value stored is actually - the node number (starting at -1)
2332*7c568831SAndroid Build Coastguard Worker * to be able to differentiate from line numbers.
2333*7c568831SAndroid Build Coastguard Worker *
2334*7c568831SAndroid Build Coastguard Worker * Returns the number of elements found in the document or -1 in case
2335*7c568831SAndroid Build Coastguard Worker * of error.
2336*7c568831SAndroid Build Coastguard Worker */
2337*7c568831SAndroid Build Coastguard Worker long
xmlXPathOrderDocElems(xmlDocPtr doc)2338*7c568831SAndroid Build Coastguard Worker xmlXPathOrderDocElems(xmlDocPtr doc) {
2339*7c568831SAndroid Build Coastguard Worker ptrdiff_t count = 0;
2340*7c568831SAndroid Build Coastguard Worker xmlNodePtr cur;
2341*7c568831SAndroid Build Coastguard Worker
2342*7c568831SAndroid Build Coastguard Worker if (doc == NULL)
2343*7c568831SAndroid Build Coastguard Worker return(-1);
2344*7c568831SAndroid Build Coastguard Worker cur = doc->children;
2345*7c568831SAndroid Build Coastguard Worker while (cur != NULL) {
2346*7c568831SAndroid Build Coastguard Worker if (cur->type == XML_ELEMENT_NODE) {
2347*7c568831SAndroid Build Coastguard Worker cur->content = (void *) (-(++count));
2348*7c568831SAndroid Build Coastguard Worker if (cur->children != NULL) {
2349*7c568831SAndroid Build Coastguard Worker cur = cur->children;
2350*7c568831SAndroid Build Coastguard Worker continue;
2351*7c568831SAndroid Build Coastguard Worker }
2352*7c568831SAndroid Build Coastguard Worker }
2353*7c568831SAndroid Build Coastguard Worker if (cur->next != NULL) {
2354*7c568831SAndroid Build Coastguard Worker cur = cur->next;
2355*7c568831SAndroid Build Coastguard Worker continue;
2356*7c568831SAndroid Build Coastguard Worker }
2357*7c568831SAndroid Build Coastguard Worker do {
2358*7c568831SAndroid Build Coastguard Worker cur = cur->parent;
2359*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
2360*7c568831SAndroid Build Coastguard Worker break;
2361*7c568831SAndroid Build Coastguard Worker if (cur == (xmlNodePtr) doc) {
2362*7c568831SAndroid Build Coastguard Worker cur = NULL;
2363*7c568831SAndroid Build Coastguard Worker break;
2364*7c568831SAndroid Build Coastguard Worker }
2365*7c568831SAndroid Build Coastguard Worker if (cur->next != NULL) {
2366*7c568831SAndroid Build Coastguard Worker cur = cur->next;
2367*7c568831SAndroid Build Coastguard Worker break;
2368*7c568831SAndroid Build Coastguard Worker }
2369*7c568831SAndroid Build Coastguard Worker } while (cur != NULL);
2370*7c568831SAndroid Build Coastguard Worker }
2371*7c568831SAndroid Build Coastguard Worker return(count);
2372*7c568831SAndroid Build Coastguard Worker }
2373*7c568831SAndroid Build Coastguard Worker
2374*7c568831SAndroid Build Coastguard Worker /**
2375*7c568831SAndroid Build Coastguard Worker * xmlXPathCmpNodes:
2376*7c568831SAndroid Build Coastguard Worker * @node1: the first node
2377*7c568831SAndroid Build Coastguard Worker * @node2: the second node
2378*7c568831SAndroid Build Coastguard Worker *
2379*7c568831SAndroid Build Coastguard Worker * Compare two nodes w.r.t document order
2380*7c568831SAndroid Build Coastguard Worker *
2381*7c568831SAndroid Build Coastguard Worker * Returns -2 in case of error 1 if first point < second point, 0 if
2382*7c568831SAndroid Build Coastguard Worker * it's the same node, -1 otherwise
2383*7c568831SAndroid Build Coastguard Worker */
2384*7c568831SAndroid Build Coastguard Worker int
xmlXPathCmpNodes(xmlNodePtr node1,xmlNodePtr node2)2385*7c568831SAndroid Build Coastguard Worker xmlXPathCmpNodes(xmlNodePtr node1, xmlNodePtr node2) {
2386*7c568831SAndroid Build Coastguard Worker int depth1, depth2;
2387*7c568831SAndroid Build Coastguard Worker int attr1 = 0, attr2 = 0;
2388*7c568831SAndroid Build Coastguard Worker xmlNodePtr attrNode1 = NULL, attrNode2 = NULL;
2389*7c568831SAndroid Build Coastguard Worker xmlNodePtr cur, root;
2390*7c568831SAndroid Build Coastguard Worker
2391*7c568831SAndroid Build Coastguard Worker if ((node1 == NULL) || (node2 == NULL))
2392*7c568831SAndroid Build Coastguard Worker return(-2);
2393*7c568831SAndroid Build Coastguard Worker /*
2394*7c568831SAndroid Build Coastguard Worker * a couple of optimizations which will avoid computations in most cases
2395*7c568831SAndroid Build Coastguard Worker */
2396*7c568831SAndroid Build Coastguard Worker if (node1 == node2) /* trivial case */
2397*7c568831SAndroid Build Coastguard Worker return(0);
2398*7c568831SAndroid Build Coastguard Worker if (node1->type == XML_ATTRIBUTE_NODE) {
2399*7c568831SAndroid Build Coastguard Worker attr1 = 1;
2400*7c568831SAndroid Build Coastguard Worker attrNode1 = node1;
2401*7c568831SAndroid Build Coastguard Worker node1 = node1->parent;
2402*7c568831SAndroid Build Coastguard Worker }
2403*7c568831SAndroid Build Coastguard Worker if (node2->type == XML_ATTRIBUTE_NODE) {
2404*7c568831SAndroid Build Coastguard Worker attr2 = 1;
2405*7c568831SAndroid Build Coastguard Worker attrNode2 = node2;
2406*7c568831SAndroid Build Coastguard Worker node2 = node2->parent;
2407*7c568831SAndroid Build Coastguard Worker }
2408*7c568831SAndroid Build Coastguard Worker if (node1 == node2) {
2409*7c568831SAndroid Build Coastguard Worker if (attr1 == attr2) {
2410*7c568831SAndroid Build Coastguard Worker /* not required, but we keep attributes in order */
2411*7c568831SAndroid Build Coastguard Worker if (attr1 != 0) {
2412*7c568831SAndroid Build Coastguard Worker cur = attrNode2->prev;
2413*7c568831SAndroid Build Coastguard Worker while (cur != NULL) {
2414*7c568831SAndroid Build Coastguard Worker if (cur == attrNode1)
2415*7c568831SAndroid Build Coastguard Worker return (1);
2416*7c568831SAndroid Build Coastguard Worker cur = cur->prev;
2417*7c568831SAndroid Build Coastguard Worker }
2418*7c568831SAndroid Build Coastguard Worker return (-1);
2419*7c568831SAndroid Build Coastguard Worker }
2420*7c568831SAndroid Build Coastguard Worker return(0);
2421*7c568831SAndroid Build Coastguard Worker }
2422*7c568831SAndroid Build Coastguard Worker if (attr2 == 1)
2423*7c568831SAndroid Build Coastguard Worker return(1);
2424*7c568831SAndroid Build Coastguard Worker return(-1);
2425*7c568831SAndroid Build Coastguard Worker }
2426*7c568831SAndroid Build Coastguard Worker if ((node1->type == XML_NAMESPACE_DECL) ||
2427*7c568831SAndroid Build Coastguard Worker (node2->type == XML_NAMESPACE_DECL))
2428*7c568831SAndroid Build Coastguard Worker return(1);
2429*7c568831SAndroid Build Coastguard Worker if (node1 == node2->prev)
2430*7c568831SAndroid Build Coastguard Worker return(1);
2431*7c568831SAndroid Build Coastguard Worker if (node1 == node2->next)
2432*7c568831SAndroid Build Coastguard Worker return(-1);
2433*7c568831SAndroid Build Coastguard Worker
2434*7c568831SAndroid Build Coastguard Worker /*
2435*7c568831SAndroid Build Coastguard Worker * Speedup using document order if available.
2436*7c568831SAndroid Build Coastguard Worker */
2437*7c568831SAndroid Build Coastguard Worker if ((node1->type == XML_ELEMENT_NODE) &&
2438*7c568831SAndroid Build Coastguard Worker (node2->type == XML_ELEMENT_NODE) &&
2439*7c568831SAndroid Build Coastguard Worker (0 > (ptrdiff_t) node1->content) &&
2440*7c568831SAndroid Build Coastguard Worker (0 > (ptrdiff_t) node2->content) &&
2441*7c568831SAndroid Build Coastguard Worker (node1->doc == node2->doc)) {
2442*7c568831SAndroid Build Coastguard Worker ptrdiff_t l1, l2;
2443*7c568831SAndroid Build Coastguard Worker
2444*7c568831SAndroid Build Coastguard Worker l1 = -((ptrdiff_t) node1->content);
2445*7c568831SAndroid Build Coastguard Worker l2 = -((ptrdiff_t) node2->content);
2446*7c568831SAndroid Build Coastguard Worker if (l1 < l2)
2447*7c568831SAndroid Build Coastguard Worker return(1);
2448*7c568831SAndroid Build Coastguard Worker if (l1 > l2)
2449*7c568831SAndroid Build Coastguard Worker return(-1);
2450*7c568831SAndroid Build Coastguard Worker }
2451*7c568831SAndroid Build Coastguard Worker
2452*7c568831SAndroid Build Coastguard Worker /*
2453*7c568831SAndroid Build Coastguard Worker * compute depth to root
2454*7c568831SAndroid Build Coastguard Worker */
2455*7c568831SAndroid Build Coastguard Worker for (depth2 = 0, cur = node2;cur->parent != NULL;cur = cur->parent) {
2456*7c568831SAndroid Build Coastguard Worker if (cur->parent == node1)
2457*7c568831SAndroid Build Coastguard Worker return(1);
2458*7c568831SAndroid Build Coastguard Worker depth2++;
2459*7c568831SAndroid Build Coastguard Worker }
2460*7c568831SAndroid Build Coastguard Worker root = cur;
2461*7c568831SAndroid Build Coastguard Worker for (depth1 = 0, cur = node1;cur->parent != NULL;cur = cur->parent) {
2462*7c568831SAndroid Build Coastguard Worker if (cur->parent == node2)
2463*7c568831SAndroid Build Coastguard Worker return(-1);
2464*7c568831SAndroid Build Coastguard Worker depth1++;
2465*7c568831SAndroid Build Coastguard Worker }
2466*7c568831SAndroid Build Coastguard Worker /*
2467*7c568831SAndroid Build Coastguard Worker * Distinct document (or distinct entities :-( ) case.
2468*7c568831SAndroid Build Coastguard Worker */
2469*7c568831SAndroid Build Coastguard Worker if (root != cur) {
2470*7c568831SAndroid Build Coastguard Worker return(-2);
2471*7c568831SAndroid Build Coastguard Worker }
2472*7c568831SAndroid Build Coastguard Worker /*
2473*7c568831SAndroid Build Coastguard Worker * get the nearest common ancestor.
2474*7c568831SAndroid Build Coastguard Worker */
2475*7c568831SAndroid Build Coastguard Worker while (depth1 > depth2) {
2476*7c568831SAndroid Build Coastguard Worker depth1--;
2477*7c568831SAndroid Build Coastguard Worker node1 = node1->parent;
2478*7c568831SAndroid Build Coastguard Worker }
2479*7c568831SAndroid Build Coastguard Worker while (depth2 > depth1) {
2480*7c568831SAndroid Build Coastguard Worker depth2--;
2481*7c568831SAndroid Build Coastguard Worker node2 = node2->parent;
2482*7c568831SAndroid Build Coastguard Worker }
2483*7c568831SAndroid Build Coastguard Worker while (node1->parent != node2->parent) {
2484*7c568831SAndroid Build Coastguard Worker node1 = node1->parent;
2485*7c568831SAndroid Build Coastguard Worker node2 = node2->parent;
2486*7c568831SAndroid Build Coastguard Worker /* should not happen but just in case ... */
2487*7c568831SAndroid Build Coastguard Worker if ((node1 == NULL) || (node2 == NULL))
2488*7c568831SAndroid Build Coastguard Worker return(-2);
2489*7c568831SAndroid Build Coastguard Worker }
2490*7c568831SAndroid Build Coastguard Worker /*
2491*7c568831SAndroid Build Coastguard Worker * Find who's first.
2492*7c568831SAndroid Build Coastguard Worker */
2493*7c568831SAndroid Build Coastguard Worker if (node1 == node2->prev)
2494*7c568831SAndroid Build Coastguard Worker return(1);
2495*7c568831SAndroid Build Coastguard Worker if (node1 == node2->next)
2496*7c568831SAndroid Build Coastguard Worker return(-1);
2497*7c568831SAndroid Build Coastguard Worker /*
2498*7c568831SAndroid Build Coastguard Worker * Speedup using document order if available.
2499*7c568831SAndroid Build Coastguard Worker */
2500*7c568831SAndroid Build Coastguard Worker if ((node1->type == XML_ELEMENT_NODE) &&
2501*7c568831SAndroid Build Coastguard Worker (node2->type == XML_ELEMENT_NODE) &&
2502*7c568831SAndroid Build Coastguard Worker (0 > (ptrdiff_t) node1->content) &&
2503*7c568831SAndroid Build Coastguard Worker (0 > (ptrdiff_t) node2->content) &&
2504*7c568831SAndroid Build Coastguard Worker (node1->doc == node2->doc)) {
2505*7c568831SAndroid Build Coastguard Worker ptrdiff_t l1, l2;
2506*7c568831SAndroid Build Coastguard Worker
2507*7c568831SAndroid Build Coastguard Worker l1 = -((ptrdiff_t) node1->content);
2508*7c568831SAndroid Build Coastguard Worker l2 = -((ptrdiff_t) node2->content);
2509*7c568831SAndroid Build Coastguard Worker if (l1 < l2)
2510*7c568831SAndroid Build Coastguard Worker return(1);
2511*7c568831SAndroid Build Coastguard Worker if (l1 > l2)
2512*7c568831SAndroid Build Coastguard Worker return(-1);
2513*7c568831SAndroid Build Coastguard Worker }
2514*7c568831SAndroid Build Coastguard Worker
2515*7c568831SAndroid Build Coastguard Worker for (cur = node1->next;cur != NULL;cur = cur->next)
2516*7c568831SAndroid Build Coastguard Worker if (cur == node2)
2517*7c568831SAndroid Build Coastguard Worker return(1);
2518*7c568831SAndroid Build Coastguard Worker return(-1); /* assume there is no sibling list corruption */
2519*7c568831SAndroid Build Coastguard Worker }
2520*7c568831SAndroid Build Coastguard Worker
2521*7c568831SAndroid Build Coastguard Worker /**
2522*7c568831SAndroid Build Coastguard Worker * xmlXPathNodeSetSort:
2523*7c568831SAndroid Build Coastguard Worker * @set: the node set
2524*7c568831SAndroid Build Coastguard Worker *
2525*7c568831SAndroid Build Coastguard Worker * Sort the node set in document order
2526*7c568831SAndroid Build Coastguard Worker */
2527*7c568831SAndroid Build Coastguard Worker void
xmlXPathNodeSetSort(xmlNodeSetPtr set)2528*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetSort(xmlNodeSetPtr set) {
2529*7c568831SAndroid Build Coastguard Worker #ifndef WITH_TIM_SORT
2530*7c568831SAndroid Build Coastguard Worker int i, j, incr, len;
2531*7c568831SAndroid Build Coastguard Worker xmlNodePtr tmp;
2532*7c568831SAndroid Build Coastguard Worker #endif
2533*7c568831SAndroid Build Coastguard Worker
2534*7c568831SAndroid Build Coastguard Worker if (set == NULL)
2535*7c568831SAndroid Build Coastguard Worker return;
2536*7c568831SAndroid Build Coastguard Worker
2537*7c568831SAndroid Build Coastguard Worker #ifndef WITH_TIM_SORT
2538*7c568831SAndroid Build Coastguard Worker /*
2539*7c568831SAndroid Build Coastguard Worker * Use the old Shell's sort implementation to sort the node-set
2540*7c568831SAndroid Build Coastguard Worker * Timsort ought to be quite faster
2541*7c568831SAndroid Build Coastguard Worker */
2542*7c568831SAndroid Build Coastguard Worker len = set->nodeNr;
2543*7c568831SAndroid Build Coastguard Worker for (incr = len / 2; incr > 0; incr /= 2) {
2544*7c568831SAndroid Build Coastguard Worker for (i = incr; i < len; i++) {
2545*7c568831SAndroid Build Coastguard Worker j = i - incr;
2546*7c568831SAndroid Build Coastguard Worker while (j >= 0) {
2547*7c568831SAndroid Build Coastguard Worker #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
2548*7c568831SAndroid Build Coastguard Worker if (xmlXPathCmpNodesExt(set->nodeTab[j],
2549*7c568831SAndroid Build Coastguard Worker set->nodeTab[j + incr]) == -1)
2550*7c568831SAndroid Build Coastguard Worker #else
2551*7c568831SAndroid Build Coastguard Worker if (xmlXPathCmpNodes(set->nodeTab[j],
2552*7c568831SAndroid Build Coastguard Worker set->nodeTab[j + incr]) == -1)
2553*7c568831SAndroid Build Coastguard Worker #endif
2554*7c568831SAndroid Build Coastguard Worker {
2555*7c568831SAndroid Build Coastguard Worker tmp = set->nodeTab[j];
2556*7c568831SAndroid Build Coastguard Worker set->nodeTab[j] = set->nodeTab[j + incr];
2557*7c568831SAndroid Build Coastguard Worker set->nodeTab[j + incr] = tmp;
2558*7c568831SAndroid Build Coastguard Worker j -= incr;
2559*7c568831SAndroid Build Coastguard Worker } else
2560*7c568831SAndroid Build Coastguard Worker break;
2561*7c568831SAndroid Build Coastguard Worker }
2562*7c568831SAndroid Build Coastguard Worker }
2563*7c568831SAndroid Build Coastguard Worker }
2564*7c568831SAndroid Build Coastguard Worker #else /* WITH_TIM_SORT */
2565*7c568831SAndroid Build Coastguard Worker libxml_domnode_tim_sort(set->nodeTab, set->nodeNr);
2566*7c568831SAndroid Build Coastguard Worker #endif /* WITH_TIM_SORT */
2567*7c568831SAndroid Build Coastguard Worker }
2568*7c568831SAndroid Build Coastguard Worker
2569*7c568831SAndroid Build Coastguard Worker #define XML_NODESET_DEFAULT 10
2570*7c568831SAndroid Build Coastguard Worker /**
2571*7c568831SAndroid Build Coastguard Worker * xmlXPathNodeSetDupNs:
2572*7c568831SAndroid Build Coastguard Worker * @node: the parent node of the namespace XPath node
2573*7c568831SAndroid Build Coastguard Worker * @ns: the libxml namespace declaration node.
2574*7c568831SAndroid Build Coastguard Worker *
2575*7c568831SAndroid Build Coastguard Worker * Namespace node in libxml don't match the XPath semantic. In a node set
2576*7c568831SAndroid Build Coastguard Worker * the namespace nodes are duplicated and the next pointer is set to the
2577*7c568831SAndroid Build Coastguard Worker * parent node in the XPath semantic.
2578*7c568831SAndroid Build Coastguard Worker *
2579*7c568831SAndroid Build Coastguard Worker * Returns the newly created object.
2580*7c568831SAndroid Build Coastguard Worker */
2581*7c568831SAndroid Build Coastguard Worker static xmlNodePtr
xmlXPathNodeSetDupNs(xmlNodePtr node,xmlNsPtr ns)2582*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetDupNs(xmlNodePtr node, xmlNsPtr ns) {
2583*7c568831SAndroid Build Coastguard Worker xmlNsPtr cur;
2584*7c568831SAndroid Build Coastguard Worker
2585*7c568831SAndroid Build Coastguard Worker if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL))
2586*7c568831SAndroid Build Coastguard Worker return(NULL);
2587*7c568831SAndroid Build Coastguard Worker if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
2588*7c568831SAndroid Build Coastguard Worker return((xmlNodePtr) ns);
2589*7c568831SAndroid Build Coastguard Worker
2590*7c568831SAndroid Build Coastguard Worker /*
2591*7c568831SAndroid Build Coastguard Worker * Allocate a new Namespace and fill the fields.
2592*7c568831SAndroid Build Coastguard Worker */
2593*7c568831SAndroid Build Coastguard Worker cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
2594*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
2595*7c568831SAndroid Build Coastguard Worker return(NULL);
2596*7c568831SAndroid Build Coastguard Worker memset(cur, 0, sizeof(xmlNs));
2597*7c568831SAndroid Build Coastguard Worker cur->type = XML_NAMESPACE_DECL;
2598*7c568831SAndroid Build Coastguard Worker if (ns->href != NULL) {
2599*7c568831SAndroid Build Coastguard Worker cur->href = xmlStrdup(ns->href);
2600*7c568831SAndroid Build Coastguard Worker if (cur->href == NULL) {
2601*7c568831SAndroid Build Coastguard Worker xmlFree(cur);
2602*7c568831SAndroid Build Coastguard Worker return(NULL);
2603*7c568831SAndroid Build Coastguard Worker }
2604*7c568831SAndroid Build Coastguard Worker }
2605*7c568831SAndroid Build Coastguard Worker if (ns->prefix != NULL) {
2606*7c568831SAndroid Build Coastguard Worker cur->prefix = xmlStrdup(ns->prefix);
2607*7c568831SAndroid Build Coastguard Worker if (cur->prefix == NULL) {
2608*7c568831SAndroid Build Coastguard Worker xmlFree((xmlChar *) cur->href);
2609*7c568831SAndroid Build Coastguard Worker xmlFree(cur);
2610*7c568831SAndroid Build Coastguard Worker return(NULL);
2611*7c568831SAndroid Build Coastguard Worker }
2612*7c568831SAndroid Build Coastguard Worker }
2613*7c568831SAndroid Build Coastguard Worker cur->next = (xmlNsPtr) node;
2614*7c568831SAndroid Build Coastguard Worker return((xmlNodePtr) cur);
2615*7c568831SAndroid Build Coastguard Worker }
2616*7c568831SAndroid Build Coastguard Worker
2617*7c568831SAndroid Build Coastguard Worker /**
2618*7c568831SAndroid Build Coastguard Worker * xmlXPathNodeSetFreeNs:
2619*7c568831SAndroid Build Coastguard Worker * @ns: the XPath namespace node found in a nodeset.
2620*7c568831SAndroid Build Coastguard Worker *
2621*7c568831SAndroid Build Coastguard Worker * Namespace nodes in libxml don't match the XPath semantic. In a node set
2622*7c568831SAndroid Build Coastguard Worker * the namespace nodes are duplicated and the next pointer is set to the
2623*7c568831SAndroid Build Coastguard Worker * parent node in the XPath semantic. Check if such a node needs to be freed
2624*7c568831SAndroid Build Coastguard Worker */
2625*7c568831SAndroid Build Coastguard Worker void
xmlXPathNodeSetFreeNs(xmlNsPtr ns)2626*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetFreeNs(xmlNsPtr ns) {
2627*7c568831SAndroid Build Coastguard Worker if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL))
2628*7c568831SAndroid Build Coastguard Worker return;
2629*7c568831SAndroid Build Coastguard Worker
2630*7c568831SAndroid Build Coastguard Worker if ((ns->next != NULL) && (ns->next->type != XML_NAMESPACE_DECL)) {
2631*7c568831SAndroid Build Coastguard Worker if (ns->href != NULL)
2632*7c568831SAndroid Build Coastguard Worker xmlFree((xmlChar *)ns->href);
2633*7c568831SAndroid Build Coastguard Worker if (ns->prefix != NULL)
2634*7c568831SAndroid Build Coastguard Worker xmlFree((xmlChar *)ns->prefix);
2635*7c568831SAndroid Build Coastguard Worker xmlFree(ns);
2636*7c568831SAndroid Build Coastguard Worker }
2637*7c568831SAndroid Build Coastguard Worker }
2638*7c568831SAndroid Build Coastguard Worker
2639*7c568831SAndroid Build Coastguard Worker /**
2640*7c568831SAndroid Build Coastguard Worker * xmlXPathNodeSetCreate:
2641*7c568831SAndroid Build Coastguard Worker * @val: an initial xmlNodePtr, or NULL
2642*7c568831SAndroid Build Coastguard Worker *
2643*7c568831SAndroid Build Coastguard Worker * Create a new xmlNodeSetPtr of type double and of value @val
2644*7c568831SAndroid Build Coastguard Worker *
2645*7c568831SAndroid Build Coastguard Worker * Returns the newly created object.
2646*7c568831SAndroid Build Coastguard Worker */
2647*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathNodeSetCreate(xmlNodePtr val)2648*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetCreate(xmlNodePtr val) {
2649*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr ret;
2650*7c568831SAndroid Build Coastguard Worker
2651*7c568831SAndroid Build Coastguard Worker ret = (xmlNodeSetPtr) xmlMalloc(sizeof(xmlNodeSet));
2652*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
2653*7c568831SAndroid Build Coastguard Worker return(NULL);
2654*7c568831SAndroid Build Coastguard Worker memset(ret, 0 , sizeof(xmlNodeSet));
2655*7c568831SAndroid Build Coastguard Worker if (val != NULL) {
2656*7c568831SAndroid Build Coastguard Worker ret->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
2657*7c568831SAndroid Build Coastguard Worker sizeof(xmlNodePtr));
2658*7c568831SAndroid Build Coastguard Worker if (ret->nodeTab == NULL) {
2659*7c568831SAndroid Build Coastguard Worker xmlFree(ret);
2660*7c568831SAndroid Build Coastguard Worker return(NULL);
2661*7c568831SAndroid Build Coastguard Worker }
2662*7c568831SAndroid Build Coastguard Worker memset(ret->nodeTab, 0 ,
2663*7c568831SAndroid Build Coastguard Worker XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
2664*7c568831SAndroid Build Coastguard Worker ret->nodeMax = XML_NODESET_DEFAULT;
2665*7c568831SAndroid Build Coastguard Worker if (val->type == XML_NAMESPACE_DECL) {
2666*7c568831SAndroid Build Coastguard Worker xmlNsPtr ns = (xmlNsPtr) val;
2667*7c568831SAndroid Build Coastguard Worker xmlNodePtr nsNode = xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
2668*7c568831SAndroid Build Coastguard Worker
2669*7c568831SAndroid Build Coastguard Worker if (nsNode == NULL) {
2670*7c568831SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(ret);
2671*7c568831SAndroid Build Coastguard Worker return(NULL);
2672*7c568831SAndroid Build Coastguard Worker }
2673*7c568831SAndroid Build Coastguard Worker ret->nodeTab[ret->nodeNr++] = nsNode;
2674*7c568831SAndroid Build Coastguard Worker } else
2675*7c568831SAndroid Build Coastguard Worker ret->nodeTab[ret->nodeNr++] = val;
2676*7c568831SAndroid Build Coastguard Worker }
2677*7c568831SAndroid Build Coastguard Worker return(ret);
2678*7c568831SAndroid Build Coastguard Worker }
2679*7c568831SAndroid Build Coastguard Worker
2680*7c568831SAndroid Build Coastguard Worker /**
2681*7c568831SAndroid Build Coastguard Worker * xmlXPathNodeSetContains:
2682*7c568831SAndroid Build Coastguard Worker * @cur: the node-set
2683*7c568831SAndroid Build Coastguard Worker * @val: the node
2684*7c568831SAndroid Build Coastguard Worker *
2685*7c568831SAndroid Build Coastguard Worker * checks whether @cur contains @val
2686*7c568831SAndroid Build Coastguard Worker *
2687*7c568831SAndroid Build Coastguard Worker * Returns true (1) if @cur contains @val, false (0) otherwise
2688*7c568831SAndroid Build Coastguard Worker */
2689*7c568831SAndroid Build Coastguard Worker int
xmlXPathNodeSetContains(xmlNodeSetPtr cur,xmlNodePtr val)2690*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetContains (xmlNodeSetPtr cur, xmlNodePtr val) {
2691*7c568831SAndroid Build Coastguard Worker int i;
2692*7c568831SAndroid Build Coastguard Worker
2693*7c568831SAndroid Build Coastguard Worker if ((cur == NULL) || (val == NULL)) return(0);
2694*7c568831SAndroid Build Coastguard Worker if (val->type == XML_NAMESPACE_DECL) {
2695*7c568831SAndroid Build Coastguard Worker for (i = 0; i < cur->nodeNr; i++) {
2696*7c568831SAndroid Build Coastguard Worker if (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) {
2697*7c568831SAndroid Build Coastguard Worker xmlNsPtr ns1, ns2;
2698*7c568831SAndroid Build Coastguard Worker
2699*7c568831SAndroid Build Coastguard Worker ns1 = (xmlNsPtr) val;
2700*7c568831SAndroid Build Coastguard Worker ns2 = (xmlNsPtr) cur->nodeTab[i];
2701*7c568831SAndroid Build Coastguard Worker if (ns1 == ns2)
2702*7c568831SAndroid Build Coastguard Worker return(1);
2703*7c568831SAndroid Build Coastguard Worker if ((ns1->next != NULL) && (ns2->next == ns1->next) &&
2704*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(ns1->prefix, ns2->prefix)))
2705*7c568831SAndroid Build Coastguard Worker return(1);
2706*7c568831SAndroid Build Coastguard Worker }
2707*7c568831SAndroid Build Coastguard Worker }
2708*7c568831SAndroid Build Coastguard Worker } else {
2709*7c568831SAndroid Build Coastguard Worker for (i = 0; i < cur->nodeNr; i++) {
2710*7c568831SAndroid Build Coastguard Worker if (cur->nodeTab[i] == val)
2711*7c568831SAndroid Build Coastguard Worker return(1);
2712*7c568831SAndroid Build Coastguard Worker }
2713*7c568831SAndroid Build Coastguard Worker }
2714*7c568831SAndroid Build Coastguard Worker return(0);
2715*7c568831SAndroid Build Coastguard Worker }
2716*7c568831SAndroid Build Coastguard Worker
2717*7c568831SAndroid Build Coastguard Worker /**
2718*7c568831SAndroid Build Coastguard Worker * xmlXPathNodeSetAddNs:
2719*7c568831SAndroid Build Coastguard Worker * @cur: the initial node set
2720*7c568831SAndroid Build Coastguard Worker * @node: the hosting node
2721*7c568831SAndroid Build Coastguard Worker * @ns: a the namespace node
2722*7c568831SAndroid Build Coastguard Worker *
2723*7c568831SAndroid Build Coastguard Worker * add a new namespace node to an existing NodeSet
2724*7c568831SAndroid Build Coastguard Worker *
2725*7c568831SAndroid Build Coastguard Worker * Returns 0 in case of success and -1 in case of error
2726*7c568831SAndroid Build Coastguard Worker */
2727*7c568831SAndroid Build Coastguard Worker int
xmlXPathNodeSetAddNs(xmlNodeSetPtr cur,xmlNodePtr node,xmlNsPtr ns)2728*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
2729*7c568831SAndroid Build Coastguard Worker int i;
2730*7c568831SAndroid Build Coastguard Worker xmlNodePtr nsNode;
2731*7c568831SAndroid Build Coastguard Worker
2732*7c568831SAndroid Build Coastguard Worker if ((cur == NULL) || (ns == NULL) || (node == NULL) ||
2733*7c568831SAndroid Build Coastguard Worker (ns->type != XML_NAMESPACE_DECL) ||
2734*7c568831SAndroid Build Coastguard Worker (node->type != XML_ELEMENT_NODE))
2735*7c568831SAndroid Build Coastguard Worker return(-1);
2736*7c568831SAndroid Build Coastguard Worker
2737*7c568831SAndroid Build Coastguard Worker /* @@ with_ns to check whether namespace nodes should be looked at @@ */
2738*7c568831SAndroid Build Coastguard Worker /*
2739*7c568831SAndroid Build Coastguard Worker * prevent duplicates
2740*7c568831SAndroid Build Coastguard Worker */
2741*7c568831SAndroid Build Coastguard Worker for (i = 0;i < cur->nodeNr;i++) {
2742*7c568831SAndroid Build Coastguard Worker if ((cur->nodeTab[i] != NULL) &&
2743*7c568831SAndroid Build Coastguard Worker (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) &&
2744*7c568831SAndroid Build Coastguard Worker (((xmlNsPtr)cur->nodeTab[i])->next == (xmlNsPtr) node) &&
2745*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(ns->prefix, ((xmlNsPtr)cur->nodeTab[i])->prefix)))
2746*7c568831SAndroid Build Coastguard Worker return(0);
2747*7c568831SAndroid Build Coastguard Worker }
2748*7c568831SAndroid Build Coastguard Worker
2749*7c568831SAndroid Build Coastguard Worker /*
2750*7c568831SAndroid Build Coastguard Worker * grow the nodeTab if needed
2751*7c568831SAndroid Build Coastguard Worker */
2752*7c568831SAndroid Build Coastguard Worker if (cur->nodeMax == 0) {
2753*7c568831SAndroid Build Coastguard Worker cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
2754*7c568831SAndroid Build Coastguard Worker sizeof(xmlNodePtr));
2755*7c568831SAndroid Build Coastguard Worker if (cur->nodeTab == NULL)
2756*7c568831SAndroid Build Coastguard Worker return(-1);
2757*7c568831SAndroid Build Coastguard Worker memset(cur->nodeTab, 0 ,
2758*7c568831SAndroid Build Coastguard Worker XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
2759*7c568831SAndroid Build Coastguard Worker cur->nodeMax = XML_NODESET_DEFAULT;
2760*7c568831SAndroid Build Coastguard Worker } else if (cur->nodeNr == cur->nodeMax) {
2761*7c568831SAndroid Build Coastguard Worker xmlNodePtr *temp;
2762*7c568831SAndroid Build Coastguard Worker
2763*7c568831SAndroid Build Coastguard Worker if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH)
2764*7c568831SAndroid Build Coastguard Worker return(-1);
2765*7c568831SAndroid Build Coastguard Worker temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
2766*7c568831SAndroid Build Coastguard Worker sizeof(xmlNodePtr));
2767*7c568831SAndroid Build Coastguard Worker if (temp == NULL)
2768*7c568831SAndroid Build Coastguard Worker return(-1);
2769*7c568831SAndroid Build Coastguard Worker cur->nodeMax *= 2;
2770*7c568831SAndroid Build Coastguard Worker cur->nodeTab = temp;
2771*7c568831SAndroid Build Coastguard Worker }
2772*7c568831SAndroid Build Coastguard Worker nsNode = xmlXPathNodeSetDupNs(node, ns);
2773*7c568831SAndroid Build Coastguard Worker if(nsNode == NULL)
2774*7c568831SAndroid Build Coastguard Worker return(-1);
2775*7c568831SAndroid Build Coastguard Worker cur->nodeTab[cur->nodeNr++] = nsNode;
2776*7c568831SAndroid Build Coastguard Worker return(0);
2777*7c568831SAndroid Build Coastguard Worker }
2778*7c568831SAndroid Build Coastguard Worker
2779*7c568831SAndroid Build Coastguard Worker /**
2780*7c568831SAndroid Build Coastguard Worker * xmlXPathNodeSetAdd:
2781*7c568831SAndroid Build Coastguard Worker * @cur: the initial node set
2782*7c568831SAndroid Build Coastguard Worker * @val: a new xmlNodePtr
2783*7c568831SAndroid Build Coastguard Worker *
2784*7c568831SAndroid Build Coastguard Worker * add a new xmlNodePtr to an existing NodeSet
2785*7c568831SAndroid Build Coastguard Worker *
2786*7c568831SAndroid Build Coastguard Worker * Returns 0 in case of success, and -1 in case of error
2787*7c568831SAndroid Build Coastguard Worker */
2788*7c568831SAndroid Build Coastguard Worker int
xmlXPathNodeSetAdd(xmlNodeSetPtr cur,xmlNodePtr val)2789*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
2790*7c568831SAndroid Build Coastguard Worker int i;
2791*7c568831SAndroid Build Coastguard Worker
2792*7c568831SAndroid Build Coastguard Worker if ((cur == NULL) || (val == NULL)) return(-1);
2793*7c568831SAndroid Build Coastguard Worker
2794*7c568831SAndroid Build Coastguard Worker /* @@ with_ns to check whether namespace nodes should be looked at @@ */
2795*7c568831SAndroid Build Coastguard Worker /*
2796*7c568831SAndroid Build Coastguard Worker * prevent duplicates
2797*7c568831SAndroid Build Coastguard Worker */
2798*7c568831SAndroid Build Coastguard Worker for (i = 0;i < cur->nodeNr;i++)
2799*7c568831SAndroid Build Coastguard Worker if (cur->nodeTab[i] == val) return(0);
2800*7c568831SAndroid Build Coastguard Worker
2801*7c568831SAndroid Build Coastguard Worker /*
2802*7c568831SAndroid Build Coastguard Worker * grow the nodeTab if needed
2803*7c568831SAndroid Build Coastguard Worker */
2804*7c568831SAndroid Build Coastguard Worker if (cur->nodeMax == 0) {
2805*7c568831SAndroid Build Coastguard Worker cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
2806*7c568831SAndroid Build Coastguard Worker sizeof(xmlNodePtr));
2807*7c568831SAndroid Build Coastguard Worker if (cur->nodeTab == NULL)
2808*7c568831SAndroid Build Coastguard Worker return(-1);
2809*7c568831SAndroid Build Coastguard Worker memset(cur->nodeTab, 0 ,
2810*7c568831SAndroid Build Coastguard Worker XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
2811*7c568831SAndroid Build Coastguard Worker cur->nodeMax = XML_NODESET_DEFAULT;
2812*7c568831SAndroid Build Coastguard Worker } else if (cur->nodeNr == cur->nodeMax) {
2813*7c568831SAndroid Build Coastguard Worker xmlNodePtr *temp;
2814*7c568831SAndroid Build Coastguard Worker
2815*7c568831SAndroid Build Coastguard Worker if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH)
2816*7c568831SAndroid Build Coastguard Worker return(-1);
2817*7c568831SAndroid Build Coastguard Worker temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
2818*7c568831SAndroid Build Coastguard Worker sizeof(xmlNodePtr));
2819*7c568831SAndroid Build Coastguard Worker if (temp == NULL)
2820*7c568831SAndroid Build Coastguard Worker return(-1);
2821*7c568831SAndroid Build Coastguard Worker cur->nodeMax *= 2;
2822*7c568831SAndroid Build Coastguard Worker cur->nodeTab = temp;
2823*7c568831SAndroid Build Coastguard Worker }
2824*7c568831SAndroid Build Coastguard Worker if (val->type == XML_NAMESPACE_DECL) {
2825*7c568831SAndroid Build Coastguard Worker xmlNsPtr ns = (xmlNsPtr) val;
2826*7c568831SAndroid Build Coastguard Worker xmlNodePtr nsNode = xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
2827*7c568831SAndroid Build Coastguard Worker
2828*7c568831SAndroid Build Coastguard Worker if (nsNode == NULL)
2829*7c568831SAndroid Build Coastguard Worker return(-1);
2830*7c568831SAndroid Build Coastguard Worker cur->nodeTab[cur->nodeNr++] = nsNode;
2831*7c568831SAndroid Build Coastguard Worker } else
2832*7c568831SAndroid Build Coastguard Worker cur->nodeTab[cur->nodeNr++] = val;
2833*7c568831SAndroid Build Coastguard Worker return(0);
2834*7c568831SAndroid Build Coastguard Worker }
2835*7c568831SAndroid Build Coastguard Worker
2836*7c568831SAndroid Build Coastguard Worker /**
2837*7c568831SAndroid Build Coastguard Worker * xmlXPathNodeSetAddUnique:
2838*7c568831SAndroid Build Coastguard Worker * @cur: the initial node set
2839*7c568831SAndroid Build Coastguard Worker * @val: a new xmlNodePtr
2840*7c568831SAndroid Build Coastguard Worker *
2841*7c568831SAndroid Build Coastguard Worker * add a new xmlNodePtr to an existing NodeSet, optimized version
2842*7c568831SAndroid Build Coastguard Worker * when we are sure the node is not already in the set.
2843*7c568831SAndroid Build Coastguard Worker *
2844*7c568831SAndroid Build Coastguard Worker * Returns 0 in case of success and -1 in case of failure
2845*7c568831SAndroid Build Coastguard Worker */
2846*7c568831SAndroid Build Coastguard Worker int
xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur,xmlNodePtr val)2847*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
2848*7c568831SAndroid Build Coastguard Worker if ((cur == NULL) || (val == NULL)) return(-1);
2849*7c568831SAndroid Build Coastguard Worker
2850*7c568831SAndroid Build Coastguard Worker /* @@ with_ns to check whether namespace nodes should be looked at @@ */
2851*7c568831SAndroid Build Coastguard Worker /*
2852*7c568831SAndroid Build Coastguard Worker * grow the nodeTab if needed
2853*7c568831SAndroid Build Coastguard Worker */
2854*7c568831SAndroid Build Coastguard Worker if (cur->nodeMax == 0) {
2855*7c568831SAndroid Build Coastguard Worker cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
2856*7c568831SAndroid Build Coastguard Worker sizeof(xmlNodePtr));
2857*7c568831SAndroid Build Coastguard Worker if (cur->nodeTab == NULL)
2858*7c568831SAndroid Build Coastguard Worker return(-1);
2859*7c568831SAndroid Build Coastguard Worker memset(cur->nodeTab, 0 ,
2860*7c568831SAndroid Build Coastguard Worker XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
2861*7c568831SAndroid Build Coastguard Worker cur->nodeMax = XML_NODESET_DEFAULT;
2862*7c568831SAndroid Build Coastguard Worker } else if (cur->nodeNr == cur->nodeMax) {
2863*7c568831SAndroid Build Coastguard Worker xmlNodePtr *temp;
2864*7c568831SAndroid Build Coastguard Worker
2865*7c568831SAndroid Build Coastguard Worker if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH)
2866*7c568831SAndroid Build Coastguard Worker return(-1);
2867*7c568831SAndroid Build Coastguard Worker temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
2868*7c568831SAndroid Build Coastguard Worker sizeof(xmlNodePtr));
2869*7c568831SAndroid Build Coastguard Worker if (temp == NULL)
2870*7c568831SAndroid Build Coastguard Worker return(-1);
2871*7c568831SAndroid Build Coastguard Worker cur->nodeTab = temp;
2872*7c568831SAndroid Build Coastguard Worker cur->nodeMax *= 2;
2873*7c568831SAndroid Build Coastguard Worker }
2874*7c568831SAndroid Build Coastguard Worker if (val->type == XML_NAMESPACE_DECL) {
2875*7c568831SAndroid Build Coastguard Worker xmlNsPtr ns = (xmlNsPtr) val;
2876*7c568831SAndroid Build Coastguard Worker xmlNodePtr nsNode = xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
2877*7c568831SAndroid Build Coastguard Worker
2878*7c568831SAndroid Build Coastguard Worker if (nsNode == NULL)
2879*7c568831SAndroid Build Coastguard Worker return(-1);
2880*7c568831SAndroid Build Coastguard Worker cur->nodeTab[cur->nodeNr++] = nsNode;
2881*7c568831SAndroid Build Coastguard Worker } else
2882*7c568831SAndroid Build Coastguard Worker cur->nodeTab[cur->nodeNr++] = val;
2883*7c568831SAndroid Build Coastguard Worker return(0);
2884*7c568831SAndroid Build Coastguard Worker }
2885*7c568831SAndroid Build Coastguard Worker
2886*7c568831SAndroid Build Coastguard Worker /**
2887*7c568831SAndroid Build Coastguard Worker * xmlXPathNodeSetMerge:
2888*7c568831SAndroid Build Coastguard Worker * @val1: the first NodeSet or NULL
2889*7c568831SAndroid Build Coastguard Worker * @val2: the second NodeSet
2890*7c568831SAndroid Build Coastguard Worker *
2891*7c568831SAndroid Build Coastguard Worker * Merges two nodesets, all nodes from @val2 are added to @val1
2892*7c568831SAndroid Build Coastguard Worker * if @val1 is NULL, a new set is created and copied from @val2
2893*7c568831SAndroid Build Coastguard Worker *
2894*7c568831SAndroid Build Coastguard Worker * Returns @val1 once extended or NULL in case of error.
2895*7c568831SAndroid Build Coastguard Worker *
2896*7c568831SAndroid Build Coastguard Worker * Frees @val1 in case of error.
2897*7c568831SAndroid Build Coastguard Worker */
2898*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathNodeSetMerge(xmlNodeSetPtr val1,xmlNodeSetPtr val2)2899*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
2900*7c568831SAndroid Build Coastguard Worker int i, j, initNr, skip;
2901*7c568831SAndroid Build Coastguard Worker xmlNodePtr n1, n2;
2902*7c568831SAndroid Build Coastguard Worker
2903*7c568831SAndroid Build Coastguard Worker if (val1 == NULL) {
2904*7c568831SAndroid Build Coastguard Worker val1 = xmlXPathNodeSetCreate(NULL);
2905*7c568831SAndroid Build Coastguard Worker if (val1 == NULL)
2906*7c568831SAndroid Build Coastguard Worker return (NULL);
2907*7c568831SAndroid Build Coastguard Worker }
2908*7c568831SAndroid Build Coastguard Worker if (val2 == NULL)
2909*7c568831SAndroid Build Coastguard Worker return(val1);
2910*7c568831SAndroid Build Coastguard Worker
2911*7c568831SAndroid Build Coastguard Worker /* @@ with_ns to check whether namespace nodes should be looked at @@ */
2912*7c568831SAndroid Build Coastguard Worker initNr = val1->nodeNr;
2913*7c568831SAndroid Build Coastguard Worker
2914*7c568831SAndroid Build Coastguard Worker for (i = 0;i < val2->nodeNr;i++) {
2915*7c568831SAndroid Build Coastguard Worker n2 = val2->nodeTab[i];
2916*7c568831SAndroid Build Coastguard Worker /*
2917*7c568831SAndroid Build Coastguard Worker * check against duplicates
2918*7c568831SAndroid Build Coastguard Worker */
2919*7c568831SAndroid Build Coastguard Worker skip = 0;
2920*7c568831SAndroid Build Coastguard Worker for (j = 0; j < initNr; j++) {
2921*7c568831SAndroid Build Coastguard Worker n1 = val1->nodeTab[j];
2922*7c568831SAndroid Build Coastguard Worker if (n1 == n2) {
2923*7c568831SAndroid Build Coastguard Worker skip = 1;
2924*7c568831SAndroid Build Coastguard Worker break;
2925*7c568831SAndroid Build Coastguard Worker } else if ((n1->type == XML_NAMESPACE_DECL) &&
2926*7c568831SAndroid Build Coastguard Worker (n2->type == XML_NAMESPACE_DECL)) {
2927*7c568831SAndroid Build Coastguard Worker if ((((xmlNsPtr) n1)->next == ((xmlNsPtr) n2)->next) &&
2928*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(((xmlNsPtr) n1)->prefix,
2929*7c568831SAndroid Build Coastguard Worker ((xmlNsPtr) n2)->prefix)))
2930*7c568831SAndroid Build Coastguard Worker {
2931*7c568831SAndroid Build Coastguard Worker skip = 1;
2932*7c568831SAndroid Build Coastguard Worker break;
2933*7c568831SAndroid Build Coastguard Worker }
2934*7c568831SAndroid Build Coastguard Worker }
2935*7c568831SAndroid Build Coastguard Worker }
2936*7c568831SAndroid Build Coastguard Worker if (skip)
2937*7c568831SAndroid Build Coastguard Worker continue;
2938*7c568831SAndroid Build Coastguard Worker
2939*7c568831SAndroid Build Coastguard Worker /*
2940*7c568831SAndroid Build Coastguard Worker * grow the nodeTab if needed
2941*7c568831SAndroid Build Coastguard Worker */
2942*7c568831SAndroid Build Coastguard Worker if (val1->nodeMax == 0) {
2943*7c568831SAndroid Build Coastguard Worker val1->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
2944*7c568831SAndroid Build Coastguard Worker sizeof(xmlNodePtr));
2945*7c568831SAndroid Build Coastguard Worker if (val1->nodeTab == NULL)
2946*7c568831SAndroid Build Coastguard Worker goto error;
2947*7c568831SAndroid Build Coastguard Worker memset(val1->nodeTab, 0 ,
2948*7c568831SAndroid Build Coastguard Worker XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
2949*7c568831SAndroid Build Coastguard Worker val1->nodeMax = XML_NODESET_DEFAULT;
2950*7c568831SAndroid Build Coastguard Worker } else if (val1->nodeNr == val1->nodeMax) {
2951*7c568831SAndroid Build Coastguard Worker xmlNodePtr *temp;
2952*7c568831SAndroid Build Coastguard Worker
2953*7c568831SAndroid Build Coastguard Worker if (val1->nodeMax >= XPATH_MAX_NODESET_LENGTH)
2954*7c568831SAndroid Build Coastguard Worker goto error;
2955*7c568831SAndroid Build Coastguard Worker temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax * 2 *
2956*7c568831SAndroid Build Coastguard Worker sizeof(xmlNodePtr));
2957*7c568831SAndroid Build Coastguard Worker if (temp == NULL)
2958*7c568831SAndroid Build Coastguard Worker goto error;
2959*7c568831SAndroid Build Coastguard Worker val1->nodeTab = temp;
2960*7c568831SAndroid Build Coastguard Worker val1->nodeMax *= 2;
2961*7c568831SAndroid Build Coastguard Worker }
2962*7c568831SAndroid Build Coastguard Worker if (n2->type == XML_NAMESPACE_DECL) {
2963*7c568831SAndroid Build Coastguard Worker xmlNsPtr ns = (xmlNsPtr) n2;
2964*7c568831SAndroid Build Coastguard Worker xmlNodePtr nsNode = xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
2965*7c568831SAndroid Build Coastguard Worker
2966*7c568831SAndroid Build Coastguard Worker if (nsNode == NULL)
2967*7c568831SAndroid Build Coastguard Worker goto error;
2968*7c568831SAndroid Build Coastguard Worker val1->nodeTab[val1->nodeNr++] = nsNode;
2969*7c568831SAndroid Build Coastguard Worker } else
2970*7c568831SAndroid Build Coastguard Worker val1->nodeTab[val1->nodeNr++] = n2;
2971*7c568831SAndroid Build Coastguard Worker }
2972*7c568831SAndroid Build Coastguard Worker
2973*7c568831SAndroid Build Coastguard Worker return(val1);
2974*7c568831SAndroid Build Coastguard Worker
2975*7c568831SAndroid Build Coastguard Worker error:
2976*7c568831SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(val1);
2977*7c568831SAndroid Build Coastguard Worker return(NULL);
2978*7c568831SAndroid Build Coastguard Worker }
2979*7c568831SAndroid Build Coastguard Worker
2980*7c568831SAndroid Build Coastguard Worker
2981*7c568831SAndroid Build Coastguard Worker /**
2982*7c568831SAndroid Build Coastguard Worker * xmlXPathNodeSetMergeAndClear:
2983*7c568831SAndroid Build Coastguard Worker * @set1: the first NodeSet or NULL
2984*7c568831SAndroid Build Coastguard Worker * @set2: the second NodeSet
2985*7c568831SAndroid Build Coastguard Worker *
2986*7c568831SAndroid Build Coastguard Worker * Merges two nodesets, all nodes from @set2 are added to @set1.
2987*7c568831SAndroid Build Coastguard Worker * Checks for duplicate nodes. Clears set2.
2988*7c568831SAndroid Build Coastguard Worker *
2989*7c568831SAndroid Build Coastguard Worker * Returns @set1 once extended or NULL in case of error.
2990*7c568831SAndroid Build Coastguard Worker *
2991*7c568831SAndroid Build Coastguard Worker * Frees @set1 in case of error.
2992*7c568831SAndroid Build Coastguard Worker */
2993*7c568831SAndroid Build Coastguard Worker static xmlNodeSetPtr
xmlXPathNodeSetMergeAndClear(xmlNodeSetPtr set1,xmlNodeSetPtr set2)2994*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetMergeAndClear(xmlNodeSetPtr set1, xmlNodeSetPtr set2)
2995*7c568831SAndroid Build Coastguard Worker {
2996*7c568831SAndroid Build Coastguard Worker {
2997*7c568831SAndroid Build Coastguard Worker int i, j, initNbSet1;
2998*7c568831SAndroid Build Coastguard Worker xmlNodePtr n1, n2;
2999*7c568831SAndroid Build Coastguard Worker
3000*7c568831SAndroid Build Coastguard Worker initNbSet1 = set1->nodeNr;
3001*7c568831SAndroid Build Coastguard Worker for (i = 0;i < set2->nodeNr;i++) {
3002*7c568831SAndroid Build Coastguard Worker n2 = set2->nodeTab[i];
3003*7c568831SAndroid Build Coastguard Worker /*
3004*7c568831SAndroid Build Coastguard Worker * Skip duplicates.
3005*7c568831SAndroid Build Coastguard Worker */
3006*7c568831SAndroid Build Coastguard Worker for (j = 0; j < initNbSet1; j++) {
3007*7c568831SAndroid Build Coastguard Worker n1 = set1->nodeTab[j];
3008*7c568831SAndroid Build Coastguard Worker if (n1 == n2) {
3009*7c568831SAndroid Build Coastguard Worker goto skip_node;
3010*7c568831SAndroid Build Coastguard Worker } else if ((n1->type == XML_NAMESPACE_DECL) &&
3011*7c568831SAndroid Build Coastguard Worker (n2->type == XML_NAMESPACE_DECL))
3012*7c568831SAndroid Build Coastguard Worker {
3013*7c568831SAndroid Build Coastguard Worker if ((((xmlNsPtr) n1)->next == ((xmlNsPtr) n2)->next) &&
3014*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(((xmlNsPtr) n1)->prefix,
3015*7c568831SAndroid Build Coastguard Worker ((xmlNsPtr) n2)->prefix)))
3016*7c568831SAndroid Build Coastguard Worker {
3017*7c568831SAndroid Build Coastguard Worker /*
3018*7c568831SAndroid Build Coastguard Worker * Free the namespace node.
3019*7c568831SAndroid Build Coastguard Worker */
3020*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetFreeNs((xmlNsPtr) n2);
3021*7c568831SAndroid Build Coastguard Worker goto skip_node;
3022*7c568831SAndroid Build Coastguard Worker }
3023*7c568831SAndroid Build Coastguard Worker }
3024*7c568831SAndroid Build Coastguard Worker }
3025*7c568831SAndroid Build Coastguard Worker /*
3026*7c568831SAndroid Build Coastguard Worker * grow the nodeTab if needed
3027*7c568831SAndroid Build Coastguard Worker */
3028*7c568831SAndroid Build Coastguard Worker if (set1->nodeMax == 0) {
3029*7c568831SAndroid Build Coastguard Worker set1->nodeTab = (xmlNodePtr *) xmlMalloc(
3030*7c568831SAndroid Build Coastguard Worker XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
3031*7c568831SAndroid Build Coastguard Worker if (set1->nodeTab == NULL)
3032*7c568831SAndroid Build Coastguard Worker goto error;
3033*7c568831SAndroid Build Coastguard Worker memset(set1->nodeTab, 0,
3034*7c568831SAndroid Build Coastguard Worker XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
3035*7c568831SAndroid Build Coastguard Worker set1->nodeMax = XML_NODESET_DEFAULT;
3036*7c568831SAndroid Build Coastguard Worker } else if (set1->nodeNr >= set1->nodeMax) {
3037*7c568831SAndroid Build Coastguard Worker xmlNodePtr *temp;
3038*7c568831SAndroid Build Coastguard Worker
3039*7c568831SAndroid Build Coastguard Worker if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH)
3040*7c568831SAndroid Build Coastguard Worker goto error;
3041*7c568831SAndroid Build Coastguard Worker temp = (xmlNodePtr *) xmlRealloc(
3042*7c568831SAndroid Build Coastguard Worker set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr));
3043*7c568831SAndroid Build Coastguard Worker if (temp == NULL)
3044*7c568831SAndroid Build Coastguard Worker goto error;
3045*7c568831SAndroid Build Coastguard Worker set1->nodeTab = temp;
3046*7c568831SAndroid Build Coastguard Worker set1->nodeMax *= 2;
3047*7c568831SAndroid Build Coastguard Worker }
3048*7c568831SAndroid Build Coastguard Worker set1->nodeTab[set1->nodeNr++] = n2;
3049*7c568831SAndroid Build Coastguard Worker skip_node:
3050*7c568831SAndroid Build Coastguard Worker set2->nodeTab[i] = NULL;
3051*7c568831SAndroid Build Coastguard Worker }
3052*7c568831SAndroid Build Coastguard Worker }
3053*7c568831SAndroid Build Coastguard Worker set2->nodeNr = 0;
3054*7c568831SAndroid Build Coastguard Worker return(set1);
3055*7c568831SAndroid Build Coastguard Worker
3056*7c568831SAndroid Build Coastguard Worker error:
3057*7c568831SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(set1);
3058*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetClear(set2, 1);
3059*7c568831SAndroid Build Coastguard Worker return(NULL);
3060*7c568831SAndroid Build Coastguard Worker }
3061*7c568831SAndroid Build Coastguard Worker
3062*7c568831SAndroid Build Coastguard Worker /**
3063*7c568831SAndroid Build Coastguard Worker * xmlXPathNodeSetMergeAndClearNoDupls:
3064*7c568831SAndroid Build Coastguard Worker * @set1: the first NodeSet or NULL
3065*7c568831SAndroid Build Coastguard Worker * @set2: the second NodeSet
3066*7c568831SAndroid Build Coastguard Worker *
3067*7c568831SAndroid Build Coastguard Worker * Merges two nodesets, all nodes from @set2 are added to @set1.
3068*7c568831SAndroid Build Coastguard Worker * Doesn't check for duplicate nodes. Clears set2.
3069*7c568831SAndroid Build Coastguard Worker *
3070*7c568831SAndroid Build Coastguard Worker * Returns @set1 once extended or NULL in case of error.
3071*7c568831SAndroid Build Coastguard Worker *
3072*7c568831SAndroid Build Coastguard Worker * Frees @set1 in case of error.
3073*7c568831SAndroid Build Coastguard Worker */
3074*7c568831SAndroid Build Coastguard Worker static xmlNodeSetPtr
xmlXPathNodeSetMergeAndClearNoDupls(xmlNodeSetPtr set1,xmlNodeSetPtr set2)3075*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetMergeAndClearNoDupls(xmlNodeSetPtr set1, xmlNodeSetPtr set2)
3076*7c568831SAndroid Build Coastguard Worker {
3077*7c568831SAndroid Build Coastguard Worker {
3078*7c568831SAndroid Build Coastguard Worker int i;
3079*7c568831SAndroid Build Coastguard Worker xmlNodePtr n2;
3080*7c568831SAndroid Build Coastguard Worker
3081*7c568831SAndroid Build Coastguard Worker for (i = 0;i < set2->nodeNr;i++) {
3082*7c568831SAndroid Build Coastguard Worker n2 = set2->nodeTab[i];
3083*7c568831SAndroid Build Coastguard Worker if (set1->nodeMax == 0) {
3084*7c568831SAndroid Build Coastguard Worker set1->nodeTab = (xmlNodePtr *) xmlMalloc(
3085*7c568831SAndroid Build Coastguard Worker XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
3086*7c568831SAndroid Build Coastguard Worker if (set1->nodeTab == NULL)
3087*7c568831SAndroid Build Coastguard Worker goto error;
3088*7c568831SAndroid Build Coastguard Worker memset(set1->nodeTab, 0,
3089*7c568831SAndroid Build Coastguard Worker XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
3090*7c568831SAndroid Build Coastguard Worker set1->nodeMax = XML_NODESET_DEFAULT;
3091*7c568831SAndroid Build Coastguard Worker } else if (set1->nodeNr >= set1->nodeMax) {
3092*7c568831SAndroid Build Coastguard Worker xmlNodePtr *temp;
3093*7c568831SAndroid Build Coastguard Worker
3094*7c568831SAndroid Build Coastguard Worker if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH)
3095*7c568831SAndroid Build Coastguard Worker goto error;
3096*7c568831SAndroid Build Coastguard Worker temp = (xmlNodePtr *) xmlRealloc(
3097*7c568831SAndroid Build Coastguard Worker set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr));
3098*7c568831SAndroid Build Coastguard Worker if (temp == NULL)
3099*7c568831SAndroid Build Coastguard Worker goto error;
3100*7c568831SAndroid Build Coastguard Worker set1->nodeTab = temp;
3101*7c568831SAndroid Build Coastguard Worker set1->nodeMax *= 2;
3102*7c568831SAndroid Build Coastguard Worker }
3103*7c568831SAndroid Build Coastguard Worker set1->nodeTab[set1->nodeNr++] = n2;
3104*7c568831SAndroid Build Coastguard Worker set2->nodeTab[i] = NULL;
3105*7c568831SAndroid Build Coastguard Worker }
3106*7c568831SAndroid Build Coastguard Worker }
3107*7c568831SAndroid Build Coastguard Worker set2->nodeNr = 0;
3108*7c568831SAndroid Build Coastguard Worker return(set1);
3109*7c568831SAndroid Build Coastguard Worker
3110*7c568831SAndroid Build Coastguard Worker error:
3111*7c568831SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(set1);
3112*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetClear(set2, 1);
3113*7c568831SAndroid Build Coastguard Worker return(NULL);
3114*7c568831SAndroid Build Coastguard Worker }
3115*7c568831SAndroid Build Coastguard Worker
3116*7c568831SAndroid Build Coastguard Worker /**
3117*7c568831SAndroid Build Coastguard Worker * xmlXPathNodeSetDel:
3118*7c568831SAndroid Build Coastguard Worker * @cur: the initial node set
3119*7c568831SAndroid Build Coastguard Worker * @val: an xmlNodePtr
3120*7c568831SAndroid Build Coastguard Worker *
3121*7c568831SAndroid Build Coastguard Worker * Removes an xmlNodePtr from an existing NodeSet
3122*7c568831SAndroid Build Coastguard Worker */
3123*7c568831SAndroid Build Coastguard Worker void
xmlXPathNodeSetDel(xmlNodeSetPtr cur,xmlNodePtr val)3124*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetDel(xmlNodeSetPtr cur, xmlNodePtr val) {
3125*7c568831SAndroid Build Coastguard Worker int i;
3126*7c568831SAndroid Build Coastguard Worker
3127*7c568831SAndroid Build Coastguard Worker if (cur == NULL) return;
3128*7c568831SAndroid Build Coastguard Worker if (val == NULL) return;
3129*7c568831SAndroid Build Coastguard Worker
3130*7c568831SAndroid Build Coastguard Worker /*
3131*7c568831SAndroid Build Coastguard Worker * find node in nodeTab
3132*7c568831SAndroid Build Coastguard Worker */
3133*7c568831SAndroid Build Coastguard Worker for (i = 0;i < cur->nodeNr;i++)
3134*7c568831SAndroid Build Coastguard Worker if (cur->nodeTab[i] == val) break;
3135*7c568831SAndroid Build Coastguard Worker
3136*7c568831SAndroid Build Coastguard Worker if (i >= cur->nodeNr) { /* not found */
3137*7c568831SAndroid Build Coastguard Worker return;
3138*7c568831SAndroid Build Coastguard Worker }
3139*7c568831SAndroid Build Coastguard Worker if ((cur->nodeTab[i] != NULL) &&
3140*7c568831SAndroid Build Coastguard Worker (cur->nodeTab[i]->type == XML_NAMESPACE_DECL))
3141*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetFreeNs((xmlNsPtr) cur->nodeTab[i]);
3142*7c568831SAndroid Build Coastguard Worker cur->nodeNr--;
3143*7c568831SAndroid Build Coastguard Worker for (;i < cur->nodeNr;i++)
3144*7c568831SAndroid Build Coastguard Worker cur->nodeTab[i] = cur->nodeTab[i + 1];
3145*7c568831SAndroid Build Coastguard Worker cur->nodeTab[cur->nodeNr] = NULL;
3146*7c568831SAndroid Build Coastguard Worker }
3147*7c568831SAndroid Build Coastguard Worker
3148*7c568831SAndroid Build Coastguard Worker /**
3149*7c568831SAndroid Build Coastguard Worker * xmlXPathNodeSetRemove:
3150*7c568831SAndroid Build Coastguard Worker * @cur: the initial node set
3151*7c568831SAndroid Build Coastguard Worker * @val: the index to remove
3152*7c568831SAndroid Build Coastguard Worker *
3153*7c568831SAndroid Build Coastguard Worker * Removes an entry from an existing NodeSet list.
3154*7c568831SAndroid Build Coastguard Worker */
3155*7c568831SAndroid Build Coastguard Worker void
xmlXPathNodeSetRemove(xmlNodeSetPtr cur,int val)3156*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetRemove(xmlNodeSetPtr cur, int val) {
3157*7c568831SAndroid Build Coastguard Worker if (cur == NULL) return;
3158*7c568831SAndroid Build Coastguard Worker if (val >= cur->nodeNr) return;
3159*7c568831SAndroid Build Coastguard Worker if ((cur->nodeTab[val] != NULL) &&
3160*7c568831SAndroid Build Coastguard Worker (cur->nodeTab[val]->type == XML_NAMESPACE_DECL))
3161*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetFreeNs((xmlNsPtr) cur->nodeTab[val]);
3162*7c568831SAndroid Build Coastguard Worker cur->nodeNr--;
3163*7c568831SAndroid Build Coastguard Worker for (;val < cur->nodeNr;val++)
3164*7c568831SAndroid Build Coastguard Worker cur->nodeTab[val] = cur->nodeTab[val + 1];
3165*7c568831SAndroid Build Coastguard Worker cur->nodeTab[cur->nodeNr] = NULL;
3166*7c568831SAndroid Build Coastguard Worker }
3167*7c568831SAndroid Build Coastguard Worker
3168*7c568831SAndroid Build Coastguard Worker /**
3169*7c568831SAndroid Build Coastguard Worker * xmlXPathFreeNodeSet:
3170*7c568831SAndroid Build Coastguard Worker * @obj: the xmlNodeSetPtr to free
3171*7c568831SAndroid Build Coastguard Worker *
3172*7c568831SAndroid Build Coastguard Worker * Free the NodeSet compound (not the actual nodes !).
3173*7c568831SAndroid Build Coastguard Worker */
3174*7c568831SAndroid Build Coastguard Worker void
xmlXPathFreeNodeSet(xmlNodeSetPtr obj)3175*7c568831SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(xmlNodeSetPtr obj) {
3176*7c568831SAndroid Build Coastguard Worker if (obj == NULL) return;
3177*7c568831SAndroid Build Coastguard Worker if (obj->nodeTab != NULL) {
3178*7c568831SAndroid Build Coastguard Worker int i;
3179*7c568831SAndroid Build Coastguard Worker
3180*7c568831SAndroid Build Coastguard Worker /* @@ with_ns to check whether namespace nodes should be looked at @@ */
3181*7c568831SAndroid Build Coastguard Worker for (i = 0;i < obj->nodeNr;i++)
3182*7c568831SAndroid Build Coastguard Worker if ((obj->nodeTab[i] != NULL) &&
3183*7c568831SAndroid Build Coastguard Worker (obj->nodeTab[i]->type == XML_NAMESPACE_DECL))
3184*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetFreeNs((xmlNsPtr) obj->nodeTab[i]);
3185*7c568831SAndroid Build Coastguard Worker xmlFree(obj->nodeTab);
3186*7c568831SAndroid Build Coastguard Worker }
3187*7c568831SAndroid Build Coastguard Worker xmlFree(obj);
3188*7c568831SAndroid Build Coastguard Worker }
3189*7c568831SAndroid Build Coastguard Worker
3190*7c568831SAndroid Build Coastguard Worker /**
3191*7c568831SAndroid Build Coastguard Worker * xmlXPathNodeSetClearFromPos:
3192*7c568831SAndroid Build Coastguard Worker * @set: the node set to be cleared
3193*7c568831SAndroid Build Coastguard Worker * @pos: the start position to clear from
3194*7c568831SAndroid Build Coastguard Worker *
3195*7c568831SAndroid Build Coastguard Worker * Clears the list from temporary XPath objects (e.g. namespace nodes
3196*7c568831SAndroid Build Coastguard Worker * are feed) starting with the entry at @pos, but does *not* free the list
3197*7c568831SAndroid Build Coastguard Worker * itself. Sets the length of the list to @pos.
3198*7c568831SAndroid Build Coastguard Worker */
3199*7c568831SAndroid Build Coastguard Worker static void
xmlXPathNodeSetClearFromPos(xmlNodeSetPtr set,int pos,int hasNsNodes)3200*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetClearFromPos(xmlNodeSetPtr set, int pos, int hasNsNodes)
3201*7c568831SAndroid Build Coastguard Worker {
3202*7c568831SAndroid Build Coastguard Worker if ((set == NULL) || (pos >= set->nodeNr))
3203*7c568831SAndroid Build Coastguard Worker return;
3204*7c568831SAndroid Build Coastguard Worker else if ((hasNsNodes)) {
3205*7c568831SAndroid Build Coastguard Worker int i;
3206*7c568831SAndroid Build Coastguard Worker xmlNodePtr node;
3207*7c568831SAndroid Build Coastguard Worker
3208*7c568831SAndroid Build Coastguard Worker for (i = pos; i < set->nodeNr; i++) {
3209*7c568831SAndroid Build Coastguard Worker node = set->nodeTab[i];
3210*7c568831SAndroid Build Coastguard Worker if ((node != NULL) &&
3211*7c568831SAndroid Build Coastguard Worker (node->type == XML_NAMESPACE_DECL))
3212*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetFreeNs((xmlNsPtr) node);
3213*7c568831SAndroid Build Coastguard Worker }
3214*7c568831SAndroid Build Coastguard Worker }
3215*7c568831SAndroid Build Coastguard Worker set->nodeNr = pos;
3216*7c568831SAndroid Build Coastguard Worker }
3217*7c568831SAndroid Build Coastguard Worker
3218*7c568831SAndroid Build Coastguard Worker /**
3219*7c568831SAndroid Build Coastguard Worker * xmlXPathNodeSetClear:
3220*7c568831SAndroid Build Coastguard Worker * @set: the node set to clear
3221*7c568831SAndroid Build Coastguard Worker *
3222*7c568831SAndroid Build Coastguard Worker * Clears the list from all temporary XPath objects (e.g. namespace nodes
3223*7c568831SAndroid Build Coastguard Worker * are feed), but does *not* free the list itself. Sets the length of the
3224*7c568831SAndroid Build Coastguard Worker * list to 0.
3225*7c568831SAndroid Build Coastguard Worker */
3226*7c568831SAndroid Build Coastguard Worker static void
xmlXPathNodeSetClear(xmlNodeSetPtr set,int hasNsNodes)3227*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetClear(xmlNodeSetPtr set, int hasNsNodes)
3228*7c568831SAndroid Build Coastguard Worker {
3229*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetClearFromPos(set, 0, hasNsNodes);
3230*7c568831SAndroid Build Coastguard Worker }
3231*7c568831SAndroid Build Coastguard Worker
3232*7c568831SAndroid Build Coastguard Worker /**
3233*7c568831SAndroid Build Coastguard Worker * xmlXPathNodeSetKeepLast:
3234*7c568831SAndroid Build Coastguard Worker * @set: the node set to be cleared
3235*7c568831SAndroid Build Coastguard Worker *
3236*7c568831SAndroid Build Coastguard Worker * Move the last node to the first position and clear temporary XPath objects
3237*7c568831SAndroid Build Coastguard Worker * (e.g. namespace nodes) from all other nodes. Sets the length of the list
3238*7c568831SAndroid Build Coastguard Worker * to 1.
3239*7c568831SAndroid Build Coastguard Worker */
3240*7c568831SAndroid Build Coastguard Worker static void
xmlXPathNodeSetKeepLast(xmlNodeSetPtr set)3241*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetKeepLast(xmlNodeSetPtr set)
3242*7c568831SAndroid Build Coastguard Worker {
3243*7c568831SAndroid Build Coastguard Worker int i;
3244*7c568831SAndroid Build Coastguard Worker xmlNodePtr node;
3245*7c568831SAndroid Build Coastguard Worker
3246*7c568831SAndroid Build Coastguard Worker if ((set == NULL) || (set->nodeNr <= 1))
3247*7c568831SAndroid Build Coastguard Worker return;
3248*7c568831SAndroid Build Coastguard Worker for (i = 0; i < set->nodeNr - 1; i++) {
3249*7c568831SAndroid Build Coastguard Worker node = set->nodeTab[i];
3250*7c568831SAndroid Build Coastguard Worker if ((node != NULL) &&
3251*7c568831SAndroid Build Coastguard Worker (node->type == XML_NAMESPACE_DECL))
3252*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetFreeNs((xmlNsPtr) node);
3253*7c568831SAndroid Build Coastguard Worker }
3254*7c568831SAndroid Build Coastguard Worker set->nodeTab[0] = set->nodeTab[set->nodeNr-1];
3255*7c568831SAndroid Build Coastguard Worker set->nodeNr = 1;
3256*7c568831SAndroid Build Coastguard Worker }
3257*7c568831SAndroid Build Coastguard Worker
3258*7c568831SAndroid Build Coastguard Worker /**
3259*7c568831SAndroid Build Coastguard Worker * xmlXPathNewNodeSet:
3260*7c568831SAndroid Build Coastguard Worker * @val: the NodePtr value
3261*7c568831SAndroid Build Coastguard Worker *
3262*7c568831SAndroid Build Coastguard Worker * Create a new xmlXPathObjectPtr of type NodeSet and initialize
3263*7c568831SAndroid Build Coastguard Worker * it with the single Node @val
3264*7c568831SAndroid Build Coastguard Worker *
3265*7c568831SAndroid Build Coastguard Worker * Returns the newly created object.
3266*7c568831SAndroid Build Coastguard Worker */
3267*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathNewNodeSet(xmlNodePtr val)3268*7c568831SAndroid Build Coastguard Worker xmlXPathNewNodeSet(xmlNodePtr val) {
3269*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
3270*7c568831SAndroid Build Coastguard Worker
3271*7c568831SAndroid Build Coastguard Worker ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
3272*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
3273*7c568831SAndroid Build Coastguard Worker return(NULL);
3274*7c568831SAndroid Build Coastguard Worker memset(ret, 0 , sizeof(xmlXPathObject));
3275*7c568831SAndroid Build Coastguard Worker ret->type = XPATH_NODESET;
3276*7c568831SAndroid Build Coastguard Worker ret->boolval = 0;
3277*7c568831SAndroid Build Coastguard Worker ret->nodesetval = xmlXPathNodeSetCreate(val);
3278*7c568831SAndroid Build Coastguard Worker if (ret->nodesetval == NULL) {
3279*7c568831SAndroid Build Coastguard Worker xmlFree(ret);
3280*7c568831SAndroid Build Coastguard Worker return(NULL);
3281*7c568831SAndroid Build Coastguard Worker }
3282*7c568831SAndroid Build Coastguard Worker /* @@ with_ns to check whether namespace nodes should be looked at @@ */
3283*7c568831SAndroid Build Coastguard Worker return(ret);
3284*7c568831SAndroid Build Coastguard Worker }
3285*7c568831SAndroid Build Coastguard Worker
3286*7c568831SAndroid Build Coastguard Worker /**
3287*7c568831SAndroid Build Coastguard Worker * xmlXPathNewValueTree:
3288*7c568831SAndroid Build Coastguard Worker * @val: the NodePtr value
3289*7c568831SAndroid Build Coastguard Worker *
3290*7c568831SAndroid Build Coastguard Worker * Create a new xmlXPathObjectPtr of type Value Tree (XSLT) and initialize
3291*7c568831SAndroid Build Coastguard Worker * it with the tree root @val
3292*7c568831SAndroid Build Coastguard Worker *
3293*7c568831SAndroid Build Coastguard Worker * Returns the newly created object.
3294*7c568831SAndroid Build Coastguard Worker */
3295*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathNewValueTree(xmlNodePtr val)3296*7c568831SAndroid Build Coastguard Worker xmlXPathNewValueTree(xmlNodePtr val) {
3297*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
3298*7c568831SAndroid Build Coastguard Worker
3299*7c568831SAndroid Build Coastguard Worker ret = xmlXPathNewNodeSet(val);
3300*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
3301*7c568831SAndroid Build Coastguard Worker return(NULL);
3302*7c568831SAndroid Build Coastguard Worker ret->type = XPATH_XSLT_TREE;
3303*7c568831SAndroid Build Coastguard Worker
3304*7c568831SAndroid Build Coastguard Worker return(ret);
3305*7c568831SAndroid Build Coastguard Worker }
3306*7c568831SAndroid Build Coastguard Worker
3307*7c568831SAndroid Build Coastguard Worker /**
3308*7c568831SAndroid Build Coastguard Worker * xmlXPathNewNodeSetList:
3309*7c568831SAndroid Build Coastguard Worker * @val: an existing NodeSet
3310*7c568831SAndroid Build Coastguard Worker *
3311*7c568831SAndroid Build Coastguard Worker * Create a new xmlXPathObjectPtr of type NodeSet and initialize
3312*7c568831SAndroid Build Coastguard Worker * it with the Nodeset @val
3313*7c568831SAndroid Build Coastguard Worker *
3314*7c568831SAndroid Build Coastguard Worker * Returns the newly created object.
3315*7c568831SAndroid Build Coastguard Worker */
3316*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathNewNodeSetList(xmlNodeSetPtr val)3317*7c568831SAndroid Build Coastguard Worker xmlXPathNewNodeSetList(xmlNodeSetPtr val)
3318*7c568831SAndroid Build Coastguard Worker {
3319*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
3320*7c568831SAndroid Build Coastguard Worker
3321*7c568831SAndroid Build Coastguard Worker if (val == NULL)
3322*7c568831SAndroid Build Coastguard Worker ret = NULL;
3323*7c568831SAndroid Build Coastguard Worker else if (val->nodeTab == NULL)
3324*7c568831SAndroid Build Coastguard Worker ret = xmlXPathNewNodeSet(NULL);
3325*7c568831SAndroid Build Coastguard Worker else {
3326*7c568831SAndroid Build Coastguard Worker ret = xmlXPathNewNodeSet(val->nodeTab[0]);
3327*7c568831SAndroid Build Coastguard Worker if (ret) {
3328*7c568831SAndroid Build Coastguard Worker ret->nodesetval = xmlXPathNodeSetMerge(NULL, val);
3329*7c568831SAndroid Build Coastguard Worker if (ret->nodesetval == NULL) {
3330*7c568831SAndroid Build Coastguard Worker xmlFree(ret);
3331*7c568831SAndroid Build Coastguard Worker return(NULL);
3332*7c568831SAndroid Build Coastguard Worker }
3333*7c568831SAndroid Build Coastguard Worker }
3334*7c568831SAndroid Build Coastguard Worker }
3335*7c568831SAndroid Build Coastguard Worker
3336*7c568831SAndroid Build Coastguard Worker return (ret);
3337*7c568831SAndroid Build Coastguard Worker }
3338*7c568831SAndroid Build Coastguard Worker
3339*7c568831SAndroid Build Coastguard Worker /**
3340*7c568831SAndroid Build Coastguard Worker * xmlXPathWrapNodeSet:
3341*7c568831SAndroid Build Coastguard Worker * @val: the NodePtr value
3342*7c568831SAndroid Build Coastguard Worker *
3343*7c568831SAndroid Build Coastguard Worker * Wrap the Nodeset @val in a new xmlXPathObjectPtr
3344*7c568831SAndroid Build Coastguard Worker *
3345*7c568831SAndroid Build Coastguard Worker * Returns the newly created object.
3346*7c568831SAndroid Build Coastguard Worker *
3347*7c568831SAndroid Build Coastguard Worker * In case of error the node set is destroyed and NULL is returned.
3348*7c568831SAndroid Build Coastguard Worker */
3349*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathWrapNodeSet(xmlNodeSetPtr val)3350*7c568831SAndroid Build Coastguard Worker xmlXPathWrapNodeSet(xmlNodeSetPtr val) {
3351*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
3352*7c568831SAndroid Build Coastguard Worker
3353*7c568831SAndroid Build Coastguard Worker ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
3354*7c568831SAndroid Build Coastguard Worker if (ret == NULL) {
3355*7c568831SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(val);
3356*7c568831SAndroid Build Coastguard Worker return(NULL);
3357*7c568831SAndroid Build Coastguard Worker }
3358*7c568831SAndroid Build Coastguard Worker memset(ret, 0 , sizeof(xmlXPathObject));
3359*7c568831SAndroid Build Coastguard Worker ret->type = XPATH_NODESET;
3360*7c568831SAndroid Build Coastguard Worker ret->nodesetval = val;
3361*7c568831SAndroid Build Coastguard Worker return(ret);
3362*7c568831SAndroid Build Coastguard Worker }
3363*7c568831SAndroid Build Coastguard Worker
3364*7c568831SAndroid Build Coastguard Worker /**
3365*7c568831SAndroid Build Coastguard Worker * xmlXPathFreeNodeSetList:
3366*7c568831SAndroid Build Coastguard Worker * @obj: an existing NodeSetList object
3367*7c568831SAndroid Build Coastguard Worker *
3368*7c568831SAndroid Build Coastguard Worker * Free up the xmlXPathObjectPtr @obj but don't deallocate the objects in
3369*7c568831SAndroid Build Coastguard Worker * the list contrary to xmlXPathFreeObject().
3370*7c568831SAndroid Build Coastguard Worker */
3371*7c568831SAndroid Build Coastguard Worker void
xmlXPathFreeNodeSetList(xmlXPathObjectPtr obj)3372*7c568831SAndroid Build Coastguard Worker xmlXPathFreeNodeSetList(xmlXPathObjectPtr obj) {
3373*7c568831SAndroid Build Coastguard Worker if (obj == NULL) return;
3374*7c568831SAndroid Build Coastguard Worker xmlFree(obj);
3375*7c568831SAndroid Build Coastguard Worker }
3376*7c568831SAndroid Build Coastguard Worker
3377*7c568831SAndroid Build Coastguard Worker /**
3378*7c568831SAndroid Build Coastguard Worker * xmlXPathDifference:
3379*7c568831SAndroid Build Coastguard Worker * @nodes1: a node-set
3380*7c568831SAndroid Build Coastguard Worker * @nodes2: a node-set
3381*7c568831SAndroid Build Coastguard Worker *
3382*7c568831SAndroid Build Coastguard Worker * Implements the EXSLT - Sets difference() function:
3383*7c568831SAndroid Build Coastguard Worker * node-set set:difference (node-set, node-set)
3384*7c568831SAndroid Build Coastguard Worker *
3385*7c568831SAndroid Build Coastguard Worker * Returns the difference between the two node sets, or nodes1 if
3386*7c568831SAndroid Build Coastguard Worker * nodes2 is empty
3387*7c568831SAndroid Build Coastguard Worker */
3388*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathDifference(xmlNodeSetPtr nodes1,xmlNodeSetPtr nodes2)3389*7c568831SAndroid Build Coastguard Worker xmlXPathDifference (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
3390*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr ret;
3391*7c568831SAndroid Build Coastguard Worker int i, l1;
3392*7c568831SAndroid Build Coastguard Worker xmlNodePtr cur;
3393*7c568831SAndroid Build Coastguard Worker
3394*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes2))
3395*7c568831SAndroid Build Coastguard Worker return(nodes1);
3396*7c568831SAndroid Build Coastguard Worker
3397*7c568831SAndroid Build Coastguard Worker ret = xmlXPathNodeSetCreate(NULL);
3398*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
3399*7c568831SAndroid Build Coastguard Worker return(NULL);
3400*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes1))
3401*7c568831SAndroid Build Coastguard Worker return(ret);
3402*7c568831SAndroid Build Coastguard Worker
3403*7c568831SAndroid Build Coastguard Worker l1 = xmlXPathNodeSetGetLength(nodes1);
3404*7c568831SAndroid Build Coastguard Worker
3405*7c568831SAndroid Build Coastguard Worker for (i = 0; i < l1; i++) {
3406*7c568831SAndroid Build Coastguard Worker cur = xmlXPathNodeSetItem(nodes1, i);
3407*7c568831SAndroid Build Coastguard Worker if (!xmlXPathNodeSetContains(nodes2, cur)) {
3408*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetAddUnique(ret, cur) < 0) {
3409*7c568831SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(ret);
3410*7c568831SAndroid Build Coastguard Worker return(NULL);
3411*7c568831SAndroid Build Coastguard Worker }
3412*7c568831SAndroid Build Coastguard Worker }
3413*7c568831SAndroid Build Coastguard Worker }
3414*7c568831SAndroid Build Coastguard Worker return(ret);
3415*7c568831SAndroid Build Coastguard Worker }
3416*7c568831SAndroid Build Coastguard Worker
3417*7c568831SAndroid Build Coastguard Worker /**
3418*7c568831SAndroid Build Coastguard Worker * xmlXPathIntersection:
3419*7c568831SAndroid Build Coastguard Worker * @nodes1: a node-set
3420*7c568831SAndroid Build Coastguard Worker * @nodes2: a node-set
3421*7c568831SAndroid Build Coastguard Worker *
3422*7c568831SAndroid Build Coastguard Worker * Implements the EXSLT - Sets intersection() function:
3423*7c568831SAndroid Build Coastguard Worker * node-set set:intersection (node-set, node-set)
3424*7c568831SAndroid Build Coastguard Worker *
3425*7c568831SAndroid Build Coastguard Worker * Returns a node set comprising the nodes that are within both the
3426*7c568831SAndroid Build Coastguard Worker * node sets passed as arguments
3427*7c568831SAndroid Build Coastguard Worker */
3428*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathIntersection(xmlNodeSetPtr nodes1,xmlNodeSetPtr nodes2)3429*7c568831SAndroid Build Coastguard Worker xmlXPathIntersection (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
3430*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr ret = xmlXPathNodeSetCreate(NULL);
3431*7c568831SAndroid Build Coastguard Worker int i, l1;
3432*7c568831SAndroid Build Coastguard Worker xmlNodePtr cur;
3433*7c568831SAndroid Build Coastguard Worker
3434*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
3435*7c568831SAndroid Build Coastguard Worker return(ret);
3436*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes1))
3437*7c568831SAndroid Build Coastguard Worker return(ret);
3438*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes2))
3439*7c568831SAndroid Build Coastguard Worker return(ret);
3440*7c568831SAndroid Build Coastguard Worker
3441*7c568831SAndroid Build Coastguard Worker l1 = xmlXPathNodeSetGetLength(nodes1);
3442*7c568831SAndroid Build Coastguard Worker
3443*7c568831SAndroid Build Coastguard Worker for (i = 0; i < l1; i++) {
3444*7c568831SAndroid Build Coastguard Worker cur = xmlXPathNodeSetItem(nodes1, i);
3445*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetContains(nodes2, cur)) {
3446*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetAddUnique(ret, cur) < 0) {
3447*7c568831SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(ret);
3448*7c568831SAndroid Build Coastguard Worker return(NULL);
3449*7c568831SAndroid Build Coastguard Worker }
3450*7c568831SAndroid Build Coastguard Worker }
3451*7c568831SAndroid Build Coastguard Worker }
3452*7c568831SAndroid Build Coastguard Worker return(ret);
3453*7c568831SAndroid Build Coastguard Worker }
3454*7c568831SAndroid Build Coastguard Worker
3455*7c568831SAndroid Build Coastguard Worker /**
3456*7c568831SAndroid Build Coastguard Worker * xmlXPathDistinctSorted:
3457*7c568831SAndroid Build Coastguard Worker * @nodes: a node-set, sorted by document order
3458*7c568831SAndroid Build Coastguard Worker *
3459*7c568831SAndroid Build Coastguard Worker * Implements the EXSLT - Sets distinct() function:
3460*7c568831SAndroid Build Coastguard Worker * node-set set:distinct (node-set)
3461*7c568831SAndroid Build Coastguard Worker *
3462*7c568831SAndroid Build Coastguard Worker * Returns a subset of the nodes contained in @nodes, or @nodes if
3463*7c568831SAndroid Build Coastguard Worker * it is empty
3464*7c568831SAndroid Build Coastguard Worker */
3465*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathDistinctSorted(xmlNodeSetPtr nodes)3466*7c568831SAndroid Build Coastguard Worker xmlXPathDistinctSorted (xmlNodeSetPtr nodes) {
3467*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr ret;
3468*7c568831SAndroid Build Coastguard Worker xmlHashTablePtr hash;
3469*7c568831SAndroid Build Coastguard Worker int i, l;
3470*7c568831SAndroid Build Coastguard Worker xmlChar * strval;
3471*7c568831SAndroid Build Coastguard Worker xmlNodePtr cur;
3472*7c568831SAndroid Build Coastguard Worker
3473*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes))
3474*7c568831SAndroid Build Coastguard Worker return(nodes);
3475*7c568831SAndroid Build Coastguard Worker
3476*7c568831SAndroid Build Coastguard Worker ret = xmlXPathNodeSetCreate(NULL);
3477*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
3478*7c568831SAndroid Build Coastguard Worker return(ret);
3479*7c568831SAndroid Build Coastguard Worker l = xmlXPathNodeSetGetLength(nodes);
3480*7c568831SAndroid Build Coastguard Worker hash = xmlHashCreate (l);
3481*7c568831SAndroid Build Coastguard Worker for (i = 0; i < l; i++) {
3482*7c568831SAndroid Build Coastguard Worker cur = xmlXPathNodeSetItem(nodes, i);
3483*7c568831SAndroid Build Coastguard Worker strval = xmlXPathCastNodeToString(cur);
3484*7c568831SAndroid Build Coastguard Worker if (xmlHashLookup(hash, strval) == NULL) {
3485*7c568831SAndroid Build Coastguard Worker if (xmlHashAddEntry(hash, strval, strval) < 0) {
3486*7c568831SAndroid Build Coastguard Worker xmlFree(strval);
3487*7c568831SAndroid Build Coastguard Worker goto error;
3488*7c568831SAndroid Build Coastguard Worker }
3489*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
3490*7c568831SAndroid Build Coastguard Worker goto error;
3491*7c568831SAndroid Build Coastguard Worker } else {
3492*7c568831SAndroid Build Coastguard Worker xmlFree(strval);
3493*7c568831SAndroid Build Coastguard Worker }
3494*7c568831SAndroid Build Coastguard Worker }
3495*7c568831SAndroid Build Coastguard Worker xmlHashFree(hash, xmlHashDefaultDeallocator);
3496*7c568831SAndroid Build Coastguard Worker return(ret);
3497*7c568831SAndroid Build Coastguard Worker
3498*7c568831SAndroid Build Coastguard Worker error:
3499*7c568831SAndroid Build Coastguard Worker xmlHashFree(hash, xmlHashDefaultDeallocator);
3500*7c568831SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(ret);
3501*7c568831SAndroid Build Coastguard Worker return(NULL);
3502*7c568831SAndroid Build Coastguard Worker }
3503*7c568831SAndroid Build Coastguard Worker
3504*7c568831SAndroid Build Coastguard Worker /**
3505*7c568831SAndroid Build Coastguard Worker * xmlXPathDistinct:
3506*7c568831SAndroid Build Coastguard Worker * @nodes: a node-set
3507*7c568831SAndroid Build Coastguard Worker *
3508*7c568831SAndroid Build Coastguard Worker * Implements the EXSLT - Sets distinct() function:
3509*7c568831SAndroid Build Coastguard Worker * node-set set:distinct (node-set)
3510*7c568831SAndroid Build Coastguard Worker * @nodes is sorted by document order, then #exslSetsDistinctSorted
3511*7c568831SAndroid Build Coastguard Worker * is called with the sorted node-set
3512*7c568831SAndroid Build Coastguard Worker *
3513*7c568831SAndroid Build Coastguard Worker * Returns a subset of the nodes contained in @nodes, or @nodes if
3514*7c568831SAndroid Build Coastguard Worker * it is empty
3515*7c568831SAndroid Build Coastguard Worker */
3516*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathDistinct(xmlNodeSetPtr nodes)3517*7c568831SAndroid Build Coastguard Worker xmlXPathDistinct (xmlNodeSetPtr nodes) {
3518*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes))
3519*7c568831SAndroid Build Coastguard Worker return(nodes);
3520*7c568831SAndroid Build Coastguard Worker
3521*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetSort(nodes);
3522*7c568831SAndroid Build Coastguard Worker return(xmlXPathDistinctSorted(nodes));
3523*7c568831SAndroid Build Coastguard Worker }
3524*7c568831SAndroid Build Coastguard Worker
3525*7c568831SAndroid Build Coastguard Worker /**
3526*7c568831SAndroid Build Coastguard Worker * xmlXPathHasSameNodes:
3527*7c568831SAndroid Build Coastguard Worker * @nodes1: a node-set
3528*7c568831SAndroid Build Coastguard Worker * @nodes2: a node-set
3529*7c568831SAndroid Build Coastguard Worker *
3530*7c568831SAndroid Build Coastguard Worker * Implements the EXSLT - Sets has-same-nodes function:
3531*7c568831SAndroid Build Coastguard Worker * boolean set:has-same-node(node-set, node-set)
3532*7c568831SAndroid Build Coastguard Worker *
3533*7c568831SAndroid Build Coastguard Worker * Returns true (1) if @nodes1 shares any node with @nodes2, false (0)
3534*7c568831SAndroid Build Coastguard Worker * otherwise
3535*7c568831SAndroid Build Coastguard Worker */
3536*7c568831SAndroid Build Coastguard Worker int
xmlXPathHasSameNodes(xmlNodeSetPtr nodes1,xmlNodeSetPtr nodes2)3537*7c568831SAndroid Build Coastguard Worker xmlXPathHasSameNodes (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
3538*7c568831SAndroid Build Coastguard Worker int i, l;
3539*7c568831SAndroid Build Coastguard Worker xmlNodePtr cur;
3540*7c568831SAndroid Build Coastguard Worker
3541*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes1) ||
3542*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetIsEmpty(nodes2))
3543*7c568831SAndroid Build Coastguard Worker return(0);
3544*7c568831SAndroid Build Coastguard Worker
3545*7c568831SAndroid Build Coastguard Worker l = xmlXPathNodeSetGetLength(nodes1);
3546*7c568831SAndroid Build Coastguard Worker for (i = 0; i < l; i++) {
3547*7c568831SAndroid Build Coastguard Worker cur = xmlXPathNodeSetItem(nodes1, i);
3548*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetContains(nodes2, cur))
3549*7c568831SAndroid Build Coastguard Worker return(1);
3550*7c568831SAndroid Build Coastguard Worker }
3551*7c568831SAndroid Build Coastguard Worker return(0);
3552*7c568831SAndroid Build Coastguard Worker }
3553*7c568831SAndroid Build Coastguard Worker
3554*7c568831SAndroid Build Coastguard Worker /**
3555*7c568831SAndroid Build Coastguard Worker * xmlXPathNodeLeadingSorted:
3556*7c568831SAndroid Build Coastguard Worker * @nodes: a node-set, sorted by document order
3557*7c568831SAndroid Build Coastguard Worker * @node: a node
3558*7c568831SAndroid Build Coastguard Worker *
3559*7c568831SAndroid Build Coastguard Worker * Implements the EXSLT - Sets leading() function:
3560*7c568831SAndroid Build Coastguard Worker * node-set set:leading (node-set, node-set)
3561*7c568831SAndroid Build Coastguard Worker *
3562*7c568831SAndroid Build Coastguard Worker * Returns the nodes in @nodes that precede @node in document order,
3563*7c568831SAndroid Build Coastguard Worker * @nodes if @node is NULL or an empty node-set if @nodes
3564*7c568831SAndroid Build Coastguard Worker * doesn't contain @node
3565*7c568831SAndroid Build Coastguard Worker */
3566*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathNodeLeadingSorted(xmlNodeSetPtr nodes,xmlNodePtr node)3567*7c568831SAndroid Build Coastguard Worker xmlXPathNodeLeadingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) {
3568*7c568831SAndroid Build Coastguard Worker int i, l;
3569*7c568831SAndroid Build Coastguard Worker xmlNodePtr cur;
3570*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr ret;
3571*7c568831SAndroid Build Coastguard Worker
3572*7c568831SAndroid Build Coastguard Worker if (node == NULL)
3573*7c568831SAndroid Build Coastguard Worker return(nodes);
3574*7c568831SAndroid Build Coastguard Worker
3575*7c568831SAndroid Build Coastguard Worker ret = xmlXPathNodeSetCreate(NULL);
3576*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
3577*7c568831SAndroid Build Coastguard Worker return(ret);
3578*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes) ||
3579*7c568831SAndroid Build Coastguard Worker (!xmlXPathNodeSetContains(nodes, node)))
3580*7c568831SAndroid Build Coastguard Worker return(ret);
3581*7c568831SAndroid Build Coastguard Worker
3582*7c568831SAndroid Build Coastguard Worker l = xmlXPathNodeSetGetLength(nodes);
3583*7c568831SAndroid Build Coastguard Worker for (i = 0; i < l; i++) {
3584*7c568831SAndroid Build Coastguard Worker cur = xmlXPathNodeSetItem(nodes, i);
3585*7c568831SAndroid Build Coastguard Worker if (cur == node)
3586*7c568831SAndroid Build Coastguard Worker break;
3587*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetAddUnique(ret, cur) < 0) {
3588*7c568831SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(ret);
3589*7c568831SAndroid Build Coastguard Worker return(NULL);
3590*7c568831SAndroid Build Coastguard Worker }
3591*7c568831SAndroid Build Coastguard Worker }
3592*7c568831SAndroid Build Coastguard Worker return(ret);
3593*7c568831SAndroid Build Coastguard Worker }
3594*7c568831SAndroid Build Coastguard Worker
3595*7c568831SAndroid Build Coastguard Worker /**
3596*7c568831SAndroid Build Coastguard Worker * xmlXPathNodeLeading:
3597*7c568831SAndroid Build Coastguard Worker * @nodes: a node-set
3598*7c568831SAndroid Build Coastguard Worker * @node: a node
3599*7c568831SAndroid Build Coastguard Worker *
3600*7c568831SAndroid Build Coastguard Worker * Implements the EXSLT - Sets leading() function:
3601*7c568831SAndroid Build Coastguard Worker * node-set set:leading (node-set, node-set)
3602*7c568831SAndroid Build Coastguard Worker * @nodes is sorted by document order, then #exslSetsNodeLeadingSorted
3603*7c568831SAndroid Build Coastguard Worker * is called.
3604*7c568831SAndroid Build Coastguard Worker *
3605*7c568831SAndroid Build Coastguard Worker * Returns the nodes in @nodes that precede @node in document order,
3606*7c568831SAndroid Build Coastguard Worker * @nodes if @node is NULL or an empty node-set if @nodes
3607*7c568831SAndroid Build Coastguard Worker * doesn't contain @node
3608*7c568831SAndroid Build Coastguard Worker */
3609*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathNodeLeading(xmlNodeSetPtr nodes,xmlNodePtr node)3610*7c568831SAndroid Build Coastguard Worker xmlXPathNodeLeading (xmlNodeSetPtr nodes, xmlNodePtr node) {
3611*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetSort(nodes);
3612*7c568831SAndroid Build Coastguard Worker return(xmlXPathNodeLeadingSorted(nodes, node));
3613*7c568831SAndroid Build Coastguard Worker }
3614*7c568831SAndroid Build Coastguard Worker
3615*7c568831SAndroid Build Coastguard Worker /**
3616*7c568831SAndroid Build Coastguard Worker * xmlXPathLeadingSorted:
3617*7c568831SAndroid Build Coastguard Worker * @nodes1: a node-set, sorted by document order
3618*7c568831SAndroid Build Coastguard Worker * @nodes2: a node-set, sorted by document order
3619*7c568831SAndroid Build Coastguard Worker *
3620*7c568831SAndroid Build Coastguard Worker * Implements the EXSLT - Sets leading() function:
3621*7c568831SAndroid Build Coastguard Worker * node-set set:leading (node-set, node-set)
3622*7c568831SAndroid Build Coastguard Worker *
3623*7c568831SAndroid Build Coastguard Worker * Returns the nodes in @nodes1 that precede the first node in @nodes2
3624*7c568831SAndroid Build Coastguard Worker * in document order, @nodes1 if @nodes2 is NULL or empty or
3625*7c568831SAndroid Build Coastguard Worker * an empty node-set if @nodes1 doesn't contain @nodes2
3626*7c568831SAndroid Build Coastguard Worker */
3627*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathLeadingSorted(xmlNodeSetPtr nodes1,xmlNodeSetPtr nodes2)3628*7c568831SAndroid Build Coastguard Worker xmlXPathLeadingSorted (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
3629*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes2))
3630*7c568831SAndroid Build Coastguard Worker return(nodes1);
3631*7c568831SAndroid Build Coastguard Worker return(xmlXPathNodeLeadingSorted(nodes1,
3632*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetItem(nodes2, 1)));
3633*7c568831SAndroid Build Coastguard Worker }
3634*7c568831SAndroid Build Coastguard Worker
3635*7c568831SAndroid Build Coastguard Worker /**
3636*7c568831SAndroid Build Coastguard Worker * xmlXPathLeading:
3637*7c568831SAndroid Build Coastguard Worker * @nodes1: a node-set
3638*7c568831SAndroid Build Coastguard Worker * @nodes2: a node-set
3639*7c568831SAndroid Build Coastguard Worker *
3640*7c568831SAndroid Build Coastguard Worker * Implements the EXSLT - Sets leading() function:
3641*7c568831SAndroid Build Coastguard Worker * node-set set:leading (node-set, node-set)
3642*7c568831SAndroid Build Coastguard Worker * @nodes1 and @nodes2 are sorted by document order, then
3643*7c568831SAndroid Build Coastguard Worker * #exslSetsLeadingSorted is called.
3644*7c568831SAndroid Build Coastguard Worker *
3645*7c568831SAndroid Build Coastguard Worker * Returns the nodes in @nodes1 that precede the first node in @nodes2
3646*7c568831SAndroid Build Coastguard Worker * in document order, @nodes1 if @nodes2 is NULL or empty or
3647*7c568831SAndroid Build Coastguard Worker * an empty node-set if @nodes1 doesn't contain @nodes2
3648*7c568831SAndroid Build Coastguard Worker */
3649*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathLeading(xmlNodeSetPtr nodes1,xmlNodeSetPtr nodes2)3650*7c568831SAndroid Build Coastguard Worker xmlXPathLeading (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
3651*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes2))
3652*7c568831SAndroid Build Coastguard Worker return(nodes1);
3653*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes1))
3654*7c568831SAndroid Build Coastguard Worker return(xmlXPathNodeSetCreate(NULL));
3655*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetSort(nodes1);
3656*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetSort(nodes2);
3657*7c568831SAndroid Build Coastguard Worker return(xmlXPathNodeLeadingSorted(nodes1,
3658*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetItem(nodes2, 1)));
3659*7c568831SAndroid Build Coastguard Worker }
3660*7c568831SAndroid Build Coastguard Worker
3661*7c568831SAndroid Build Coastguard Worker /**
3662*7c568831SAndroid Build Coastguard Worker * xmlXPathNodeTrailingSorted:
3663*7c568831SAndroid Build Coastguard Worker * @nodes: a node-set, sorted by document order
3664*7c568831SAndroid Build Coastguard Worker * @node: a node
3665*7c568831SAndroid Build Coastguard Worker *
3666*7c568831SAndroid Build Coastguard Worker * Implements the EXSLT - Sets trailing() function:
3667*7c568831SAndroid Build Coastguard Worker * node-set set:trailing (node-set, node-set)
3668*7c568831SAndroid Build Coastguard Worker *
3669*7c568831SAndroid Build Coastguard Worker * Returns the nodes in @nodes that follow @node in document order,
3670*7c568831SAndroid Build Coastguard Worker * @nodes if @node is NULL or an empty node-set if @nodes
3671*7c568831SAndroid Build Coastguard Worker * doesn't contain @node
3672*7c568831SAndroid Build Coastguard Worker */
3673*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathNodeTrailingSorted(xmlNodeSetPtr nodes,xmlNodePtr node)3674*7c568831SAndroid Build Coastguard Worker xmlXPathNodeTrailingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) {
3675*7c568831SAndroid Build Coastguard Worker int i, l;
3676*7c568831SAndroid Build Coastguard Worker xmlNodePtr cur;
3677*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr ret;
3678*7c568831SAndroid Build Coastguard Worker
3679*7c568831SAndroid Build Coastguard Worker if (node == NULL)
3680*7c568831SAndroid Build Coastguard Worker return(nodes);
3681*7c568831SAndroid Build Coastguard Worker
3682*7c568831SAndroid Build Coastguard Worker ret = xmlXPathNodeSetCreate(NULL);
3683*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
3684*7c568831SAndroid Build Coastguard Worker return(ret);
3685*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes) ||
3686*7c568831SAndroid Build Coastguard Worker (!xmlXPathNodeSetContains(nodes, node)))
3687*7c568831SAndroid Build Coastguard Worker return(ret);
3688*7c568831SAndroid Build Coastguard Worker
3689*7c568831SAndroid Build Coastguard Worker l = xmlXPathNodeSetGetLength(nodes);
3690*7c568831SAndroid Build Coastguard Worker for (i = l - 1; i >= 0; i--) {
3691*7c568831SAndroid Build Coastguard Worker cur = xmlXPathNodeSetItem(nodes, i);
3692*7c568831SAndroid Build Coastguard Worker if (cur == node)
3693*7c568831SAndroid Build Coastguard Worker break;
3694*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetAddUnique(ret, cur) < 0) {
3695*7c568831SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(ret);
3696*7c568831SAndroid Build Coastguard Worker return(NULL);
3697*7c568831SAndroid Build Coastguard Worker }
3698*7c568831SAndroid Build Coastguard Worker }
3699*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetSort(ret); /* bug 413451 */
3700*7c568831SAndroid Build Coastguard Worker return(ret);
3701*7c568831SAndroid Build Coastguard Worker }
3702*7c568831SAndroid Build Coastguard Worker
3703*7c568831SAndroid Build Coastguard Worker /**
3704*7c568831SAndroid Build Coastguard Worker * xmlXPathNodeTrailing:
3705*7c568831SAndroid Build Coastguard Worker * @nodes: a node-set
3706*7c568831SAndroid Build Coastguard Worker * @node: a node
3707*7c568831SAndroid Build Coastguard Worker *
3708*7c568831SAndroid Build Coastguard Worker * Implements the EXSLT - Sets trailing() function:
3709*7c568831SAndroid Build Coastguard Worker * node-set set:trailing (node-set, node-set)
3710*7c568831SAndroid Build Coastguard Worker * @nodes is sorted by document order, then #xmlXPathNodeTrailingSorted
3711*7c568831SAndroid Build Coastguard Worker * is called.
3712*7c568831SAndroid Build Coastguard Worker *
3713*7c568831SAndroid Build Coastguard Worker * Returns the nodes in @nodes that follow @node in document order,
3714*7c568831SAndroid Build Coastguard Worker * @nodes if @node is NULL or an empty node-set if @nodes
3715*7c568831SAndroid Build Coastguard Worker * doesn't contain @node
3716*7c568831SAndroid Build Coastguard Worker */
3717*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathNodeTrailing(xmlNodeSetPtr nodes,xmlNodePtr node)3718*7c568831SAndroid Build Coastguard Worker xmlXPathNodeTrailing (xmlNodeSetPtr nodes, xmlNodePtr node) {
3719*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetSort(nodes);
3720*7c568831SAndroid Build Coastguard Worker return(xmlXPathNodeTrailingSorted(nodes, node));
3721*7c568831SAndroid Build Coastguard Worker }
3722*7c568831SAndroid Build Coastguard Worker
3723*7c568831SAndroid Build Coastguard Worker /**
3724*7c568831SAndroid Build Coastguard Worker * xmlXPathTrailingSorted:
3725*7c568831SAndroid Build Coastguard Worker * @nodes1: a node-set, sorted by document order
3726*7c568831SAndroid Build Coastguard Worker * @nodes2: a node-set, sorted by document order
3727*7c568831SAndroid Build Coastguard Worker *
3728*7c568831SAndroid Build Coastguard Worker * Implements the EXSLT - Sets trailing() function:
3729*7c568831SAndroid Build Coastguard Worker * node-set set:trailing (node-set, node-set)
3730*7c568831SAndroid Build Coastguard Worker *
3731*7c568831SAndroid Build Coastguard Worker * Returns the nodes in @nodes1 that follow the first node in @nodes2
3732*7c568831SAndroid Build Coastguard Worker * in document order, @nodes1 if @nodes2 is NULL or empty or
3733*7c568831SAndroid Build Coastguard Worker * an empty node-set if @nodes1 doesn't contain @nodes2
3734*7c568831SAndroid Build Coastguard Worker */
3735*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathTrailingSorted(xmlNodeSetPtr nodes1,xmlNodeSetPtr nodes2)3736*7c568831SAndroid Build Coastguard Worker xmlXPathTrailingSorted (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
3737*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes2))
3738*7c568831SAndroid Build Coastguard Worker return(nodes1);
3739*7c568831SAndroid Build Coastguard Worker return(xmlXPathNodeTrailingSorted(nodes1,
3740*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetItem(nodes2, 0)));
3741*7c568831SAndroid Build Coastguard Worker }
3742*7c568831SAndroid Build Coastguard Worker
3743*7c568831SAndroid Build Coastguard Worker /**
3744*7c568831SAndroid Build Coastguard Worker * xmlXPathTrailing:
3745*7c568831SAndroid Build Coastguard Worker * @nodes1: a node-set
3746*7c568831SAndroid Build Coastguard Worker * @nodes2: a node-set
3747*7c568831SAndroid Build Coastguard Worker *
3748*7c568831SAndroid Build Coastguard Worker * Implements the EXSLT - Sets trailing() function:
3749*7c568831SAndroid Build Coastguard Worker * node-set set:trailing (node-set, node-set)
3750*7c568831SAndroid Build Coastguard Worker * @nodes1 and @nodes2 are sorted by document order, then
3751*7c568831SAndroid Build Coastguard Worker * #xmlXPathTrailingSorted is called.
3752*7c568831SAndroid Build Coastguard Worker *
3753*7c568831SAndroid Build Coastguard Worker * Returns the nodes in @nodes1 that follow the first node in @nodes2
3754*7c568831SAndroid Build Coastguard Worker * in document order, @nodes1 if @nodes2 is NULL or empty or
3755*7c568831SAndroid Build Coastguard Worker * an empty node-set if @nodes1 doesn't contain @nodes2
3756*7c568831SAndroid Build Coastguard Worker */
3757*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathTrailing(xmlNodeSetPtr nodes1,xmlNodeSetPtr nodes2)3758*7c568831SAndroid Build Coastguard Worker xmlXPathTrailing (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
3759*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes2))
3760*7c568831SAndroid Build Coastguard Worker return(nodes1);
3761*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes1))
3762*7c568831SAndroid Build Coastguard Worker return(xmlXPathNodeSetCreate(NULL));
3763*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetSort(nodes1);
3764*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetSort(nodes2);
3765*7c568831SAndroid Build Coastguard Worker return(xmlXPathNodeTrailingSorted(nodes1,
3766*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetItem(nodes2, 0)));
3767*7c568831SAndroid Build Coastguard Worker }
3768*7c568831SAndroid Build Coastguard Worker
3769*7c568831SAndroid Build Coastguard Worker /************************************************************************
3770*7c568831SAndroid Build Coastguard Worker * *
3771*7c568831SAndroid Build Coastguard Worker * Routines to handle extra functions *
3772*7c568831SAndroid Build Coastguard Worker * *
3773*7c568831SAndroid Build Coastguard Worker ************************************************************************/
3774*7c568831SAndroid Build Coastguard Worker
3775*7c568831SAndroid Build Coastguard Worker /**
3776*7c568831SAndroid Build Coastguard Worker * xmlXPathRegisterFunc:
3777*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath context
3778*7c568831SAndroid Build Coastguard Worker * @name: the function name
3779*7c568831SAndroid Build Coastguard Worker * @f: the function implementation or NULL
3780*7c568831SAndroid Build Coastguard Worker *
3781*7c568831SAndroid Build Coastguard Worker * Register a new function. If @f is NULL it unregisters the function
3782*7c568831SAndroid Build Coastguard Worker *
3783*7c568831SAndroid Build Coastguard Worker * Returns 0 in case of success, -1 in case of error
3784*7c568831SAndroid Build Coastguard Worker */
3785*7c568831SAndroid Build Coastguard Worker int
xmlXPathRegisterFunc(xmlXPathContextPtr ctxt,const xmlChar * name,xmlXPathFunction f)3786*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(xmlXPathContextPtr ctxt, const xmlChar *name,
3787*7c568831SAndroid Build Coastguard Worker xmlXPathFunction f) {
3788*7c568831SAndroid Build Coastguard Worker return(xmlXPathRegisterFuncNS(ctxt, name, NULL, f));
3789*7c568831SAndroid Build Coastguard Worker }
3790*7c568831SAndroid Build Coastguard Worker
3791*7c568831SAndroid Build Coastguard Worker /**
3792*7c568831SAndroid Build Coastguard Worker * xmlXPathRegisterFuncNS:
3793*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath context
3794*7c568831SAndroid Build Coastguard Worker * @name: the function name
3795*7c568831SAndroid Build Coastguard Worker * @ns_uri: the function namespace URI
3796*7c568831SAndroid Build Coastguard Worker * @f: the function implementation or NULL
3797*7c568831SAndroid Build Coastguard Worker *
3798*7c568831SAndroid Build Coastguard Worker * Register a new function. If @f is NULL it unregisters the function
3799*7c568831SAndroid Build Coastguard Worker *
3800*7c568831SAndroid Build Coastguard Worker * Returns 0 in case of success, -1 in case of error
3801*7c568831SAndroid Build Coastguard Worker */
3802*7c568831SAndroid Build Coastguard Worker int
xmlXPathRegisterFuncNS(xmlXPathContextPtr ctxt,const xmlChar * name,const xmlChar * ns_uri,xmlXPathFunction f)3803*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFuncNS(xmlXPathContextPtr ctxt, const xmlChar *name,
3804*7c568831SAndroid Build Coastguard Worker const xmlChar *ns_uri, xmlXPathFunction f) {
3805*7c568831SAndroid Build Coastguard Worker int ret;
3806*7c568831SAndroid Build Coastguard Worker
3807*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
3808*7c568831SAndroid Build Coastguard Worker return(-1);
3809*7c568831SAndroid Build Coastguard Worker if (name == NULL)
3810*7c568831SAndroid Build Coastguard Worker return(-1);
3811*7c568831SAndroid Build Coastguard Worker
3812*7c568831SAndroid Build Coastguard Worker if (ctxt->funcHash == NULL)
3813*7c568831SAndroid Build Coastguard Worker ctxt->funcHash = xmlHashCreate(0);
3814*7c568831SAndroid Build Coastguard Worker if (ctxt->funcHash == NULL) {
3815*7c568831SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt);
3816*7c568831SAndroid Build Coastguard Worker return(-1);
3817*7c568831SAndroid Build Coastguard Worker }
3818*7c568831SAndroid Build Coastguard Worker if (f == NULL)
3819*7c568831SAndroid Build Coastguard Worker return(xmlHashRemoveEntry2(ctxt->funcHash, name, ns_uri, NULL));
3820*7c568831SAndroid Build Coastguard Worker XML_IGNORE_FPTR_CAST_WARNINGS
3821*7c568831SAndroid Build Coastguard Worker ret = xmlHashAddEntry2(ctxt->funcHash, name, ns_uri, (void *) f);
3822*7c568831SAndroid Build Coastguard Worker XML_POP_WARNINGS
3823*7c568831SAndroid Build Coastguard Worker if (ret < 0) {
3824*7c568831SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt);
3825*7c568831SAndroid Build Coastguard Worker return(-1);
3826*7c568831SAndroid Build Coastguard Worker }
3827*7c568831SAndroid Build Coastguard Worker
3828*7c568831SAndroid Build Coastguard Worker return(0);
3829*7c568831SAndroid Build Coastguard Worker }
3830*7c568831SAndroid Build Coastguard Worker
3831*7c568831SAndroid Build Coastguard Worker /**
3832*7c568831SAndroid Build Coastguard Worker * xmlXPathRegisterFuncLookup:
3833*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath context
3834*7c568831SAndroid Build Coastguard Worker * @f: the lookup function
3835*7c568831SAndroid Build Coastguard Worker * @funcCtxt: the lookup data
3836*7c568831SAndroid Build Coastguard Worker *
3837*7c568831SAndroid Build Coastguard Worker * Registers an external mechanism to do function lookup.
3838*7c568831SAndroid Build Coastguard Worker */
3839*7c568831SAndroid Build Coastguard Worker void
xmlXPathRegisterFuncLookup(xmlXPathContextPtr ctxt,xmlXPathFuncLookupFunc f,void * funcCtxt)3840*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFuncLookup (xmlXPathContextPtr ctxt,
3841*7c568831SAndroid Build Coastguard Worker xmlXPathFuncLookupFunc f,
3842*7c568831SAndroid Build Coastguard Worker void *funcCtxt) {
3843*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
3844*7c568831SAndroid Build Coastguard Worker return;
3845*7c568831SAndroid Build Coastguard Worker ctxt->funcLookupFunc = f;
3846*7c568831SAndroid Build Coastguard Worker ctxt->funcLookupData = funcCtxt;
3847*7c568831SAndroid Build Coastguard Worker }
3848*7c568831SAndroid Build Coastguard Worker
3849*7c568831SAndroid Build Coastguard Worker /**
3850*7c568831SAndroid Build Coastguard Worker * xmlXPathFunctionLookup:
3851*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath context
3852*7c568831SAndroid Build Coastguard Worker * @name: the function name
3853*7c568831SAndroid Build Coastguard Worker *
3854*7c568831SAndroid Build Coastguard Worker * Search in the Function array of the context for the given
3855*7c568831SAndroid Build Coastguard Worker * function.
3856*7c568831SAndroid Build Coastguard Worker *
3857*7c568831SAndroid Build Coastguard Worker * Returns the xmlXPathFunction or NULL if not found
3858*7c568831SAndroid Build Coastguard Worker */
3859*7c568831SAndroid Build Coastguard Worker xmlXPathFunction
xmlXPathFunctionLookup(xmlXPathContextPtr ctxt,const xmlChar * name)3860*7c568831SAndroid Build Coastguard Worker xmlXPathFunctionLookup(xmlXPathContextPtr ctxt, const xmlChar *name) {
3861*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
3862*7c568831SAndroid Build Coastguard Worker return (NULL);
3863*7c568831SAndroid Build Coastguard Worker
3864*7c568831SAndroid Build Coastguard Worker if (ctxt->funcLookupFunc != NULL) {
3865*7c568831SAndroid Build Coastguard Worker xmlXPathFunction ret;
3866*7c568831SAndroid Build Coastguard Worker xmlXPathFuncLookupFunc f;
3867*7c568831SAndroid Build Coastguard Worker
3868*7c568831SAndroid Build Coastguard Worker f = ctxt->funcLookupFunc;
3869*7c568831SAndroid Build Coastguard Worker ret = f(ctxt->funcLookupData, name, NULL);
3870*7c568831SAndroid Build Coastguard Worker if (ret != NULL)
3871*7c568831SAndroid Build Coastguard Worker return(ret);
3872*7c568831SAndroid Build Coastguard Worker }
3873*7c568831SAndroid Build Coastguard Worker return(xmlXPathFunctionLookupNS(ctxt, name, NULL));
3874*7c568831SAndroid Build Coastguard Worker }
3875*7c568831SAndroid Build Coastguard Worker
3876*7c568831SAndroid Build Coastguard Worker /**
3877*7c568831SAndroid Build Coastguard Worker * xmlXPathFunctionLookupNS:
3878*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath context
3879*7c568831SAndroid Build Coastguard Worker * @name: the function name
3880*7c568831SAndroid Build Coastguard Worker * @ns_uri: the function namespace URI
3881*7c568831SAndroid Build Coastguard Worker *
3882*7c568831SAndroid Build Coastguard Worker * Search in the Function array of the context for the given
3883*7c568831SAndroid Build Coastguard Worker * function.
3884*7c568831SAndroid Build Coastguard Worker *
3885*7c568831SAndroid Build Coastguard Worker * Returns the xmlXPathFunction or NULL if not found
3886*7c568831SAndroid Build Coastguard Worker */
3887*7c568831SAndroid Build Coastguard Worker xmlXPathFunction
xmlXPathFunctionLookupNS(xmlXPathContextPtr ctxt,const xmlChar * name,const xmlChar * ns_uri)3888*7c568831SAndroid Build Coastguard Worker xmlXPathFunctionLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name,
3889*7c568831SAndroid Build Coastguard Worker const xmlChar *ns_uri) {
3890*7c568831SAndroid Build Coastguard Worker xmlXPathFunction ret;
3891*7c568831SAndroid Build Coastguard Worker
3892*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
3893*7c568831SAndroid Build Coastguard Worker return(NULL);
3894*7c568831SAndroid Build Coastguard Worker if (name == NULL)
3895*7c568831SAndroid Build Coastguard Worker return(NULL);
3896*7c568831SAndroid Build Coastguard Worker
3897*7c568831SAndroid Build Coastguard Worker if (ctxt->funcLookupFunc != NULL) {
3898*7c568831SAndroid Build Coastguard Worker xmlXPathFuncLookupFunc f;
3899*7c568831SAndroid Build Coastguard Worker
3900*7c568831SAndroid Build Coastguard Worker f = ctxt->funcLookupFunc;
3901*7c568831SAndroid Build Coastguard Worker ret = f(ctxt->funcLookupData, name, ns_uri);
3902*7c568831SAndroid Build Coastguard Worker if (ret != NULL)
3903*7c568831SAndroid Build Coastguard Worker return(ret);
3904*7c568831SAndroid Build Coastguard Worker }
3905*7c568831SAndroid Build Coastguard Worker
3906*7c568831SAndroid Build Coastguard Worker if (ctxt->funcHash == NULL)
3907*7c568831SAndroid Build Coastguard Worker return(NULL);
3908*7c568831SAndroid Build Coastguard Worker
3909*7c568831SAndroid Build Coastguard Worker XML_IGNORE_FPTR_CAST_WARNINGS
3910*7c568831SAndroid Build Coastguard Worker ret = (xmlXPathFunction) xmlHashLookup2(ctxt->funcHash, name, ns_uri);
3911*7c568831SAndroid Build Coastguard Worker XML_POP_WARNINGS
3912*7c568831SAndroid Build Coastguard Worker return(ret);
3913*7c568831SAndroid Build Coastguard Worker }
3914*7c568831SAndroid Build Coastguard Worker
3915*7c568831SAndroid Build Coastguard Worker /**
3916*7c568831SAndroid Build Coastguard Worker * xmlXPathRegisteredFuncsCleanup:
3917*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath context
3918*7c568831SAndroid Build Coastguard Worker *
3919*7c568831SAndroid Build Coastguard Worker * Cleanup the XPath context data associated to registered functions
3920*7c568831SAndroid Build Coastguard Worker */
3921*7c568831SAndroid Build Coastguard Worker void
xmlXPathRegisteredFuncsCleanup(xmlXPathContextPtr ctxt)3922*7c568831SAndroid Build Coastguard Worker xmlXPathRegisteredFuncsCleanup(xmlXPathContextPtr ctxt) {
3923*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
3924*7c568831SAndroid Build Coastguard Worker return;
3925*7c568831SAndroid Build Coastguard Worker
3926*7c568831SAndroid Build Coastguard Worker xmlHashFree(ctxt->funcHash, NULL);
3927*7c568831SAndroid Build Coastguard Worker ctxt->funcHash = NULL;
3928*7c568831SAndroid Build Coastguard Worker }
3929*7c568831SAndroid Build Coastguard Worker
3930*7c568831SAndroid Build Coastguard Worker /************************************************************************
3931*7c568831SAndroid Build Coastguard Worker * *
3932*7c568831SAndroid Build Coastguard Worker * Routines to handle Variables *
3933*7c568831SAndroid Build Coastguard Worker * *
3934*7c568831SAndroid Build Coastguard Worker ************************************************************************/
3935*7c568831SAndroid Build Coastguard Worker
3936*7c568831SAndroid Build Coastguard Worker /**
3937*7c568831SAndroid Build Coastguard Worker * xmlXPathRegisterVariable:
3938*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath context
3939*7c568831SAndroid Build Coastguard Worker * @name: the variable name
3940*7c568831SAndroid Build Coastguard Worker * @value: the variable value or NULL
3941*7c568831SAndroid Build Coastguard Worker *
3942*7c568831SAndroid Build Coastguard Worker * Register a new variable value. If @value is NULL it unregisters
3943*7c568831SAndroid Build Coastguard Worker * the variable
3944*7c568831SAndroid Build Coastguard Worker *
3945*7c568831SAndroid Build Coastguard Worker * Returns 0 in case of success, -1 in case of error
3946*7c568831SAndroid Build Coastguard Worker */
3947*7c568831SAndroid Build Coastguard Worker int
xmlXPathRegisterVariable(xmlXPathContextPtr ctxt,const xmlChar * name,xmlXPathObjectPtr value)3948*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterVariable(xmlXPathContextPtr ctxt, const xmlChar *name,
3949*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr value) {
3950*7c568831SAndroid Build Coastguard Worker return(xmlXPathRegisterVariableNS(ctxt, name, NULL, value));
3951*7c568831SAndroid Build Coastguard Worker }
3952*7c568831SAndroid Build Coastguard Worker
3953*7c568831SAndroid Build Coastguard Worker /**
3954*7c568831SAndroid Build Coastguard Worker * xmlXPathRegisterVariableNS:
3955*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath context
3956*7c568831SAndroid Build Coastguard Worker * @name: the variable name
3957*7c568831SAndroid Build Coastguard Worker * @ns_uri: the variable namespace URI
3958*7c568831SAndroid Build Coastguard Worker * @value: the variable value or NULL
3959*7c568831SAndroid Build Coastguard Worker *
3960*7c568831SAndroid Build Coastguard Worker * Register a new variable value. If @value is NULL it unregisters
3961*7c568831SAndroid Build Coastguard Worker * the variable
3962*7c568831SAndroid Build Coastguard Worker *
3963*7c568831SAndroid Build Coastguard Worker * Returns 0 in case of success, -1 in case of error
3964*7c568831SAndroid Build Coastguard Worker */
3965*7c568831SAndroid Build Coastguard Worker int
xmlXPathRegisterVariableNS(xmlXPathContextPtr ctxt,const xmlChar * name,const xmlChar * ns_uri,xmlXPathObjectPtr value)3966*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterVariableNS(xmlXPathContextPtr ctxt, const xmlChar *name,
3967*7c568831SAndroid Build Coastguard Worker const xmlChar *ns_uri,
3968*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr value) {
3969*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
3970*7c568831SAndroid Build Coastguard Worker return(-1);
3971*7c568831SAndroid Build Coastguard Worker if (name == NULL)
3972*7c568831SAndroid Build Coastguard Worker return(-1);
3973*7c568831SAndroid Build Coastguard Worker
3974*7c568831SAndroid Build Coastguard Worker if (ctxt->varHash == NULL)
3975*7c568831SAndroid Build Coastguard Worker ctxt->varHash = xmlHashCreate(0);
3976*7c568831SAndroid Build Coastguard Worker if (ctxt->varHash == NULL)
3977*7c568831SAndroid Build Coastguard Worker return(-1);
3978*7c568831SAndroid Build Coastguard Worker if (value == NULL)
3979*7c568831SAndroid Build Coastguard Worker return(xmlHashRemoveEntry2(ctxt->varHash, name, ns_uri,
3980*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObjectEntry));
3981*7c568831SAndroid Build Coastguard Worker return(xmlHashUpdateEntry2(ctxt->varHash, name, ns_uri,
3982*7c568831SAndroid Build Coastguard Worker (void *) value, xmlXPathFreeObjectEntry));
3983*7c568831SAndroid Build Coastguard Worker }
3984*7c568831SAndroid Build Coastguard Worker
3985*7c568831SAndroid Build Coastguard Worker /**
3986*7c568831SAndroid Build Coastguard Worker * xmlXPathRegisterVariableLookup:
3987*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath context
3988*7c568831SAndroid Build Coastguard Worker * @f: the lookup function
3989*7c568831SAndroid Build Coastguard Worker * @data: the lookup data
3990*7c568831SAndroid Build Coastguard Worker *
3991*7c568831SAndroid Build Coastguard Worker * register an external mechanism to do variable lookup
3992*7c568831SAndroid Build Coastguard Worker */
3993*7c568831SAndroid Build Coastguard Worker void
xmlXPathRegisterVariableLookup(xmlXPathContextPtr ctxt,xmlXPathVariableLookupFunc f,void * data)3994*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterVariableLookup(xmlXPathContextPtr ctxt,
3995*7c568831SAndroid Build Coastguard Worker xmlXPathVariableLookupFunc f, void *data) {
3996*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
3997*7c568831SAndroid Build Coastguard Worker return;
3998*7c568831SAndroid Build Coastguard Worker ctxt->varLookupFunc = f;
3999*7c568831SAndroid Build Coastguard Worker ctxt->varLookupData = data;
4000*7c568831SAndroid Build Coastguard Worker }
4001*7c568831SAndroid Build Coastguard Worker
4002*7c568831SAndroid Build Coastguard Worker /**
4003*7c568831SAndroid Build Coastguard Worker * xmlXPathVariableLookup:
4004*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath context
4005*7c568831SAndroid Build Coastguard Worker * @name: the variable name
4006*7c568831SAndroid Build Coastguard Worker *
4007*7c568831SAndroid Build Coastguard Worker * Search in the Variable array of the context for the given
4008*7c568831SAndroid Build Coastguard Worker * variable value.
4009*7c568831SAndroid Build Coastguard Worker *
4010*7c568831SAndroid Build Coastguard Worker * Returns a copy of the value or NULL if not found
4011*7c568831SAndroid Build Coastguard Worker */
4012*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathVariableLookup(xmlXPathContextPtr ctxt,const xmlChar * name)4013*7c568831SAndroid Build Coastguard Worker xmlXPathVariableLookup(xmlXPathContextPtr ctxt, const xmlChar *name) {
4014*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
4015*7c568831SAndroid Build Coastguard Worker return(NULL);
4016*7c568831SAndroid Build Coastguard Worker
4017*7c568831SAndroid Build Coastguard Worker if (ctxt->varLookupFunc != NULL) {
4018*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
4019*7c568831SAndroid Build Coastguard Worker
4020*7c568831SAndroid Build Coastguard Worker ret = ((xmlXPathVariableLookupFunc)ctxt->varLookupFunc)
4021*7c568831SAndroid Build Coastguard Worker (ctxt->varLookupData, name, NULL);
4022*7c568831SAndroid Build Coastguard Worker return(ret);
4023*7c568831SAndroid Build Coastguard Worker }
4024*7c568831SAndroid Build Coastguard Worker return(xmlXPathVariableLookupNS(ctxt, name, NULL));
4025*7c568831SAndroid Build Coastguard Worker }
4026*7c568831SAndroid Build Coastguard Worker
4027*7c568831SAndroid Build Coastguard Worker /**
4028*7c568831SAndroid Build Coastguard Worker * xmlXPathVariableLookupNS:
4029*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath context
4030*7c568831SAndroid Build Coastguard Worker * @name: the variable name
4031*7c568831SAndroid Build Coastguard Worker * @ns_uri: the variable namespace URI
4032*7c568831SAndroid Build Coastguard Worker *
4033*7c568831SAndroid Build Coastguard Worker * Search in the Variable array of the context for the given
4034*7c568831SAndroid Build Coastguard Worker * variable value.
4035*7c568831SAndroid Build Coastguard Worker *
4036*7c568831SAndroid Build Coastguard Worker * Returns the a copy of the value or NULL if not found
4037*7c568831SAndroid Build Coastguard Worker */
4038*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathVariableLookupNS(xmlXPathContextPtr ctxt,const xmlChar * name,const xmlChar * ns_uri)4039*7c568831SAndroid Build Coastguard Worker xmlXPathVariableLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name,
4040*7c568831SAndroid Build Coastguard Worker const xmlChar *ns_uri) {
4041*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
4042*7c568831SAndroid Build Coastguard Worker return(NULL);
4043*7c568831SAndroid Build Coastguard Worker
4044*7c568831SAndroid Build Coastguard Worker if (ctxt->varLookupFunc != NULL) {
4045*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
4046*7c568831SAndroid Build Coastguard Worker
4047*7c568831SAndroid Build Coastguard Worker ret = ((xmlXPathVariableLookupFunc)ctxt->varLookupFunc)
4048*7c568831SAndroid Build Coastguard Worker (ctxt->varLookupData, name, ns_uri);
4049*7c568831SAndroid Build Coastguard Worker if (ret != NULL) return(ret);
4050*7c568831SAndroid Build Coastguard Worker }
4051*7c568831SAndroid Build Coastguard Worker
4052*7c568831SAndroid Build Coastguard Worker if (ctxt->varHash == NULL)
4053*7c568831SAndroid Build Coastguard Worker return(NULL);
4054*7c568831SAndroid Build Coastguard Worker if (name == NULL)
4055*7c568831SAndroid Build Coastguard Worker return(NULL);
4056*7c568831SAndroid Build Coastguard Worker
4057*7c568831SAndroid Build Coastguard Worker return(xmlXPathObjectCopy(xmlHashLookup2(ctxt->varHash, name, ns_uri)));
4058*7c568831SAndroid Build Coastguard Worker }
4059*7c568831SAndroid Build Coastguard Worker
4060*7c568831SAndroid Build Coastguard Worker /**
4061*7c568831SAndroid Build Coastguard Worker * xmlXPathRegisteredVariablesCleanup:
4062*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath context
4063*7c568831SAndroid Build Coastguard Worker *
4064*7c568831SAndroid Build Coastguard Worker * Cleanup the XPath context data associated to registered variables
4065*7c568831SAndroid Build Coastguard Worker */
4066*7c568831SAndroid Build Coastguard Worker void
xmlXPathRegisteredVariablesCleanup(xmlXPathContextPtr ctxt)4067*7c568831SAndroid Build Coastguard Worker xmlXPathRegisteredVariablesCleanup(xmlXPathContextPtr ctxt) {
4068*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
4069*7c568831SAndroid Build Coastguard Worker return;
4070*7c568831SAndroid Build Coastguard Worker
4071*7c568831SAndroid Build Coastguard Worker xmlHashFree(ctxt->varHash, xmlXPathFreeObjectEntry);
4072*7c568831SAndroid Build Coastguard Worker ctxt->varHash = NULL;
4073*7c568831SAndroid Build Coastguard Worker }
4074*7c568831SAndroid Build Coastguard Worker
4075*7c568831SAndroid Build Coastguard Worker /**
4076*7c568831SAndroid Build Coastguard Worker * xmlXPathRegisterNs:
4077*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath context
4078*7c568831SAndroid Build Coastguard Worker * @prefix: the namespace prefix cannot be NULL or empty string
4079*7c568831SAndroid Build Coastguard Worker * @ns_uri: the namespace name
4080*7c568831SAndroid Build Coastguard Worker *
4081*7c568831SAndroid Build Coastguard Worker * Register a new namespace. If @ns_uri is NULL it unregisters
4082*7c568831SAndroid Build Coastguard Worker * the namespace
4083*7c568831SAndroid Build Coastguard Worker *
4084*7c568831SAndroid Build Coastguard Worker * Returns 0 in case of success, -1 in case of error
4085*7c568831SAndroid Build Coastguard Worker */
4086*7c568831SAndroid Build Coastguard Worker int
xmlXPathRegisterNs(xmlXPathContextPtr ctxt,const xmlChar * prefix,const xmlChar * ns_uri)4087*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterNs(xmlXPathContextPtr ctxt, const xmlChar *prefix,
4088*7c568831SAndroid Build Coastguard Worker const xmlChar *ns_uri) {
4089*7c568831SAndroid Build Coastguard Worker xmlChar *copy;
4090*7c568831SAndroid Build Coastguard Worker
4091*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
4092*7c568831SAndroid Build Coastguard Worker return(-1);
4093*7c568831SAndroid Build Coastguard Worker if (prefix == NULL)
4094*7c568831SAndroid Build Coastguard Worker return(-1);
4095*7c568831SAndroid Build Coastguard Worker if (prefix[0] == 0)
4096*7c568831SAndroid Build Coastguard Worker return(-1);
4097*7c568831SAndroid Build Coastguard Worker
4098*7c568831SAndroid Build Coastguard Worker if (ctxt->nsHash == NULL)
4099*7c568831SAndroid Build Coastguard Worker ctxt->nsHash = xmlHashCreate(10);
4100*7c568831SAndroid Build Coastguard Worker if (ctxt->nsHash == NULL) {
4101*7c568831SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt);
4102*7c568831SAndroid Build Coastguard Worker return(-1);
4103*7c568831SAndroid Build Coastguard Worker }
4104*7c568831SAndroid Build Coastguard Worker if (ns_uri == NULL)
4105*7c568831SAndroid Build Coastguard Worker return(xmlHashRemoveEntry(ctxt->nsHash, prefix,
4106*7c568831SAndroid Build Coastguard Worker xmlHashDefaultDeallocator));
4107*7c568831SAndroid Build Coastguard Worker
4108*7c568831SAndroid Build Coastguard Worker copy = xmlStrdup(ns_uri);
4109*7c568831SAndroid Build Coastguard Worker if (copy == NULL) {
4110*7c568831SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt);
4111*7c568831SAndroid Build Coastguard Worker return(-1);
4112*7c568831SAndroid Build Coastguard Worker }
4113*7c568831SAndroid Build Coastguard Worker if (xmlHashUpdateEntry(ctxt->nsHash, prefix, copy,
4114*7c568831SAndroid Build Coastguard Worker xmlHashDefaultDeallocator) < 0) {
4115*7c568831SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt);
4116*7c568831SAndroid Build Coastguard Worker xmlFree(copy);
4117*7c568831SAndroid Build Coastguard Worker return(-1);
4118*7c568831SAndroid Build Coastguard Worker }
4119*7c568831SAndroid Build Coastguard Worker
4120*7c568831SAndroid Build Coastguard Worker return(0);
4121*7c568831SAndroid Build Coastguard Worker }
4122*7c568831SAndroid Build Coastguard Worker
4123*7c568831SAndroid Build Coastguard Worker /**
4124*7c568831SAndroid Build Coastguard Worker * xmlXPathNsLookup:
4125*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath context
4126*7c568831SAndroid Build Coastguard Worker * @prefix: the namespace prefix value
4127*7c568831SAndroid Build Coastguard Worker *
4128*7c568831SAndroid Build Coastguard Worker * Search in the namespace declaration array of the context for the given
4129*7c568831SAndroid Build Coastguard Worker * namespace name associated to the given prefix
4130*7c568831SAndroid Build Coastguard Worker *
4131*7c568831SAndroid Build Coastguard Worker * Returns the value or NULL if not found
4132*7c568831SAndroid Build Coastguard Worker */
4133*7c568831SAndroid Build Coastguard Worker const xmlChar *
xmlXPathNsLookup(xmlXPathContextPtr ctxt,const xmlChar * prefix)4134*7c568831SAndroid Build Coastguard Worker xmlXPathNsLookup(xmlXPathContextPtr ctxt, const xmlChar *prefix) {
4135*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
4136*7c568831SAndroid Build Coastguard Worker return(NULL);
4137*7c568831SAndroid Build Coastguard Worker if (prefix == NULL)
4138*7c568831SAndroid Build Coastguard Worker return(NULL);
4139*7c568831SAndroid Build Coastguard Worker
4140*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(prefix, (const xmlChar *) "xml"))
4141*7c568831SAndroid Build Coastguard Worker return(XML_XML_NAMESPACE);
4142*7c568831SAndroid Build Coastguard Worker
4143*7c568831SAndroid Build Coastguard Worker if (ctxt->namespaces != NULL) {
4144*7c568831SAndroid Build Coastguard Worker int i;
4145*7c568831SAndroid Build Coastguard Worker
4146*7c568831SAndroid Build Coastguard Worker for (i = 0;i < ctxt->nsNr;i++) {
4147*7c568831SAndroid Build Coastguard Worker if ((ctxt->namespaces[i] != NULL) &&
4148*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(ctxt->namespaces[i]->prefix, prefix)))
4149*7c568831SAndroid Build Coastguard Worker return(ctxt->namespaces[i]->href);
4150*7c568831SAndroid Build Coastguard Worker }
4151*7c568831SAndroid Build Coastguard Worker }
4152*7c568831SAndroid Build Coastguard Worker
4153*7c568831SAndroid Build Coastguard Worker return((const xmlChar *) xmlHashLookup(ctxt->nsHash, prefix));
4154*7c568831SAndroid Build Coastguard Worker }
4155*7c568831SAndroid Build Coastguard Worker
4156*7c568831SAndroid Build Coastguard Worker /**
4157*7c568831SAndroid Build Coastguard Worker * xmlXPathRegisteredNsCleanup:
4158*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath context
4159*7c568831SAndroid Build Coastguard Worker *
4160*7c568831SAndroid Build Coastguard Worker * Cleanup the XPath context data associated to registered variables
4161*7c568831SAndroid Build Coastguard Worker */
4162*7c568831SAndroid Build Coastguard Worker void
xmlXPathRegisteredNsCleanup(xmlXPathContextPtr ctxt)4163*7c568831SAndroid Build Coastguard Worker xmlXPathRegisteredNsCleanup(xmlXPathContextPtr ctxt) {
4164*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
4165*7c568831SAndroid Build Coastguard Worker return;
4166*7c568831SAndroid Build Coastguard Worker
4167*7c568831SAndroid Build Coastguard Worker xmlHashFree(ctxt->nsHash, xmlHashDefaultDeallocator);
4168*7c568831SAndroid Build Coastguard Worker ctxt->nsHash = NULL;
4169*7c568831SAndroid Build Coastguard Worker }
4170*7c568831SAndroid Build Coastguard Worker
4171*7c568831SAndroid Build Coastguard Worker /************************************************************************
4172*7c568831SAndroid Build Coastguard Worker * *
4173*7c568831SAndroid Build Coastguard Worker * Routines to handle Values *
4174*7c568831SAndroid Build Coastguard Worker * *
4175*7c568831SAndroid Build Coastguard Worker ************************************************************************/
4176*7c568831SAndroid Build Coastguard Worker
4177*7c568831SAndroid Build Coastguard Worker /* Allocations are terrible, one needs to optimize all this !!! */
4178*7c568831SAndroid Build Coastguard Worker
4179*7c568831SAndroid Build Coastguard Worker /**
4180*7c568831SAndroid Build Coastguard Worker * xmlXPathNewFloat:
4181*7c568831SAndroid Build Coastguard Worker * @val: the double value
4182*7c568831SAndroid Build Coastguard Worker *
4183*7c568831SAndroid Build Coastguard Worker * Create a new xmlXPathObjectPtr of type double and of value @val
4184*7c568831SAndroid Build Coastguard Worker *
4185*7c568831SAndroid Build Coastguard Worker * Returns the newly created object.
4186*7c568831SAndroid Build Coastguard Worker */
4187*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathNewFloat(double val)4188*7c568831SAndroid Build Coastguard Worker xmlXPathNewFloat(double val) {
4189*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
4190*7c568831SAndroid Build Coastguard Worker
4191*7c568831SAndroid Build Coastguard Worker ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
4192*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
4193*7c568831SAndroid Build Coastguard Worker return(NULL);
4194*7c568831SAndroid Build Coastguard Worker memset(ret, 0 , sizeof(xmlXPathObject));
4195*7c568831SAndroid Build Coastguard Worker ret->type = XPATH_NUMBER;
4196*7c568831SAndroid Build Coastguard Worker ret->floatval = val;
4197*7c568831SAndroid Build Coastguard Worker return(ret);
4198*7c568831SAndroid Build Coastguard Worker }
4199*7c568831SAndroid Build Coastguard Worker
4200*7c568831SAndroid Build Coastguard Worker /**
4201*7c568831SAndroid Build Coastguard Worker * xmlXPathNewBoolean:
4202*7c568831SAndroid Build Coastguard Worker * @val: the boolean value
4203*7c568831SAndroid Build Coastguard Worker *
4204*7c568831SAndroid Build Coastguard Worker * Create a new xmlXPathObjectPtr of type boolean and of value @val
4205*7c568831SAndroid Build Coastguard Worker *
4206*7c568831SAndroid Build Coastguard Worker * Returns the newly created object.
4207*7c568831SAndroid Build Coastguard Worker */
4208*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathNewBoolean(int val)4209*7c568831SAndroid Build Coastguard Worker xmlXPathNewBoolean(int val) {
4210*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
4211*7c568831SAndroid Build Coastguard Worker
4212*7c568831SAndroid Build Coastguard Worker ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
4213*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
4214*7c568831SAndroid Build Coastguard Worker return(NULL);
4215*7c568831SAndroid Build Coastguard Worker memset(ret, 0 , sizeof(xmlXPathObject));
4216*7c568831SAndroid Build Coastguard Worker ret->type = XPATH_BOOLEAN;
4217*7c568831SAndroid Build Coastguard Worker ret->boolval = (val != 0);
4218*7c568831SAndroid Build Coastguard Worker return(ret);
4219*7c568831SAndroid Build Coastguard Worker }
4220*7c568831SAndroid Build Coastguard Worker
4221*7c568831SAndroid Build Coastguard Worker /**
4222*7c568831SAndroid Build Coastguard Worker * xmlXPathNewString:
4223*7c568831SAndroid Build Coastguard Worker * @val: the xmlChar * value
4224*7c568831SAndroid Build Coastguard Worker *
4225*7c568831SAndroid Build Coastguard Worker * Create a new xmlXPathObjectPtr of type string and of value @val
4226*7c568831SAndroid Build Coastguard Worker *
4227*7c568831SAndroid Build Coastguard Worker * Returns the newly created object.
4228*7c568831SAndroid Build Coastguard Worker */
4229*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathNewString(const xmlChar * val)4230*7c568831SAndroid Build Coastguard Worker xmlXPathNewString(const xmlChar *val) {
4231*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
4232*7c568831SAndroid Build Coastguard Worker
4233*7c568831SAndroid Build Coastguard Worker ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
4234*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
4235*7c568831SAndroid Build Coastguard Worker return(NULL);
4236*7c568831SAndroid Build Coastguard Worker memset(ret, 0 , sizeof(xmlXPathObject));
4237*7c568831SAndroid Build Coastguard Worker ret->type = XPATH_STRING;
4238*7c568831SAndroid Build Coastguard Worker if (val == NULL)
4239*7c568831SAndroid Build Coastguard Worker val = BAD_CAST "";
4240*7c568831SAndroid Build Coastguard Worker ret->stringval = xmlStrdup(val);
4241*7c568831SAndroid Build Coastguard Worker if (ret->stringval == NULL) {
4242*7c568831SAndroid Build Coastguard Worker xmlFree(ret);
4243*7c568831SAndroid Build Coastguard Worker return(NULL);
4244*7c568831SAndroid Build Coastguard Worker }
4245*7c568831SAndroid Build Coastguard Worker return(ret);
4246*7c568831SAndroid Build Coastguard Worker }
4247*7c568831SAndroid Build Coastguard Worker
4248*7c568831SAndroid Build Coastguard Worker /**
4249*7c568831SAndroid Build Coastguard Worker * xmlXPathWrapString:
4250*7c568831SAndroid Build Coastguard Worker * @val: the xmlChar * value
4251*7c568831SAndroid Build Coastguard Worker *
4252*7c568831SAndroid Build Coastguard Worker * Wraps the @val string into an XPath object.
4253*7c568831SAndroid Build Coastguard Worker *
4254*7c568831SAndroid Build Coastguard Worker * Returns the newly created object.
4255*7c568831SAndroid Build Coastguard Worker *
4256*7c568831SAndroid Build Coastguard Worker * Frees @val in case of error.
4257*7c568831SAndroid Build Coastguard Worker */
4258*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathWrapString(xmlChar * val)4259*7c568831SAndroid Build Coastguard Worker xmlXPathWrapString (xmlChar *val) {
4260*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
4261*7c568831SAndroid Build Coastguard Worker
4262*7c568831SAndroid Build Coastguard Worker ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
4263*7c568831SAndroid Build Coastguard Worker if (ret == NULL) {
4264*7c568831SAndroid Build Coastguard Worker xmlFree(val);
4265*7c568831SAndroid Build Coastguard Worker return(NULL);
4266*7c568831SAndroid Build Coastguard Worker }
4267*7c568831SAndroid Build Coastguard Worker memset(ret, 0 , sizeof(xmlXPathObject));
4268*7c568831SAndroid Build Coastguard Worker ret->type = XPATH_STRING;
4269*7c568831SAndroid Build Coastguard Worker ret->stringval = val;
4270*7c568831SAndroid Build Coastguard Worker return(ret);
4271*7c568831SAndroid Build Coastguard Worker }
4272*7c568831SAndroid Build Coastguard Worker
4273*7c568831SAndroid Build Coastguard Worker /**
4274*7c568831SAndroid Build Coastguard Worker * xmlXPathNewCString:
4275*7c568831SAndroid Build Coastguard Worker * @val: the char * value
4276*7c568831SAndroid Build Coastguard Worker *
4277*7c568831SAndroid Build Coastguard Worker * Create a new xmlXPathObjectPtr of type string and of value @val
4278*7c568831SAndroid Build Coastguard Worker *
4279*7c568831SAndroid Build Coastguard Worker * Returns the newly created object.
4280*7c568831SAndroid Build Coastguard Worker */
4281*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathNewCString(const char * val)4282*7c568831SAndroid Build Coastguard Worker xmlXPathNewCString(const char *val) {
4283*7c568831SAndroid Build Coastguard Worker return(xmlXPathNewString(BAD_CAST val));
4284*7c568831SAndroid Build Coastguard Worker }
4285*7c568831SAndroid Build Coastguard Worker
4286*7c568831SAndroid Build Coastguard Worker /**
4287*7c568831SAndroid Build Coastguard Worker * xmlXPathWrapCString:
4288*7c568831SAndroid Build Coastguard Worker * @val: the char * value
4289*7c568831SAndroid Build Coastguard Worker *
4290*7c568831SAndroid Build Coastguard Worker * Wraps a string into an XPath object.
4291*7c568831SAndroid Build Coastguard Worker *
4292*7c568831SAndroid Build Coastguard Worker * Returns the newly created object.
4293*7c568831SAndroid Build Coastguard Worker */
4294*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathWrapCString(char * val)4295*7c568831SAndroid Build Coastguard Worker xmlXPathWrapCString (char * val) {
4296*7c568831SAndroid Build Coastguard Worker return(xmlXPathWrapString((xmlChar *)(val)));
4297*7c568831SAndroid Build Coastguard Worker }
4298*7c568831SAndroid Build Coastguard Worker
4299*7c568831SAndroid Build Coastguard Worker /**
4300*7c568831SAndroid Build Coastguard Worker * xmlXPathWrapExternal:
4301*7c568831SAndroid Build Coastguard Worker * @val: the user data
4302*7c568831SAndroid Build Coastguard Worker *
4303*7c568831SAndroid Build Coastguard Worker * Wraps the @val data into an XPath object.
4304*7c568831SAndroid Build Coastguard Worker *
4305*7c568831SAndroid Build Coastguard Worker * Returns the newly created object.
4306*7c568831SAndroid Build Coastguard Worker */
4307*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathWrapExternal(void * val)4308*7c568831SAndroid Build Coastguard Worker xmlXPathWrapExternal (void *val) {
4309*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
4310*7c568831SAndroid Build Coastguard Worker
4311*7c568831SAndroid Build Coastguard Worker ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
4312*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
4313*7c568831SAndroid Build Coastguard Worker return(NULL);
4314*7c568831SAndroid Build Coastguard Worker memset(ret, 0 , sizeof(xmlXPathObject));
4315*7c568831SAndroid Build Coastguard Worker ret->type = XPATH_USERS;
4316*7c568831SAndroid Build Coastguard Worker ret->user = val;
4317*7c568831SAndroid Build Coastguard Worker return(ret);
4318*7c568831SAndroid Build Coastguard Worker }
4319*7c568831SAndroid Build Coastguard Worker
4320*7c568831SAndroid Build Coastguard Worker /**
4321*7c568831SAndroid Build Coastguard Worker * xmlXPathObjectCopy:
4322*7c568831SAndroid Build Coastguard Worker * @val: the original object
4323*7c568831SAndroid Build Coastguard Worker *
4324*7c568831SAndroid Build Coastguard Worker * allocate a new copy of a given object
4325*7c568831SAndroid Build Coastguard Worker *
4326*7c568831SAndroid Build Coastguard Worker * Returns the newly created object.
4327*7c568831SAndroid Build Coastguard Worker */
4328*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathObjectCopy(xmlXPathObjectPtr val)4329*7c568831SAndroid Build Coastguard Worker xmlXPathObjectCopy(xmlXPathObjectPtr val) {
4330*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
4331*7c568831SAndroid Build Coastguard Worker
4332*7c568831SAndroid Build Coastguard Worker if (val == NULL)
4333*7c568831SAndroid Build Coastguard Worker return(NULL);
4334*7c568831SAndroid Build Coastguard Worker
4335*7c568831SAndroid Build Coastguard Worker ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
4336*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
4337*7c568831SAndroid Build Coastguard Worker return(NULL);
4338*7c568831SAndroid Build Coastguard Worker memcpy(ret, val , sizeof(xmlXPathObject));
4339*7c568831SAndroid Build Coastguard Worker switch (val->type) {
4340*7c568831SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
4341*7c568831SAndroid Build Coastguard Worker case XPATH_NUMBER:
4342*7c568831SAndroid Build Coastguard Worker break;
4343*7c568831SAndroid Build Coastguard Worker case XPATH_STRING:
4344*7c568831SAndroid Build Coastguard Worker ret->stringval = xmlStrdup(val->stringval);
4345*7c568831SAndroid Build Coastguard Worker if (ret->stringval == NULL) {
4346*7c568831SAndroid Build Coastguard Worker xmlFree(ret);
4347*7c568831SAndroid Build Coastguard Worker return(NULL);
4348*7c568831SAndroid Build Coastguard Worker }
4349*7c568831SAndroid Build Coastguard Worker break;
4350*7c568831SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
4351*7c568831SAndroid Build Coastguard Worker case XPATH_NODESET:
4352*7c568831SAndroid Build Coastguard Worker ret->nodesetval = xmlXPathNodeSetMerge(NULL, val->nodesetval);
4353*7c568831SAndroid Build Coastguard Worker if (ret->nodesetval == NULL) {
4354*7c568831SAndroid Build Coastguard Worker xmlFree(ret);
4355*7c568831SAndroid Build Coastguard Worker return(NULL);
4356*7c568831SAndroid Build Coastguard Worker }
4357*7c568831SAndroid Build Coastguard Worker /* Do not deallocate the copied tree value */
4358*7c568831SAndroid Build Coastguard Worker ret->boolval = 0;
4359*7c568831SAndroid Build Coastguard Worker break;
4360*7c568831SAndroid Build Coastguard Worker case XPATH_USERS:
4361*7c568831SAndroid Build Coastguard Worker ret->user = val->user;
4362*7c568831SAndroid Build Coastguard Worker break;
4363*7c568831SAndroid Build Coastguard Worker default:
4364*7c568831SAndroid Build Coastguard Worker xmlFree(ret);
4365*7c568831SAndroid Build Coastguard Worker ret = NULL;
4366*7c568831SAndroid Build Coastguard Worker break;
4367*7c568831SAndroid Build Coastguard Worker }
4368*7c568831SAndroid Build Coastguard Worker return(ret);
4369*7c568831SAndroid Build Coastguard Worker }
4370*7c568831SAndroid Build Coastguard Worker
4371*7c568831SAndroid Build Coastguard Worker /**
4372*7c568831SAndroid Build Coastguard Worker * xmlXPathFreeObject:
4373*7c568831SAndroid Build Coastguard Worker * @obj: the object to free
4374*7c568831SAndroid Build Coastguard Worker *
4375*7c568831SAndroid Build Coastguard Worker * Free up an xmlXPathObjectPtr object.
4376*7c568831SAndroid Build Coastguard Worker */
4377*7c568831SAndroid Build Coastguard Worker void
xmlXPathFreeObject(xmlXPathObjectPtr obj)4378*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(xmlXPathObjectPtr obj) {
4379*7c568831SAndroid Build Coastguard Worker if (obj == NULL) return;
4380*7c568831SAndroid Build Coastguard Worker if ((obj->type == XPATH_NODESET) || (obj->type == XPATH_XSLT_TREE)) {
4381*7c568831SAndroid Build Coastguard Worker if (obj->nodesetval != NULL)
4382*7c568831SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(obj->nodesetval);
4383*7c568831SAndroid Build Coastguard Worker } else if (obj->type == XPATH_STRING) {
4384*7c568831SAndroid Build Coastguard Worker if (obj->stringval != NULL)
4385*7c568831SAndroid Build Coastguard Worker xmlFree(obj->stringval);
4386*7c568831SAndroid Build Coastguard Worker }
4387*7c568831SAndroid Build Coastguard Worker xmlFree(obj);
4388*7c568831SAndroid Build Coastguard Worker }
4389*7c568831SAndroid Build Coastguard Worker
4390*7c568831SAndroid Build Coastguard Worker static void
xmlXPathFreeObjectEntry(void * obj,const xmlChar * name ATTRIBUTE_UNUSED)4391*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObjectEntry(void *obj, const xmlChar *name ATTRIBUTE_UNUSED) {
4392*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject((xmlXPathObjectPtr) obj);
4393*7c568831SAndroid Build Coastguard Worker }
4394*7c568831SAndroid Build Coastguard Worker
4395*7c568831SAndroid Build Coastguard Worker /**
4396*7c568831SAndroid Build Coastguard Worker * xmlXPathReleaseObject:
4397*7c568831SAndroid Build Coastguard Worker * @obj: the xmlXPathObjectPtr to free or to cache
4398*7c568831SAndroid Build Coastguard Worker *
4399*7c568831SAndroid Build Coastguard Worker * Depending on the state of the cache this frees the given
4400*7c568831SAndroid Build Coastguard Worker * XPath object or stores it in the cache.
4401*7c568831SAndroid Build Coastguard Worker */
4402*7c568831SAndroid Build Coastguard Worker static void
xmlXPathReleaseObject(xmlXPathContextPtr ctxt,xmlXPathObjectPtr obj)4403*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj)
4404*7c568831SAndroid Build Coastguard Worker {
4405*7c568831SAndroid Build Coastguard Worker if (obj == NULL)
4406*7c568831SAndroid Build Coastguard Worker return;
4407*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->cache == NULL)) {
4408*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(obj);
4409*7c568831SAndroid Build Coastguard Worker } else {
4410*7c568831SAndroid Build Coastguard Worker xmlXPathContextCachePtr cache =
4411*7c568831SAndroid Build Coastguard Worker (xmlXPathContextCachePtr) ctxt->cache;
4412*7c568831SAndroid Build Coastguard Worker
4413*7c568831SAndroid Build Coastguard Worker switch (obj->type) {
4414*7c568831SAndroid Build Coastguard Worker case XPATH_NODESET:
4415*7c568831SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
4416*7c568831SAndroid Build Coastguard Worker if (obj->nodesetval != NULL) {
4417*7c568831SAndroid Build Coastguard Worker if ((obj->nodesetval->nodeMax <= 40) &&
4418*7c568831SAndroid Build Coastguard Worker (cache->numNodeset < cache->maxNodeset)) {
4419*7c568831SAndroid Build Coastguard Worker obj->stringval = (void *) cache->nodesetObjs;
4420*7c568831SAndroid Build Coastguard Worker cache->nodesetObjs = obj;
4421*7c568831SAndroid Build Coastguard Worker cache->numNodeset += 1;
4422*7c568831SAndroid Build Coastguard Worker goto obj_cached;
4423*7c568831SAndroid Build Coastguard Worker } else {
4424*7c568831SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(obj->nodesetval);
4425*7c568831SAndroid Build Coastguard Worker obj->nodesetval = NULL;
4426*7c568831SAndroid Build Coastguard Worker }
4427*7c568831SAndroid Build Coastguard Worker }
4428*7c568831SAndroid Build Coastguard Worker break;
4429*7c568831SAndroid Build Coastguard Worker case XPATH_STRING:
4430*7c568831SAndroid Build Coastguard Worker if (obj->stringval != NULL)
4431*7c568831SAndroid Build Coastguard Worker xmlFree(obj->stringval);
4432*7c568831SAndroid Build Coastguard Worker obj->stringval = NULL;
4433*7c568831SAndroid Build Coastguard Worker break;
4434*7c568831SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
4435*7c568831SAndroid Build Coastguard Worker case XPATH_NUMBER:
4436*7c568831SAndroid Build Coastguard Worker break;
4437*7c568831SAndroid Build Coastguard Worker default:
4438*7c568831SAndroid Build Coastguard Worker goto free_obj;
4439*7c568831SAndroid Build Coastguard Worker }
4440*7c568831SAndroid Build Coastguard Worker
4441*7c568831SAndroid Build Coastguard Worker /*
4442*7c568831SAndroid Build Coastguard Worker * Fallback to adding to the misc-objects slot.
4443*7c568831SAndroid Build Coastguard Worker */
4444*7c568831SAndroid Build Coastguard Worker if (cache->numMisc >= cache->maxMisc)
4445*7c568831SAndroid Build Coastguard Worker goto free_obj;
4446*7c568831SAndroid Build Coastguard Worker obj->stringval = (void *) cache->miscObjs;
4447*7c568831SAndroid Build Coastguard Worker cache->miscObjs = obj;
4448*7c568831SAndroid Build Coastguard Worker cache->numMisc += 1;
4449*7c568831SAndroid Build Coastguard Worker
4450*7c568831SAndroid Build Coastguard Worker obj_cached:
4451*7c568831SAndroid Build Coastguard Worker obj->boolval = 0;
4452*7c568831SAndroid Build Coastguard Worker if (obj->nodesetval != NULL) {
4453*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr tmpset = obj->nodesetval;
4454*7c568831SAndroid Build Coastguard Worker
4455*7c568831SAndroid Build Coastguard Worker /*
4456*7c568831SAndroid Build Coastguard Worker * Due to those nasty ns-nodes, we need to traverse
4457*7c568831SAndroid Build Coastguard Worker * the list and free the ns-nodes.
4458*7c568831SAndroid Build Coastguard Worker */
4459*7c568831SAndroid Build Coastguard Worker if (tmpset->nodeNr > 0) {
4460*7c568831SAndroid Build Coastguard Worker int i;
4461*7c568831SAndroid Build Coastguard Worker xmlNodePtr node;
4462*7c568831SAndroid Build Coastguard Worker
4463*7c568831SAndroid Build Coastguard Worker for (i = 0; i < tmpset->nodeNr; i++) {
4464*7c568831SAndroid Build Coastguard Worker node = tmpset->nodeTab[i];
4465*7c568831SAndroid Build Coastguard Worker if ((node != NULL) &&
4466*7c568831SAndroid Build Coastguard Worker (node->type == XML_NAMESPACE_DECL))
4467*7c568831SAndroid Build Coastguard Worker {
4468*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetFreeNs((xmlNsPtr) node);
4469*7c568831SAndroid Build Coastguard Worker }
4470*7c568831SAndroid Build Coastguard Worker }
4471*7c568831SAndroid Build Coastguard Worker }
4472*7c568831SAndroid Build Coastguard Worker tmpset->nodeNr = 0;
4473*7c568831SAndroid Build Coastguard Worker }
4474*7c568831SAndroid Build Coastguard Worker
4475*7c568831SAndroid Build Coastguard Worker return;
4476*7c568831SAndroid Build Coastguard Worker
4477*7c568831SAndroid Build Coastguard Worker free_obj:
4478*7c568831SAndroid Build Coastguard Worker /*
4479*7c568831SAndroid Build Coastguard Worker * Cache is full; free the object.
4480*7c568831SAndroid Build Coastguard Worker */
4481*7c568831SAndroid Build Coastguard Worker if (obj->nodesetval != NULL)
4482*7c568831SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(obj->nodesetval);
4483*7c568831SAndroid Build Coastguard Worker xmlFree(obj);
4484*7c568831SAndroid Build Coastguard Worker }
4485*7c568831SAndroid Build Coastguard Worker }
4486*7c568831SAndroid Build Coastguard Worker
4487*7c568831SAndroid Build Coastguard Worker
4488*7c568831SAndroid Build Coastguard Worker /************************************************************************
4489*7c568831SAndroid Build Coastguard Worker * *
4490*7c568831SAndroid Build Coastguard Worker * Type Casting Routines *
4491*7c568831SAndroid Build Coastguard Worker * *
4492*7c568831SAndroid Build Coastguard Worker ************************************************************************/
4493*7c568831SAndroid Build Coastguard Worker
4494*7c568831SAndroid Build Coastguard Worker /**
4495*7c568831SAndroid Build Coastguard Worker * xmlXPathCastBooleanToString:
4496*7c568831SAndroid Build Coastguard Worker * @val: a boolean
4497*7c568831SAndroid Build Coastguard Worker *
4498*7c568831SAndroid Build Coastguard Worker * Converts a boolean to its string value.
4499*7c568831SAndroid Build Coastguard Worker *
4500*7c568831SAndroid Build Coastguard Worker * Returns a newly allocated string.
4501*7c568831SAndroid Build Coastguard Worker */
4502*7c568831SAndroid Build Coastguard Worker xmlChar *
xmlXPathCastBooleanToString(int val)4503*7c568831SAndroid Build Coastguard Worker xmlXPathCastBooleanToString (int val) {
4504*7c568831SAndroid Build Coastguard Worker xmlChar *ret;
4505*7c568831SAndroid Build Coastguard Worker if (val)
4506*7c568831SAndroid Build Coastguard Worker ret = xmlStrdup((const xmlChar *) "true");
4507*7c568831SAndroid Build Coastguard Worker else
4508*7c568831SAndroid Build Coastguard Worker ret = xmlStrdup((const xmlChar *) "false");
4509*7c568831SAndroid Build Coastguard Worker return(ret);
4510*7c568831SAndroid Build Coastguard Worker }
4511*7c568831SAndroid Build Coastguard Worker
4512*7c568831SAndroid Build Coastguard Worker /**
4513*7c568831SAndroid Build Coastguard Worker * xmlXPathCastNumberToString:
4514*7c568831SAndroid Build Coastguard Worker * @val: a number
4515*7c568831SAndroid Build Coastguard Worker *
4516*7c568831SAndroid Build Coastguard Worker * Converts a number to its string value.
4517*7c568831SAndroid Build Coastguard Worker *
4518*7c568831SAndroid Build Coastguard Worker * Returns a newly allocated string.
4519*7c568831SAndroid Build Coastguard Worker */
4520*7c568831SAndroid Build Coastguard Worker xmlChar *
xmlXPathCastNumberToString(double val)4521*7c568831SAndroid Build Coastguard Worker xmlXPathCastNumberToString (double val) {
4522*7c568831SAndroid Build Coastguard Worker xmlChar *ret;
4523*7c568831SAndroid Build Coastguard Worker switch (xmlXPathIsInf(val)) {
4524*7c568831SAndroid Build Coastguard Worker case 1:
4525*7c568831SAndroid Build Coastguard Worker ret = xmlStrdup((const xmlChar *) "Infinity");
4526*7c568831SAndroid Build Coastguard Worker break;
4527*7c568831SAndroid Build Coastguard Worker case -1:
4528*7c568831SAndroid Build Coastguard Worker ret = xmlStrdup((const xmlChar *) "-Infinity");
4529*7c568831SAndroid Build Coastguard Worker break;
4530*7c568831SAndroid Build Coastguard Worker default:
4531*7c568831SAndroid Build Coastguard Worker if (xmlXPathIsNaN(val)) {
4532*7c568831SAndroid Build Coastguard Worker ret = xmlStrdup((const xmlChar *) "NaN");
4533*7c568831SAndroid Build Coastguard Worker } else if (val == 0) {
4534*7c568831SAndroid Build Coastguard Worker /* Omit sign for negative zero. */
4535*7c568831SAndroid Build Coastguard Worker ret = xmlStrdup((const xmlChar *) "0");
4536*7c568831SAndroid Build Coastguard Worker } else {
4537*7c568831SAndroid Build Coastguard Worker /* could be improved */
4538*7c568831SAndroid Build Coastguard Worker char buf[100];
4539*7c568831SAndroid Build Coastguard Worker xmlXPathFormatNumber(val, buf, 99);
4540*7c568831SAndroid Build Coastguard Worker buf[99] = 0;
4541*7c568831SAndroid Build Coastguard Worker ret = xmlStrdup((const xmlChar *) buf);
4542*7c568831SAndroid Build Coastguard Worker }
4543*7c568831SAndroid Build Coastguard Worker }
4544*7c568831SAndroid Build Coastguard Worker return(ret);
4545*7c568831SAndroid Build Coastguard Worker }
4546*7c568831SAndroid Build Coastguard Worker
4547*7c568831SAndroid Build Coastguard Worker /**
4548*7c568831SAndroid Build Coastguard Worker * xmlXPathCastNodeToString:
4549*7c568831SAndroid Build Coastguard Worker * @node: a node
4550*7c568831SAndroid Build Coastguard Worker *
4551*7c568831SAndroid Build Coastguard Worker * Converts a node to its string value.
4552*7c568831SAndroid Build Coastguard Worker *
4553*7c568831SAndroid Build Coastguard Worker * Returns a newly allocated string.
4554*7c568831SAndroid Build Coastguard Worker */
4555*7c568831SAndroid Build Coastguard Worker xmlChar *
xmlXPathCastNodeToString(xmlNodePtr node)4556*7c568831SAndroid Build Coastguard Worker xmlXPathCastNodeToString (xmlNodePtr node) {
4557*7c568831SAndroid Build Coastguard Worker return(xmlNodeGetContent(node));
4558*7c568831SAndroid Build Coastguard Worker }
4559*7c568831SAndroid Build Coastguard Worker
4560*7c568831SAndroid Build Coastguard Worker /**
4561*7c568831SAndroid Build Coastguard Worker * xmlXPathCastNodeSetToString:
4562*7c568831SAndroid Build Coastguard Worker * @ns: a node-set
4563*7c568831SAndroid Build Coastguard Worker *
4564*7c568831SAndroid Build Coastguard Worker * Converts a node-set to its string value.
4565*7c568831SAndroid Build Coastguard Worker *
4566*7c568831SAndroid Build Coastguard Worker * Returns a newly allocated string.
4567*7c568831SAndroid Build Coastguard Worker */
4568*7c568831SAndroid Build Coastguard Worker xmlChar *
xmlXPathCastNodeSetToString(xmlNodeSetPtr ns)4569*7c568831SAndroid Build Coastguard Worker xmlXPathCastNodeSetToString (xmlNodeSetPtr ns) {
4570*7c568831SAndroid Build Coastguard Worker if ((ns == NULL) || (ns->nodeNr == 0) || (ns->nodeTab == NULL))
4571*7c568831SAndroid Build Coastguard Worker return(xmlStrdup((const xmlChar *) ""));
4572*7c568831SAndroid Build Coastguard Worker
4573*7c568831SAndroid Build Coastguard Worker if (ns->nodeNr > 1)
4574*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetSort(ns);
4575*7c568831SAndroid Build Coastguard Worker return(xmlXPathCastNodeToString(ns->nodeTab[0]));
4576*7c568831SAndroid Build Coastguard Worker }
4577*7c568831SAndroid Build Coastguard Worker
4578*7c568831SAndroid Build Coastguard Worker /**
4579*7c568831SAndroid Build Coastguard Worker * xmlXPathCastToString:
4580*7c568831SAndroid Build Coastguard Worker * @val: an XPath object
4581*7c568831SAndroid Build Coastguard Worker *
4582*7c568831SAndroid Build Coastguard Worker * Converts an existing object to its string() equivalent
4583*7c568831SAndroid Build Coastguard Worker *
4584*7c568831SAndroid Build Coastguard Worker * Returns the allocated string value of the object, NULL in case of error.
4585*7c568831SAndroid Build Coastguard Worker * It's up to the caller to free the string memory with xmlFree().
4586*7c568831SAndroid Build Coastguard Worker */
4587*7c568831SAndroid Build Coastguard Worker xmlChar *
xmlXPathCastToString(xmlXPathObjectPtr val)4588*7c568831SAndroid Build Coastguard Worker xmlXPathCastToString(xmlXPathObjectPtr val) {
4589*7c568831SAndroid Build Coastguard Worker xmlChar *ret = NULL;
4590*7c568831SAndroid Build Coastguard Worker
4591*7c568831SAndroid Build Coastguard Worker if (val == NULL)
4592*7c568831SAndroid Build Coastguard Worker return(xmlStrdup((const xmlChar *) ""));
4593*7c568831SAndroid Build Coastguard Worker switch (val->type) {
4594*7c568831SAndroid Build Coastguard Worker case XPATH_UNDEFINED:
4595*7c568831SAndroid Build Coastguard Worker ret = xmlStrdup((const xmlChar *) "");
4596*7c568831SAndroid Build Coastguard Worker break;
4597*7c568831SAndroid Build Coastguard Worker case XPATH_NODESET:
4598*7c568831SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
4599*7c568831SAndroid Build Coastguard Worker ret = xmlXPathCastNodeSetToString(val->nodesetval);
4600*7c568831SAndroid Build Coastguard Worker break;
4601*7c568831SAndroid Build Coastguard Worker case XPATH_STRING:
4602*7c568831SAndroid Build Coastguard Worker return(xmlStrdup(val->stringval));
4603*7c568831SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
4604*7c568831SAndroid Build Coastguard Worker ret = xmlXPathCastBooleanToString(val->boolval);
4605*7c568831SAndroid Build Coastguard Worker break;
4606*7c568831SAndroid Build Coastguard Worker case XPATH_NUMBER: {
4607*7c568831SAndroid Build Coastguard Worker ret = xmlXPathCastNumberToString(val->floatval);
4608*7c568831SAndroid Build Coastguard Worker break;
4609*7c568831SAndroid Build Coastguard Worker }
4610*7c568831SAndroid Build Coastguard Worker case XPATH_USERS:
4611*7c568831SAndroid Build Coastguard Worker /* TODO */
4612*7c568831SAndroid Build Coastguard Worker ret = xmlStrdup((const xmlChar *) "");
4613*7c568831SAndroid Build Coastguard Worker break;
4614*7c568831SAndroid Build Coastguard Worker }
4615*7c568831SAndroid Build Coastguard Worker return(ret);
4616*7c568831SAndroid Build Coastguard Worker }
4617*7c568831SAndroid Build Coastguard Worker
4618*7c568831SAndroid Build Coastguard Worker /**
4619*7c568831SAndroid Build Coastguard Worker * xmlXPathConvertString:
4620*7c568831SAndroid Build Coastguard Worker * @val: an XPath object
4621*7c568831SAndroid Build Coastguard Worker *
4622*7c568831SAndroid Build Coastguard Worker * Converts an existing object to its string() equivalent
4623*7c568831SAndroid Build Coastguard Worker *
4624*7c568831SAndroid Build Coastguard Worker * Returns the new object, the old one is freed (or the operation
4625*7c568831SAndroid Build Coastguard Worker * is done directly on @val)
4626*7c568831SAndroid Build Coastguard Worker */
4627*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathConvertString(xmlXPathObjectPtr val)4628*7c568831SAndroid Build Coastguard Worker xmlXPathConvertString(xmlXPathObjectPtr val) {
4629*7c568831SAndroid Build Coastguard Worker xmlChar *res = NULL;
4630*7c568831SAndroid Build Coastguard Worker
4631*7c568831SAndroid Build Coastguard Worker if (val == NULL)
4632*7c568831SAndroid Build Coastguard Worker return(xmlXPathNewCString(""));
4633*7c568831SAndroid Build Coastguard Worker
4634*7c568831SAndroid Build Coastguard Worker switch (val->type) {
4635*7c568831SAndroid Build Coastguard Worker case XPATH_UNDEFINED:
4636*7c568831SAndroid Build Coastguard Worker break;
4637*7c568831SAndroid Build Coastguard Worker case XPATH_NODESET:
4638*7c568831SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
4639*7c568831SAndroid Build Coastguard Worker res = xmlXPathCastNodeSetToString(val->nodesetval);
4640*7c568831SAndroid Build Coastguard Worker break;
4641*7c568831SAndroid Build Coastguard Worker case XPATH_STRING:
4642*7c568831SAndroid Build Coastguard Worker return(val);
4643*7c568831SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
4644*7c568831SAndroid Build Coastguard Worker res = xmlXPathCastBooleanToString(val->boolval);
4645*7c568831SAndroid Build Coastguard Worker break;
4646*7c568831SAndroid Build Coastguard Worker case XPATH_NUMBER:
4647*7c568831SAndroid Build Coastguard Worker res = xmlXPathCastNumberToString(val->floatval);
4648*7c568831SAndroid Build Coastguard Worker break;
4649*7c568831SAndroid Build Coastguard Worker case XPATH_USERS:
4650*7c568831SAndroid Build Coastguard Worker /* TODO */
4651*7c568831SAndroid Build Coastguard Worker break;
4652*7c568831SAndroid Build Coastguard Worker }
4653*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(val);
4654*7c568831SAndroid Build Coastguard Worker if (res == NULL)
4655*7c568831SAndroid Build Coastguard Worker return(xmlXPathNewCString(""));
4656*7c568831SAndroid Build Coastguard Worker return(xmlXPathWrapString(res));
4657*7c568831SAndroid Build Coastguard Worker }
4658*7c568831SAndroid Build Coastguard Worker
4659*7c568831SAndroid Build Coastguard Worker /**
4660*7c568831SAndroid Build Coastguard Worker * xmlXPathCastBooleanToNumber:
4661*7c568831SAndroid Build Coastguard Worker * @val: a boolean
4662*7c568831SAndroid Build Coastguard Worker *
4663*7c568831SAndroid Build Coastguard Worker * Converts a boolean to its number value
4664*7c568831SAndroid Build Coastguard Worker *
4665*7c568831SAndroid Build Coastguard Worker * Returns the number value
4666*7c568831SAndroid Build Coastguard Worker */
4667*7c568831SAndroid Build Coastguard Worker double
xmlXPathCastBooleanToNumber(int val)4668*7c568831SAndroid Build Coastguard Worker xmlXPathCastBooleanToNumber(int val) {
4669*7c568831SAndroid Build Coastguard Worker if (val)
4670*7c568831SAndroid Build Coastguard Worker return(1.0);
4671*7c568831SAndroid Build Coastguard Worker return(0.0);
4672*7c568831SAndroid Build Coastguard Worker }
4673*7c568831SAndroid Build Coastguard Worker
4674*7c568831SAndroid Build Coastguard Worker /**
4675*7c568831SAndroid Build Coastguard Worker * xmlXPathCastStringToNumber:
4676*7c568831SAndroid Build Coastguard Worker * @val: a string
4677*7c568831SAndroid Build Coastguard Worker *
4678*7c568831SAndroid Build Coastguard Worker * Converts a string to its number value
4679*7c568831SAndroid Build Coastguard Worker *
4680*7c568831SAndroid Build Coastguard Worker * Returns the number value
4681*7c568831SAndroid Build Coastguard Worker */
4682*7c568831SAndroid Build Coastguard Worker double
xmlXPathCastStringToNumber(const xmlChar * val)4683*7c568831SAndroid Build Coastguard Worker xmlXPathCastStringToNumber(const xmlChar * val) {
4684*7c568831SAndroid Build Coastguard Worker return(xmlXPathStringEvalNumber(val));
4685*7c568831SAndroid Build Coastguard Worker }
4686*7c568831SAndroid Build Coastguard Worker
4687*7c568831SAndroid Build Coastguard Worker /**
4688*7c568831SAndroid Build Coastguard Worker * xmlXPathNodeToNumberInternal:
4689*7c568831SAndroid Build Coastguard Worker * @node: a node
4690*7c568831SAndroid Build Coastguard Worker *
4691*7c568831SAndroid Build Coastguard Worker * Converts a node to its number value
4692*7c568831SAndroid Build Coastguard Worker *
4693*7c568831SAndroid Build Coastguard Worker * Returns the number value
4694*7c568831SAndroid Build Coastguard Worker */
4695*7c568831SAndroid Build Coastguard Worker static double
xmlXPathNodeToNumberInternal(xmlXPathParserContextPtr ctxt,xmlNodePtr node)4696*7c568831SAndroid Build Coastguard Worker xmlXPathNodeToNumberInternal(xmlXPathParserContextPtr ctxt, xmlNodePtr node) {
4697*7c568831SAndroid Build Coastguard Worker xmlChar *strval;
4698*7c568831SAndroid Build Coastguard Worker double ret;
4699*7c568831SAndroid Build Coastguard Worker
4700*7c568831SAndroid Build Coastguard Worker if (node == NULL)
4701*7c568831SAndroid Build Coastguard Worker return(xmlXPathNAN);
4702*7c568831SAndroid Build Coastguard Worker strval = xmlXPathCastNodeToString(node);
4703*7c568831SAndroid Build Coastguard Worker if (strval == NULL) {
4704*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
4705*7c568831SAndroid Build Coastguard Worker return(xmlXPathNAN);
4706*7c568831SAndroid Build Coastguard Worker }
4707*7c568831SAndroid Build Coastguard Worker ret = xmlXPathCastStringToNumber(strval);
4708*7c568831SAndroid Build Coastguard Worker xmlFree(strval);
4709*7c568831SAndroid Build Coastguard Worker
4710*7c568831SAndroid Build Coastguard Worker return(ret);
4711*7c568831SAndroid Build Coastguard Worker }
4712*7c568831SAndroid Build Coastguard Worker
4713*7c568831SAndroid Build Coastguard Worker /**
4714*7c568831SAndroid Build Coastguard Worker * xmlXPathCastNodeToNumber:
4715*7c568831SAndroid Build Coastguard Worker * @node: a node
4716*7c568831SAndroid Build Coastguard Worker *
4717*7c568831SAndroid Build Coastguard Worker * Converts a node to its number value
4718*7c568831SAndroid Build Coastguard Worker *
4719*7c568831SAndroid Build Coastguard Worker * Returns the number value
4720*7c568831SAndroid Build Coastguard Worker */
4721*7c568831SAndroid Build Coastguard Worker double
xmlXPathCastNodeToNumber(xmlNodePtr node)4722*7c568831SAndroid Build Coastguard Worker xmlXPathCastNodeToNumber (xmlNodePtr node) {
4723*7c568831SAndroid Build Coastguard Worker return(xmlXPathNodeToNumberInternal(NULL, node));
4724*7c568831SAndroid Build Coastguard Worker }
4725*7c568831SAndroid Build Coastguard Worker
4726*7c568831SAndroid Build Coastguard Worker /**
4727*7c568831SAndroid Build Coastguard Worker * xmlXPathCastNodeSetToNumber:
4728*7c568831SAndroid Build Coastguard Worker * @ns: a node-set
4729*7c568831SAndroid Build Coastguard Worker *
4730*7c568831SAndroid Build Coastguard Worker * Converts a node-set to its number value
4731*7c568831SAndroid Build Coastguard Worker *
4732*7c568831SAndroid Build Coastguard Worker * Returns the number value
4733*7c568831SAndroid Build Coastguard Worker */
4734*7c568831SAndroid Build Coastguard Worker double
xmlXPathCastNodeSetToNumber(xmlNodeSetPtr ns)4735*7c568831SAndroid Build Coastguard Worker xmlXPathCastNodeSetToNumber (xmlNodeSetPtr ns) {
4736*7c568831SAndroid Build Coastguard Worker xmlChar *str;
4737*7c568831SAndroid Build Coastguard Worker double ret;
4738*7c568831SAndroid Build Coastguard Worker
4739*7c568831SAndroid Build Coastguard Worker if (ns == NULL)
4740*7c568831SAndroid Build Coastguard Worker return(xmlXPathNAN);
4741*7c568831SAndroid Build Coastguard Worker str = xmlXPathCastNodeSetToString(ns);
4742*7c568831SAndroid Build Coastguard Worker ret = xmlXPathCastStringToNumber(str);
4743*7c568831SAndroid Build Coastguard Worker xmlFree(str);
4744*7c568831SAndroid Build Coastguard Worker return(ret);
4745*7c568831SAndroid Build Coastguard Worker }
4746*7c568831SAndroid Build Coastguard Worker
4747*7c568831SAndroid Build Coastguard Worker /**
4748*7c568831SAndroid Build Coastguard Worker * xmlXPathCastToNumber:
4749*7c568831SAndroid Build Coastguard Worker * @val: an XPath object
4750*7c568831SAndroid Build Coastguard Worker *
4751*7c568831SAndroid Build Coastguard Worker * Converts an XPath object to its number value
4752*7c568831SAndroid Build Coastguard Worker *
4753*7c568831SAndroid Build Coastguard Worker * Returns the number value
4754*7c568831SAndroid Build Coastguard Worker */
4755*7c568831SAndroid Build Coastguard Worker double
xmlXPathCastToNumber(xmlXPathObjectPtr val)4756*7c568831SAndroid Build Coastguard Worker xmlXPathCastToNumber(xmlXPathObjectPtr val) {
4757*7c568831SAndroid Build Coastguard Worker return(xmlXPathCastToNumberInternal(NULL, val));
4758*7c568831SAndroid Build Coastguard Worker }
4759*7c568831SAndroid Build Coastguard Worker
4760*7c568831SAndroid Build Coastguard Worker /**
4761*7c568831SAndroid Build Coastguard Worker * xmlXPathConvertNumber:
4762*7c568831SAndroid Build Coastguard Worker * @val: an XPath object
4763*7c568831SAndroid Build Coastguard Worker *
4764*7c568831SAndroid Build Coastguard Worker * Converts an existing object to its number() equivalent
4765*7c568831SAndroid Build Coastguard Worker *
4766*7c568831SAndroid Build Coastguard Worker * Returns the new object, the old one is freed (or the operation
4767*7c568831SAndroid Build Coastguard Worker * is done directly on @val)
4768*7c568831SAndroid Build Coastguard Worker */
4769*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathConvertNumber(xmlXPathObjectPtr val)4770*7c568831SAndroid Build Coastguard Worker xmlXPathConvertNumber(xmlXPathObjectPtr val) {
4771*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
4772*7c568831SAndroid Build Coastguard Worker
4773*7c568831SAndroid Build Coastguard Worker if (val == NULL)
4774*7c568831SAndroid Build Coastguard Worker return(xmlXPathNewFloat(0.0));
4775*7c568831SAndroid Build Coastguard Worker if (val->type == XPATH_NUMBER)
4776*7c568831SAndroid Build Coastguard Worker return(val);
4777*7c568831SAndroid Build Coastguard Worker ret = xmlXPathNewFloat(xmlXPathCastToNumber(val));
4778*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(val);
4779*7c568831SAndroid Build Coastguard Worker return(ret);
4780*7c568831SAndroid Build Coastguard Worker }
4781*7c568831SAndroid Build Coastguard Worker
4782*7c568831SAndroid Build Coastguard Worker /**
4783*7c568831SAndroid Build Coastguard Worker * xmlXPathCastNumberToBoolean:
4784*7c568831SAndroid Build Coastguard Worker * @val: a number
4785*7c568831SAndroid Build Coastguard Worker *
4786*7c568831SAndroid Build Coastguard Worker * Converts a number to its boolean value
4787*7c568831SAndroid Build Coastguard Worker *
4788*7c568831SAndroid Build Coastguard Worker * Returns the boolean value
4789*7c568831SAndroid Build Coastguard Worker */
4790*7c568831SAndroid Build Coastguard Worker int
xmlXPathCastNumberToBoolean(double val)4791*7c568831SAndroid Build Coastguard Worker xmlXPathCastNumberToBoolean (double val) {
4792*7c568831SAndroid Build Coastguard Worker if (xmlXPathIsNaN(val) || (val == 0.0))
4793*7c568831SAndroid Build Coastguard Worker return(0);
4794*7c568831SAndroid Build Coastguard Worker return(1);
4795*7c568831SAndroid Build Coastguard Worker }
4796*7c568831SAndroid Build Coastguard Worker
4797*7c568831SAndroid Build Coastguard Worker /**
4798*7c568831SAndroid Build Coastguard Worker * xmlXPathCastStringToBoolean:
4799*7c568831SAndroid Build Coastguard Worker * @val: a string
4800*7c568831SAndroid Build Coastguard Worker *
4801*7c568831SAndroid Build Coastguard Worker * Converts a string to its boolean value
4802*7c568831SAndroid Build Coastguard Worker *
4803*7c568831SAndroid Build Coastguard Worker * Returns the boolean value
4804*7c568831SAndroid Build Coastguard Worker */
4805*7c568831SAndroid Build Coastguard Worker int
xmlXPathCastStringToBoolean(const xmlChar * val)4806*7c568831SAndroid Build Coastguard Worker xmlXPathCastStringToBoolean (const xmlChar *val) {
4807*7c568831SAndroid Build Coastguard Worker if ((val == NULL) || (xmlStrlen(val) == 0))
4808*7c568831SAndroid Build Coastguard Worker return(0);
4809*7c568831SAndroid Build Coastguard Worker return(1);
4810*7c568831SAndroid Build Coastguard Worker }
4811*7c568831SAndroid Build Coastguard Worker
4812*7c568831SAndroid Build Coastguard Worker /**
4813*7c568831SAndroid Build Coastguard Worker * xmlXPathCastNodeSetToBoolean:
4814*7c568831SAndroid Build Coastguard Worker * @ns: a node-set
4815*7c568831SAndroid Build Coastguard Worker *
4816*7c568831SAndroid Build Coastguard Worker * Converts a node-set to its boolean value
4817*7c568831SAndroid Build Coastguard Worker *
4818*7c568831SAndroid Build Coastguard Worker * Returns the boolean value
4819*7c568831SAndroid Build Coastguard Worker */
4820*7c568831SAndroid Build Coastguard Worker int
xmlXPathCastNodeSetToBoolean(xmlNodeSetPtr ns)4821*7c568831SAndroid Build Coastguard Worker xmlXPathCastNodeSetToBoolean (xmlNodeSetPtr ns) {
4822*7c568831SAndroid Build Coastguard Worker if ((ns == NULL) || (ns->nodeNr == 0))
4823*7c568831SAndroid Build Coastguard Worker return(0);
4824*7c568831SAndroid Build Coastguard Worker return(1);
4825*7c568831SAndroid Build Coastguard Worker }
4826*7c568831SAndroid Build Coastguard Worker
4827*7c568831SAndroid Build Coastguard Worker /**
4828*7c568831SAndroid Build Coastguard Worker * xmlXPathCastToBoolean:
4829*7c568831SAndroid Build Coastguard Worker * @val: an XPath object
4830*7c568831SAndroid Build Coastguard Worker *
4831*7c568831SAndroid Build Coastguard Worker * Converts an XPath object to its boolean value
4832*7c568831SAndroid Build Coastguard Worker *
4833*7c568831SAndroid Build Coastguard Worker * Returns the boolean value
4834*7c568831SAndroid Build Coastguard Worker */
4835*7c568831SAndroid Build Coastguard Worker int
xmlXPathCastToBoolean(xmlXPathObjectPtr val)4836*7c568831SAndroid Build Coastguard Worker xmlXPathCastToBoolean (xmlXPathObjectPtr val) {
4837*7c568831SAndroid Build Coastguard Worker int ret = 0;
4838*7c568831SAndroid Build Coastguard Worker
4839*7c568831SAndroid Build Coastguard Worker if (val == NULL)
4840*7c568831SAndroid Build Coastguard Worker return(0);
4841*7c568831SAndroid Build Coastguard Worker switch (val->type) {
4842*7c568831SAndroid Build Coastguard Worker case XPATH_UNDEFINED:
4843*7c568831SAndroid Build Coastguard Worker ret = 0;
4844*7c568831SAndroid Build Coastguard Worker break;
4845*7c568831SAndroid Build Coastguard Worker case XPATH_NODESET:
4846*7c568831SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
4847*7c568831SAndroid Build Coastguard Worker ret = xmlXPathCastNodeSetToBoolean(val->nodesetval);
4848*7c568831SAndroid Build Coastguard Worker break;
4849*7c568831SAndroid Build Coastguard Worker case XPATH_STRING:
4850*7c568831SAndroid Build Coastguard Worker ret = xmlXPathCastStringToBoolean(val->stringval);
4851*7c568831SAndroid Build Coastguard Worker break;
4852*7c568831SAndroid Build Coastguard Worker case XPATH_NUMBER:
4853*7c568831SAndroid Build Coastguard Worker ret = xmlXPathCastNumberToBoolean(val->floatval);
4854*7c568831SAndroid Build Coastguard Worker break;
4855*7c568831SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
4856*7c568831SAndroid Build Coastguard Worker ret = val->boolval;
4857*7c568831SAndroid Build Coastguard Worker break;
4858*7c568831SAndroid Build Coastguard Worker case XPATH_USERS:
4859*7c568831SAndroid Build Coastguard Worker /* TODO */
4860*7c568831SAndroid Build Coastguard Worker ret = 0;
4861*7c568831SAndroid Build Coastguard Worker break;
4862*7c568831SAndroid Build Coastguard Worker }
4863*7c568831SAndroid Build Coastguard Worker return(ret);
4864*7c568831SAndroid Build Coastguard Worker }
4865*7c568831SAndroid Build Coastguard Worker
4866*7c568831SAndroid Build Coastguard Worker
4867*7c568831SAndroid Build Coastguard Worker /**
4868*7c568831SAndroid Build Coastguard Worker * xmlXPathConvertBoolean:
4869*7c568831SAndroid Build Coastguard Worker * @val: an XPath object
4870*7c568831SAndroid Build Coastguard Worker *
4871*7c568831SAndroid Build Coastguard Worker * Converts an existing object to its boolean() equivalent
4872*7c568831SAndroid Build Coastguard Worker *
4873*7c568831SAndroid Build Coastguard Worker * Returns the new object, the old one is freed (or the operation
4874*7c568831SAndroid Build Coastguard Worker * is done directly on @val)
4875*7c568831SAndroid Build Coastguard Worker */
4876*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathConvertBoolean(xmlXPathObjectPtr val)4877*7c568831SAndroid Build Coastguard Worker xmlXPathConvertBoolean(xmlXPathObjectPtr val) {
4878*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
4879*7c568831SAndroid Build Coastguard Worker
4880*7c568831SAndroid Build Coastguard Worker if (val == NULL)
4881*7c568831SAndroid Build Coastguard Worker return(xmlXPathNewBoolean(0));
4882*7c568831SAndroid Build Coastguard Worker if (val->type == XPATH_BOOLEAN)
4883*7c568831SAndroid Build Coastguard Worker return(val);
4884*7c568831SAndroid Build Coastguard Worker ret = xmlXPathNewBoolean(xmlXPathCastToBoolean(val));
4885*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(val);
4886*7c568831SAndroid Build Coastguard Worker return(ret);
4887*7c568831SAndroid Build Coastguard Worker }
4888*7c568831SAndroid Build Coastguard Worker
4889*7c568831SAndroid Build Coastguard Worker /************************************************************************
4890*7c568831SAndroid Build Coastguard Worker * *
4891*7c568831SAndroid Build Coastguard Worker * Routines to handle XPath contexts *
4892*7c568831SAndroid Build Coastguard Worker * *
4893*7c568831SAndroid Build Coastguard Worker ************************************************************************/
4894*7c568831SAndroid Build Coastguard Worker
4895*7c568831SAndroid Build Coastguard Worker /**
4896*7c568831SAndroid Build Coastguard Worker * xmlXPathNewContext:
4897*7c568831SAndroid Build Coastguard Worker * @doc: the XML document
4898*7c568831SAndroid Build Coastguard Worker *
4899*7c568831SAndroid Build Coastguard Worker * Create a new xmlXPathContext
4900*7c568831SAndroid Build Coastguard Worker *
4901*7c568831SAndroid Build Coastguard Worker * Returns the xmlXPathContext just allocated. The caller will need to free it.
4902*7c568831SAndroid Build Coastguard Worker */
4903*7c568831SAndroid Build Coastguard Worker xmlXPathContextPtr
xmlXPathNewContext(xmlDocPtr doc)4904*7c568831SAndroid Build Coastguard Worker xmlXPathNewContext(xmlDocPtr doc) {
4905*7c568831SAndroid Build Coastguard Worker xmlXPathContextPtr ret;
4906*7c568831SAndroid Build Coastguard Worker
4907*7c568831SAndroid Build Coastguard Worker ret = (xmlXPathContextPtr) xmlMalloc(sizeof(xmlXPathContext));
4908*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
4909*7c568831SAndroid Build Coastguard Worker return(NULL);
4910*7c568831SAndroid Build Coastguard Worker memset(ret, 0 , sizeof(xmlXPathContext));
4911*7c568831SAndroid Build Coastguard Worker ret->doc = doc;
4912*7c568831SAndroid Build Coastguard Worker ret->node = NULL;
4913*7c568831SAndroid Build Coastguard Worker
4914*7c568831SAndroid Build Coastguard Worker ret->varHash = NULL;
4915*7c568831SAndroid Build Coastguard Worker
4916*7c568831SAndroid Build Coastguard Worker ret->nb_types = 0;
4917*7c568831SAndroid Build Coastguard Worker ret->max_types = 0;
4918*7c568831SAndroid Build Coastguard Worker ret->types = NULL;
4919*7c568831SAndroid Build Coastguard Worker
4920*7c568831SAndroid Build Coastguard Worker ret->nb_axis = 0;
4921*7c568831SAndroid Build Coastguard Worker ret->max_axis = 0;
4922*7c568831SAndroid Build Coastguard Worker ret->axis = NULL;
4923*7c568831SAndroid Build Coastguard Worker
4924*7c568831SAndroid Build Coastguard Worker ret->nsHash = NULL;
4925*7c568831SAndroid Build Coastguard Worker ret->user = NULL;
4926*7c568831SAndroid Build Coastguard Worker
4927*7c568831SAndroid Build Coastguard Worker ret->contextSize = -1;
4928*7c568831SAndroid Build Coastguard Worker ret->proximityPosition = -1;
4929*7c568831SAndroid Build Coastguard Worker
4930*7c568831SAndroid Build Coastguard Worker #ifdef XP_DEFAULT_CACHE_ON
4931*7c568831SAndroid Build Coastguard Worker if (xmlXPathContextSetCache(ret, 1, -1, 0) == -1) {
4932*7c568831SAndroid Build Coastguard Worker xmlXPathFreeContext(ret);
4933*7c568831SAndroid Build Coastguard Worker return(NULL);
4934*7c568831SAndroid Build Coastguard Worker }
4935*7c568831SAndroid Build Coastguard Worker #endif
4936*7c568831SAndroid Build Coastguard Worker
4937*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterAllFunctions(ret);
4938*7c568831SAndroid Build Coastguard Worker
4939*7c568831SAndroid Build Coastguard Worker if (ret->lastError.code != XML_ERR_OK) {
4940*7c568831SAndroid Build Coastguard Worker xmlXPathFreeContext(ret);
4941*7c568831SAndroid Build Coastguard Worker return(NULL);
4942*7c568831SAndroid Build Coastguard Worker }
4943*7c568831SAndroid Build Coastguard Worker
4944*7c568831SAndroid Build Coastguard Worker return(ret);
4945*7c568831SAndroid Build Coastguard Worker }
4946*7c568831SAndroid Build Coastguard Worker
4947*7c568831SAndroid Build Coastguard Worker /**
4948*7c568831SAndroid Build Coastguard Worker * xmlXPathFreeContext:
4949*7c568831SAndroid Build Coastguard Worker * @ctxt: the context to free
4950*7c568831SAndroid Build Coastguard Worker *
4951*7c568831SAndroid Build Coastguard Worker * Free up an xmlXPathContext
4952*7c568831SAndroid Build Coastguard Worker */
4953*7c568831SAndroid Build Coastguard Worker void
xmlXPathFreeContext(xmlXPathContextPtr ctxt)4954*7c568831SAndroid Build Coastguard Worker xmlXPathFreeContext(xmlXPathContextPtr ctxt) {
4955*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL) return;
4956*7c568831SAndroid Build Coastguard Worker
4957*7c568831SAndroid Build Coastguard Worker if (ctxt->cache != NULL)
4958*7c568831SAndroid Build Coastguard Worker xmlXPathFreeCache((xmlXPathContextCachePtr) ctxt->cache);
4959*7c568831SAndroid Build Coastguard Worker xmlXPathRegisteredNsCleanup(ctxt);
4960*7c568831SAndroid Build Coastguard Worker xmlXPathRegisteredFuncsCleanup(ctxt);
4961*7c568831SAndroid Build Coastguard Worker xmlXPathRegisteredVariablesCleanup(ctxt);
4962*7c568831SAndroid Build Coastguard Worker xmlResetError(&ctxt->lastError);
4963*7c568831SAndroid Build Coastguard Worker xmlFree(ctxt);
4964*7c568831SAndroid Build Coastguard Worker }
4965*7c568831SAndroid Build Coastguard Worker
4966*7c568831SAndroid Build Coastguard Worker /**
4967*7c568831SAndroid Build Coastguard Worker * xmlXPathSetErrorHandler:
4968*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath context
4969*7c568831SAndroid Build Coastguard Worker * @handler: error handler
4970*7c568831SAndroid Build Coastguard Worker * @data: user data which will be passed to the handler
4971*7c568831SAndroid Build Coastguard Worker *
4972*7c568831SAndroid Build Coastguard Worker * Register a callback function that will be called on errors and
4973*7c568831SAndroid Build Coastguard Worker * warnings. If handler is NULL, the error handler will be deactivated.
4974*7c568831SAndroid Build Coastguard Worker *
4975*7c568831SAndroid Build Coastguard Worker * Available since 2.13.0.
4976*7c568831SAndroid Build Coastguard Worker */
4977*7c568831SAndroid Build Coastguard Worker void
xmlXPathSetErrorHandler(xmlXPathContextPtr ctxt,xmlStructuredErrorFunc handler,void * data)4978*7c568831SAndroid Build Coastguard Worker xmlXPathSetErrorHandler(xmlXPathContextPtr ctxt,
4979*7c568831SAndroid Build Coastguard Worker xmlStructuredErrorFunc handler, void *data) {
4980*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
4981*7c568831SAndroid Build Coastguard Worker return;
4982*7c568831SAndroid Build Coastguard Worker
4983*7c568831SAndroid Build Coastguard Worker ctxt->error = handler;
4984*7c568831SAndroid Build Coastguard Worker ctxt->userData = data;
4985*7c568831SAndroid Build Coastguard Worker }
4986*7c568831SAndroid Build Coastguard Worker
4987*7c568831SAndroid Build Coastguard Worker /************************************************************************
4988*7c568831SAndroid Build Coastguard Worker * *
4989*7c568831SAndroid Build Coastguard Worker * Routines to handle XPath parser contexts *
4990*7c568831SAndroid Build Coastguard Worker * *
4991*7c568831SAndroid Build Coastguard Worker ************************************************************************/
4992*7c568831SAndroid Build Coastguard Worker
4993*7c568831SAndroid Build Coastguard Worker /**
4994*7c568831SAndroid Build Coastguard Worker * xmlXPathNewParserContext:
4995*7c568831SAndroid Build Coastguard Worker * @str: the XPath expression
4996*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath context
4997*7c568831SAndroid Build Coastguard Worker *
4998*7c568831SAndroid Build Coastguard Worker * Create a new xmlXPathParserContext
4999*7c568831SAndroid Build Coastguard Worker *
5000*7c568831SAndroid Build Coastguard Worker * Returns the xmlXPathParserContext just allocated.
5001*7c568831SAndroid Build Coastguard Worker */
5002*7c568831SAndroid Build Coastguard Worker xmlXPathParserContextPtr
xmlXPathNewParserContext(const xmlChar * str,xmlXPathContextPtr ctxt)5003*7c568831SAndroid Build Coastguard Worker xmlXPathNewParserContext(const xmlChar *str, xmlXPathContextPtr ctxt) {
5004*7c568831SAndroid Build Coastguard Worker xmlXPathParserContextPtr ret;
5005*7c568831SAndroid Build Coastguard Worker
5006*7c568831SAndroid Build Coastguard Worker ret = (xmlXPathParserContextPtr) xmlMalloc(sizeof(xmlXPathParserContext));
5007*7c568831SAndroid Build Coastguard Worker if (ret == NULL) {
5008*7c568831SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt);
5009*7c568831SAndroid Build Coastguard Worker return(NULL);
5010*7c568831SAndroid Build Coastguard Worker }
5011*7c568831SAndroid Build Coastguard Worker memset(ret, 0 , sizeof(xmlXPathParserContext));
5012*7c568831SAndroid Build Coastguard Worker ret->cur = ret->base = str;
5013*7c568831SAndroid Build Coastguard Worker ret->context = ctxt;
5014*7c568831SAndroid Build Coastguard Worker
5015*7c568831SAndroid Build Coastguard Worker ret->comp = xmlXPathNewCompExpr();
5016*7c568831SAndroid Build Coastguard Worker if (ret->comp == NULL) {
5017*7c568831SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt);
5018*7c568831SAndroid Build Coastguard Worker xmlFree(ret->valueTab);
5019*7c568831SAndroid Build Coastguard Worker xmlFree(ret);
5020*7c568831SAndroid Build Coastguard Worker return(NULL);
5021*7c568831SAndroid Build Coastguard Worker }
5022*7c568831SAndroid Build Coastguard Worker if ((ctxt != NULL) && (ctxt->dict != NULL)) {
5023*7c568831SAndroid Build Coastguard Worker ret->comp->dict = ctxt->dict;
5024*7c568831SAndroid Build Coastguard Worker xmlDictReference(ret->comp->dict);
5025*7c568831SAndroid Build Coastguard Worker }
5026*7c568831SAndroid Build Coastguard Worker
5027*7c568831SAndroid Build Coastguard Worker return(ret);
5028*7c568831SAndroid Build Coastguard Worker }
5029*7c568831SAndroid Build Coastguard Worker
5030*7c568831SAndroid Build Coastguard Worker /**
5031*7c568831SAndroid Build Coastguard Worker * xmlXPathCompParserContext:
5032*7c568831SAndroid Build Coastguard Worker * @comp: the XPath compiled expression
5033*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath context
5034*7c568831SAndroid Build Coastguard Worker *
5035*7c568831SAndroid Build Coastguard Worker * Create a new xmlXPathParserContext when processing a compiled expression
5036*7c568831SAndroid Build Coastguard Worker *
5037*7c568831SAndroid Build Coastguard Worker * Returns the xmlXPathParserContext just allocated.
5038*7c568831SAndroid Build Coastguard Worker */
5039*7c568831SAndroid Build Coastguard Worker static xmlXPathParserContextPtr
xmlXPathCompParserContext(xmlXPathCompExprPtr comp,xmlXPathContextPtr ctxt)5040*7c568831SAndroid Build Coastguard Worker xmlXPathCompParserContext(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctxt) {
5041*7c568831SAndroid Build Coastguard Worker xmlXPathParserContextPtr ret;
5042*7c568831SAndroid Build Coastguard Worker
5043*7c568831SAndroid Build Coastguard Worker ret = (xmlXPathParserContextPtr) xmlMalloc(sizeof(xmlXPathParserContext));
5044*7c568831SAndroid Build Coastguard Worker if (ret == NULL) {
5045*7c568831SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt);
5046*7c568831SAndroid Build Coastguard Worker return(NULL);
5047*7c568831SAndroid Build Coastguard Worker }
5048*7c568831SAndroid Build Coastguard Worker memset(ret, 0 , sizeof(xmlXPathParserContext));
5049*7c568831SAndroid Build Coastguard Worker
5050*7c568831SAndroid Build Coastguard Worker /* Allocate the value stack */
5051*7c568831SAndroid Build Coastguard Worker ret->valueTab = (xmlXPathObjectPtr *)
5052*7c568831SAndroid Build Coastguard Worker xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
5053*7c568831SAndroid Build Coastguard Worker if (ret->valueTab == NULL) {
5054*7c568831SAndroid Build Coastguard Worker xmlFree(ret);
5055*7c568831SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt);
5056*7c568831SAndroid Build Coastguard Worker return(NULL);
5057*7c568831SAndroid Build Coastguard Worker }
5058*7c568831SAndroid Build Coastguard Worker ret->valueNr = 0;
5059*7c568831SAndroid Build Coastguard Worker ret->valueMax = 10;
5060*7c568831SAndroid Build Coastguard Worker ret->value = NULL;
5061*7c568831SAndroid Build Coastguard Worker
5062*7c568831SAndroid Build Coastguard Worker ret->context = ctxt;
5063*7c568831SAndroid Build Coastguard Worker ret->comp = comp;
5064*7c568831SAndroid Build Coastguard Worker
5065*7c568831SAndroid Build Coastguard Worker return(ret);
5066*7c568831SAndroid Build Coastguard Worker }
5067*7c568831SAndroid Build Coastguard Worker
5068*7c568831SAndroid Build Coastguard Worker /**
5069*7c568831SAndroid Build Coastguard Worker * xmlXPathFreeParserContext:
5070*7c568831SAndroid Build Coastguard Worker * @ctxt: the context to free
5071*7c568831SAndroid Build Coastguard Worker *
5072*7c568831SAndroid Build Coastguard Worker * Free up an xmlXPathParserContext
5073*7c568831SAndroid Build Coastguard Worker */
5074*7c568831SAndroid Build Coastguard Worker void
xmlXPathFreeParserContext(xmlXPathParserContextPtr ctxt)5075*7c568831SAndroid Build Coastguard Worker xmlXPathFreeParserContext(xmlXPathParserContextPtr ctxt) {
5076*7c568831SAndroid Build Coastguard Worker int i;
5077*7c568831SAndroid Build Coastguard Worker
5078*7c568831SAndroid Build Coastguard Worker if (ctxt->valueTab != NULL) {
5079*7c568831SAndroid Build Coastguard Worker for (i = 0; i < ctxt->valueNr; i++) {
5080*7c568831SAndroid Build Coastguard Worker if (ctxt->context)
5081*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, ctxt->valueTab[i]);
5082*7c568831SAndroid Build Coastguard Worker else
5083*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(ctxt->valueTab[i]);
5084*7c568831SAndroid Build Coastguard Worker }
5085*7c568831SAndroid Build Coastguard Worker xmlFree(ctxt->valueTab);
5086*7c568831SAndroid Build Coastguard Worker }
5087*7c568831SAndroid Build Coastguard Worker if (ctxt->comp != NULL) {
5088*7c568831SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
5089*7c568831SAndroid Build Coastguard Worker if (ctxt->comp->stream != NULL) {
5090*7c568831SAndroid Build Coastguard Worker xmlFreePatternList(ctxt->comp->stream);
5091*7c568831SAndroid Build Coastguard Worker ctxt->comp->stream = NULL;
5092*7c568831SAndroid Build Coastguard Worker }
5093*7c568831SAndroid Build Coastguard Worker #endif
5094*7c568831SAndroid Build Coastguard Worker xmlXPathFreeCompExpr(ctxt->comp);
5095*7c568831SAndroid Build Coastguard Worker }
5096*7c568831SAndroid Build Coastguard Worker xmlFree(ctxt);
5097*7c568831SAndroid Build Coastguard Worker }
5098*7c568831SAndroid Build Coastguard Worker
5099*7c568831SAndroid Build Coastguard Worker /************************************************************************
5100*7c568831SAndroid Build Coastguard Worker * *
5101*7c568831SAndroid Build Coastguard Worker * The implicit core function library *
5102*7c568831SAndroid Build Coastguard Worker * *
5103*7c568831SAndroid Build Coastguard Worker ************************************************************************/
5104*7c568831SAndroid Build Coastguard Worker
5105*7c568831SAndroid Build Coastguard Worker /**
5106*7c568831SAndroid Build Coastguard Worker * xmlXPathNodeValHash:
5107*7c568831SAndroid Build Coastguard Worker * @node: a node pointer
5108*7c568831SAndroid Build Coastguard Worker *
5109*7c568831SAndroid Build Coastguard Worker * Function computing the beginning of the string value of the node,
5110*7c568831SAndroid Build Coastguard Worker * used to speed up comparisons
5111*7c568831SAndroid Build Coastguard Worker *
5112*7c568831SAndroid Build Coastguard Worker * Returns an int usable as a hash
5113*7c568831SAndroid Build Coastguard Worker */
5114*7c568831SAndroid Build Coastguard Worker static unsigned int
xmlXPathNodeValHash(xmlNodePtr node)5115*7c568831SAndroid Build Coastguard Worker xmlXPathNodeValHash(xmlNodePtr node) {
5116*7c568831SAndroid Build Coastguard Worker int len = 2;
5117*7c568831SAndroid Build Coastguard Worker const xmlChar * string = NULL;
5118*7c568831SAndroid Build Coastguard Worker xmlNodePtr tmp = NULL;
5119*7c568831SAndroid Build Coastguard Worker unsigned int ret = 0;
5120*7c568831SAndroid Build Coastguard Worker
5121*7c568831SAndroid Build Coastguard Worker if (node == NULL)
5122*7c568831SAndroid Build Coastguard Worker return(0);
5123*7c568831SAndroid Build Coastguard Worker
5124*7c568831SAndroid Build Coastguard Worker if (node->type == XML_DOCUMENT_NODE) {
5125*7c568831SAndroid Build Coastguard Worker tmp = xmlDocGetRootElement((xmlDocPtr) node);
5126*7c568831SAndroid Build Coastguard Worker if (tmp == NULL)
5127*7c568831SAndroid Build Coastguard Worker node = node->children;
5128*7c568831SAndroid Build Coastguard Worker else
5129*7c568831SAndroid Build Coastguard Worker node = tmp;
5130*7c568831SAndroid Build Coastguard Worker
5131*7c568831SAndroid Build Coastguard Worker if (node == NULL)
5132*7c568831SAndroid Build Coastguard Worker return(0);
5133*7c568831SAndroid Build Coastguard Worker }
5134*7c568831SAndroid Build Coastguard Worker
5135*7c568831SAndroid Build Coastguard Worker switch (node->type) {
5136*7c568831SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
5137*7c568831SAndroid Build Coastguard Worker case XML_PI_NODE:
5138*7c568831SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
5139*7c568831SAndroid Build Coastguard Worker case XML_TEXT_NODE:
5140*7c568831SAndroid Build Coastguard Worker string = node->content;
5141*7c568831SAndroid Build Coastguard Worker if (string == NULL)
5142*7c568831SAndroid Build Coastguard Worker return(0);
5143*7c568831SAndroid Build Coastguard Worker if (string[0] == 0)
5144*7c568831SAndroid Build Coastguard Worker return(0);
5145*7c568831SAndroid Build Coastguard Worker return(string[0] + (string[1] << 8));
5146*7c568831SAndroid Build Coastguard Worker case XML_NAMESPACE_DECL:
5147*7c568831SAndroid Build Coastguard Worker string = ((xmlNsPtr)node)->href;
5148*7c568831SAndroid Build Coastguard Worker if (string == NULL)
5149*7c568831SAndroid Build Coastguard Worker return(0);
5150*7c568831SAndroid Build Coastguard Worker if (string[0] == 0)
5151*7c568831SAndroid Build Coastguard Worker return(0);
5152*7c568831SAndroid Build Coastguard Worker return(string[0] + (string[1] << 8));
5153*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE:
5154*7c568831SAndroid Build Coastguard Worker tmp = ((xmlAttrPtr) node)->children;
5155*7c568831SAndroid Build Coastguard Worker break;
5156*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
5157*7c568831SAndroid Build Coastguard Worker tmp = node->children;
5158*7c568831SAndroid Build Coastguard Worker break;
5159*7c568831SAndroid Build Coastguard Worker default:
5160*7c568831SAndroid Build Coastguard Worker return(0);
5161*7c568831SAndroid Build Coastguard Worker }
5162*7c568831SAndroid Build Coastguard Worker while (tmp != NULL) {
5163*7c568831SAndroid Build Coastguard Worker switch (tmp->type) {
5164*7c568831SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
5165*7c568831SAndroid Build Coastguard Worker case XML_TEXT_NODE:
5166*7c568831SAndroid Build Coastguard Worker string = tmp->content;
5167*7c568831SAndroid Build Coastguard Worker break;
5168*7c568831SAndroid Build Coastguard Worker default:
5169*7c568831SAndroid Build Coastguard Worker string = NULL;
5170*7c568831SAndroid Build Coastguard Worker break;
5171*7c568831SAndroid Build Coastguard Worker }
5172*7c568831SAndroid Build Coastguard Worker if ((string != NULL) && (string[0] != 0)) {
5173*7c568831SAndroid Build Coastguard Worker if (len == 1) {
5174*7c568831SAndroid Build Coastguard Worker return(ret + (string[0] << 8));
5175*7c568831SAndroid Build Coastguard Worker }
5176*7c568831SAndroid Build Coastguard Worker if (string[1] == 0) {
5177*7c568831SAndroid Build Coastguard Worker len = 1;
5178*7c568831SAndroid Build Coastguard Worker ret = string[0];
5179*7c568831SAndroid Build Coastguard Worker } else {
5180*7c568831SAndroid Build Coastguard Worker return(string[0] + (string[1] << 8));
5181*7c568831SAndroid Build Coastguard Worker }
5182*7c568831SAndroid Build Coastguard Worker }
5183*7c568831SAndroid Build Coastguard Worker /*
5184*7c568831SAndroid Build Coastguard Worker * Skip to next node
5185*7c568831SAndroid Build Coastguard Worker */
5186*7c568831SAndroid Build Coastguard Worker if ((tmp->children != NULL) &&
5187*7c568831SAndroid Build Coastguard Worker (tmp->type != XML_DTD_NODE) &&
5188*7c568831SAndroid Build Coastguard Worker (tmp->type != XML_ENTITY_REF_NODE) &&
5189*7c568831SAndroid Build Coastguard Worker (tmp->children->type != XML_ENTITY_DECL)) {
5190*7c568831SAndroid Build Coastguard Worker tmp = tmp->children;
5191*7c568831SAndroid Build Coastguard Worker continue;
5192*7c568831SAndroid Build Coastguard Worker }
5193*7c568831SAndroid Build Coastguard Worker if (tmp == node)
5194*7c568831SAndroid Build Coastguard Worker break;
5195*7c568831SAndroid Build Coastguard Worker
5196*7c568831SAndroid Build Coastguard Worker if (tmp->next != NULL) {
5197*7c568831SAndroid Build Coastguard Worker tmp = tmp->next;
5198*7c568831SAndroid Build Coastguard Worker continue;
5199*7c568831SAndroid Build Coastguard Worker }
5200*7c568831SAndroid Build Coastguard Worker
5201*7c568831SAndroid Build Coastguard Worker do {
5202*7c568831SAndroid Build Coastguard Worker tmp = tmp->parent;
5203*7c568831SAndroid Build Coastguard Worker if (tmp == NULL)
5204*7c568831SAndroid Build Coastguard Worker break;
5205*7c568831SAndroid Build Coastguard Worker if (tmp == node) {
5206*7c568831SAndroid Build Coastguard Worker tmp = NULL;
5207*7c568831SAndroid Build Coastguard Worker break;
5208*7c568831SAndroid Build Coastguard Worker }
5209*7c568831SAndroid Build Coastguard Worker if (tmp->next != NULL) {
5210*7c568831SAndroid Build Coastguard Worker tmp = tmp->next;
5211*7c568831SAndroid Build Coastguard Worker break;
5212*7c568831SAndroid Build Coastguard Worker }
5213*7c568831SAndroid Build Coastguard Worker } while (tmp != NULL);
5214*7c568831SAndroid Build Coastguard Worker }
5215*7c568831SAndroid Build Coastguard Worker return(ret);
5216*7c568831SAndroid Build Coastguard Worker }
5217*7c568831SAndroid Build Coastguard Worker
5218*7c568831SAndroid Build Coastguard Worker /**
5219*7c568831SAndroid Build Coastguard Worker * xmlXPathStringHash:
5220*7c568831SAndroid Build Coastguard Worker * @string: a string
5221*7c568831SAndroid Build Coastguard Worker *
5222*7c568831SAndroid Build Coastguard Worker * Function computing the beginning of the string value of the node,
5223*7c568831SAndroid Build Coastguard Worker * used to speed up comparisons
5224*7c568831SAndroid Build Coastguard Worker *
5225*7c568831SAndroid Build Coastguard Worker * Returns an int usable as a hash
5226*7c568831SAndroid Build Coastguard Worker */
5227*7c568831SAndroid Build Coastguard Worker static unsigned int
xmlXPathStringHash(const xmlChar * string)5228*7c568831SAndroid Build Coastguard Worker xmlXPathStringHash(const xmlChar * string) {
5229*7c568831SAndroid Build Coastguard Worker if (string == NULL)
5230*7c568831SAndroid Build Coastguard Worker return(0);
5231*7c568831SAndroid Build Coastguard Worker if (string[0] == 0)
5232*7c568831SAndroid Build Coastguard Worker return(0);
5233*7c568831SAndroid Build Coastguard Worker return(string[0] + (string[1] << 8));
5234*7c568831SAndroid Build Coastguard Worker }
5235*7c568831SAndroid Build Coastguard Worker
5236*7c568831SAndroid Build Coastguard Worker /**
5237*7c568831SAndroid Build Coastguard Worker * xmlXPathCompareNodeSetFloat:
5238*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
5239*7c568831SAndroid Build Coastguard Worker * @inf: less than (1) or greater than (0)
5240*7c568831SAndroid Build Coastguard Worker * @strict: is the comparison strict
5241*7c568831SAndroid Build Coastguard Worker * @arg: the node set
5242*7c568831SAndroid Build Coastguard Worker * @f: the value
5243*7c568831SAndroid Build Coastguard Worker *
5244*7c568831SAndroid Build Coastguard Worker * Implement the compare operation between a nodeset and a number
5245*7c568831SAndroid Build Coastguard Worker * @ns < @val (1, 1, ...
5246*7c568831SAndroid Build Coastguard Worker * @ns <= @val (1, 0, ...
5247*7c568831SAndroid Build Coastguard Worker * @ns > @val (0, 1, ...
5248*7c568831SAndroid Build Coastguard Worker * @ns >= @val (0, 0, ...
5249*7c568831SAndroid Build Coastguard Worker *
5250*7c568831SAndroid Build Coastguard Worker * If one object to be compared is a node-set and the other is a number,
5251*7c568831SAndroid Build Coastguard Worker * then the comparison will be true if and only if there is a node in the
5252*7c568831SAndroid Build Coastguard Worker * node-set such that the result of performing the comparison on the number
5253*7c568831SAndroid Build Coastguard Worker * to be compared and on the result of converting the string-value of that
5254*7c568831SAndroid Build Coastguard Worker * node to a number using the number function is true.
5255*7c568831SAndroid Build Coastguard Worker *
5256*7c568831SAndroid Build Coastguard Worker * Returns 0 or 1 depending on the results of the test.
5257*7c568831SAndroid Build Coastguard Worker */
5258*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCompareNodeSetFloat(xmlXPathParserContextPtr ctxt,int inf,int strict,xmlXPathObjectPtr arg,xmlXPathObjectPtr f)5259*7c568831SAndroid Build Coastguard Worker xmlXPathCompareNodeSetFloat(xmlXPathParserContextPtr ctxt, int inf, int strict,
5260*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr arg, xmlXPathObjectPtr f) {
5261*7c568831SAndroid Build Coastguard Worker int i, ret = 0;
5262*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr ns;
5263*7c568831SAndroid Build Coastguard Worker xmlChar *str2;
5264*7c568831SAndroid Build Coastguard Worker
5265*7c568831SAndroid Build Coastguard Worker if ((f == NULL) || (arg == NULL) ||
5266*7c568831SAndroid Build Coastguard Worker ((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE))) {
5267*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg);
5268*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, f);
5269*7c568831SAndroid Build Coastguard Worker return(0);
5270*7c568831SAndroid Build Coastguard Worker }
5271*7c568831SAndroid Build Coastguard Worker ns = arg->nodesetval;
5272*7c568831SAndroid Build Coastguard Worker if (ns != NULL) {
5273*7c568831SAndroid Build Coastguard Worker for (i = 0;i < ns->nodeNr;i++) {
5274*7c568831SAndroid Build Coastguard Worker str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
5275*7c568831SAndroid Build Coastguard Worker if (str2 != NULL) {
5276*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewString(ctxt, str2));
5277*7c568831SAndroid Build Coastguard Worker xmlFree(str2);
5278*7c568831SAndroid Build Coastguard Worker xmlXPathNumberFunction(ctxt, 1);
5279*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt, f));
5280*7c568831SAndroid Build Coastguard Worker ret = xmlXPathCompareValues(ctxt, inf, strict);
5281*7c568831SAndroid Build Coastguard Worker if (ret)
5282*7c568831SAndroid Build Coastguard Worker break;
5283*7c568831SAndroid Build Coastguard Worker } else {
5284*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
5285*7c568831SAndroid Build Coastguard Worker }
5286*7c568831SAndroid Build Coastguard Worker }
5287*7c568831SAndroid Build Coastguard Worker }
5288*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg);
5289*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, f);
5290*7c568831SAndroid Build Coastguard Worker return(ret);
5291*7c568831SAndroid Build Coastguard Worker }
5292*7c568831SAndroid Build Coastguard Worker
5293*7c568831SAndroid Build Coastguard Worker /**
5294*7c568831SAndroid Build Coastguard Worker * xmlXPathCompareNodeSetString:
5295*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
5296*7c568831SAndroid Build Coastguard Worker * @inf: less than (1) or greater than (0)
5297*7c568831SAndroid Build Coastguard Worker * @strict: is the comparison strict
5298*7c568831SAndroid Build Coastguard Worker * @arg: the node set
5299*7c568831SAndroid Build Coastguard Worker * @s: the value
5300*7c568831SAndroid Build Coastguard Worker *
5301*7c568831SAndroid Build Coastguard Worker * Implement the compare operation between a nodeset and a string
5302*7c568831SAndroid Build Coastguard Worker * @ns < @val (1, 1, ...
5303*7c568831SAndroid Build Coastguard Worker * @ns <= @val (1, 0, ...
5304*7c568831SAndroid Build Coastguard Worker * @ns > @val (0, 1, ...
5305*7c568831SAndroid Build Coastguard Worker * @ns >= @val (0, 0, ...
5306*7c568831SAndroid Build Coastguard Worker *
5307*7c568831SAndroid Build Coastguard Worker * If one object to be compared is a node-set and the other is a string,
5308*7c568831SAndroid Build Coastguard Worker * then the comparison will be true if and only if there is a node in
5309*7c568831SAndroid Build Coastguard Worker * the node-set such that the result of performing the comparison on the
5310*7c568831SAndroid Build Coastguard Worker * string-value of the node and the other string is true.
5311*7c568831SAndroid Build Coastguard Worker *
5312*7c568831SAndroid Build Coastguard Worker * Returns 0 or 1 depending on the results of the test.
5313*7c568831SAndroid Build Coastguard Worker */
5314*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCompareNodeSetString(xmlXPathParserContextPtr ctxt,int inf,int strict,xmlXPathObjectPtr arg,xmlXPathObjectPtr s)5315*7c568831SAndroid Build Coastguard Worker xmlXPathCompareNodeSetString(xmlXPathParserContextPtr ctxt, int inf, int strict,
5316*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr arg, xmlXPathObjectPtr s) {
5317*7c568831SAndroid Build Coastguard Worker int i, ret = 0;
5318*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr ns;
5319*7c568831SAndroid Build Coastguard Worker xmlChar *str2;
5320*7c568831SAndroid Build Coastguard Worker
5321*7c568831SAndroid Build Coastguard Worker if ((s == NULL) || (arg == NULL) ||
5322*7c568831SAndroid Build Coastguard Worker ((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE))) {
5323*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg);
5324*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, s);
5325*7c568831SAndroid Build Coastguard Worker return(0);
5326*7c568831SAndroid Build Coastguard Worker }
5327*7c568831SAndroid Build Coastguard Worker ns = arg->nodesetval;
5328*7c568831SAndroid Build Coastguard Worker if (ns != NULL) {
5329*7c568831SAndroid Build Coastguard Worker for (i = 0;i < ns->nodeNr;i++) {
5330*7c568831SAndroid Build Coastguard Worker str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
5331*7c568831SAndroid Build Coastguard Worker if (str2 != NULL) {
5332*7c568831SAndroid Build Coastguard Worker valuePush(ctxt,
5333*7c568831SAndroid Build Coastguard Worker xmlXPathCacheNewString(ctxt, str2));
5334*7c568831SAndroid Build Coastguard Worker xmlFree(str2);
5335*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt, s));
5336*7c568831SAndroid Build Coastguard Worker ret = xmlXPathCompareValues(ctxt, inf, strict);
5337*7c568831SAndroid Build Coastguard Worker if (ret)
5338*7c568831SAndroid Build Coastguard Worker break;
5339*7c568831SAndroid Build Coastguard Worker } else {
5340*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
5341*7c568831SAndroid Build Coastguard Worker }
5342*7c568831SAndroid Build Coastguard Worker }
5343*7c568831SAndroid Build Coastguard Worker }
5344*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg);
5345*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, s);
5346*7c568831SAndroid Build Coastguard Worker return(ret);
5347*7c568831SAndroid Build Coastguard Worker }
5348*7c568831SAndroid Build Coastguard Worker
5349*7c568831SAndroid Build Coastguard Worker /**
5350*7c568831SAndroid Build Coastguard Worker * xmlXPathCompareNodeSets:
5351*7c568831SAndroid Build Coastguard Worker * @inf: less than (1) or greater than (0)
5352*7c568831SAndroid Build Coastguard Worker * @strict: is the comparison strict
5353*7c568831SAndroid Build Coastguard Worker * @arg1: the first node set object
5354*7c568831SAndroid Build Coastguard Worker * @arg2: the second node set object
5355*7c568831SAndroid Build Coastguard Worker *
5356*7c568831SAndroid Build Coastguard Worker * Implement the compare operation on nodesets:
5357*7c568831SAndroid Build Coastguard Worker *
5358*7c568831SAndroid Build Coastguard Worker * If both objects to be compared are node-sets, then the comparison
5359*7c568831SAndroid Build Coastguard Worker * will be true if and only if there is a node in the first node-set
5360*7c568831SAndroid Build Coastguard Worker * and a node in the second node-set such that the result of performing
5361*7c568831SAndroid Build Coastguard Worker * the comparison on the string-values of the two nodes is true.
5362*7c568831SAndroid Build Coastguard Worker * ....
5363*7c568831SAndroid Build Coastguard Worker * When neither object to be compared is a node-set and the operator
5364*7c568831SAndroid Build Coastguard Worker * is <=, <, >= or >, then the objects are compared by converting both
5365*7c568831SAndroid Build Coastguard Worker * objects to numbers and comparing the numbers according to IEEE 754.
5366*7c568831SAndroid Build Coastguard Worker * ....
5367*7c568831SAndroid Build Coastguard Worker * The number function converts its argument to a number as follows:
5368*7c568831SAndroid Build Coastguard Worker * - a string that consists of optional whitespace followed by an
5369*7c568831SAndroid Build Coastguard Worker * optional minus sign followed by a Number followed by whitespace
5370*7c568831SAndroid Build Coastguard Worker * is converted to the IEEE 754 number that is nearest (according
5371*7c568831SAndroid Build Coastguard Worker * to the IEEE 754 round-to-nearest rule) to the mathematical value
5372*7c568831SAndroid Build Coastguard Worker * represented by the string; any other string is converted to NaN
5373*7c568831SAndroid Build Coastguard Worker *
5374*7c568831SAndroid Build Coastguard Worker * Conclusion all nodes need to be converted first to their string value
5375*7c568831SAndroid Build Coastguard Worker * and then the comparison must be done when possible
5376*7c568831SAndroid Build Coastguard Worker */
5377*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCompareNodeSets(xmlXPathParserContextPtr ctxt,int inf,int strict,xmlXPathObjectPtr arg1,xmlXPathObjectPtr arg2)5378*7c568831SAndroid Build Coastguard Worker xmlXPathCompareNodeSets(xmlXPathParserContextPtr ctxt, int inf, int strict,
5379*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2) {
5380*7c568831SAndroid Build Coastguard Worker int i, j, init = 0;
5381*7c568831SAndroid Build Coastguard Worker double val1;
5382*7c568831SAndroid Build Coastguard Worker double *values2;
5383*7c568831SAndroid Build Coastguard Worker int ret = 0;
5384*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr ns1;
5385*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr ns2;
5386*7c568831SAndroid Build Coastguard Worker
5387*7c568831SAndroid Build Coastguard Worker if ((arg1 == NULL) ||
5388*7c568831SAndroid Build Coastguard Worker ((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE))) {
5389*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(arg2);
5390*7c568831SAndroid Build Coastguard Worker return(0);
5391*7c568831SAndroid Build Coastguard Worker }
5392*7c568831SAndroid Build Coastguard Worker if ((arg2 == NULL) ||
5393*7c568831SAndroid Build Coastguard Worker ((arg2->type != XPATH_NODESET) && (arg2->type != XPATH_XSLT_TREE))) {
5394*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(arg1);
5395*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(arg2);
5396*7c568831SAndroid Build Coastguard Worker return(0);
5397*7c568831SAndroid Build Coastguard Worker }
5398*7c568831SAndroid Build Coastguard Worker
5399*7c568831SAndroid Build Coastguard Worker ns1 = arg1->nodesetval;
5400*7c568831SAndroid Build Coastguard Worker ns2 = arg2->nodesetval;
5401*7c568831SAndroid Build Coastguard Worker
5402*7c568831SAndroid Build Coastguard Worker if ((ns1 == NULL) || (ns1->nodeNr <= 0)) {
5403*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(arg1);
5404*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(arg2);
5405*7c568831SAndroid Build Coastguard Worker return(0);
5406*7c568831SAndroid Build Coastguard Worker }
5407*7c568831SAndroid Build Coastguard Worker if ((ns2 == NULL) || (ns2->nodeNr <= 0)) {
5408*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(arg1);
5409*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(arg2);
5410*7c568831SAndroid Build Coastguard Worker return(0);
5411*7c568831SAndroid Build Coastguard Worker }
5412*7c568831SAndroid Build Coastguard Worker
5413*7c568831SAndroid Build Coastguard Worker values2 = (double *) xmlMalloc(ns2->nodeNr * sizeof(double));
5414*7c568831SAndroid Build Coastguard Worker if (values2 == NULL) {
5415*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
5416*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(arg1);
5417*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(arg2);
5418*7c568831SAndroid Build Coastguard Worker return(0);
5419*7c568831SAndroid Build Coastguard Worker }
5420*7c568831SAndroid Build Coastguard Worker for (i = 0;i < ns1->nodeNr;i++) {
5421*7c568831SAndroid Build Coastguard Worker val1 = xmlXPathNodeToNumberInternal(ctxt, ns1->nodeTab[i]);
5422*7c568831SAndroid Build Coastguard Worker if (xmlXPathIsNaN(val1))
5423*7c568831SAndroid Build Coastguard Worker continue;
5424*7c568831SAndroid Build Coastguard Worker for (j = 0;j < ns2->nodeNr;j++) {
5425*7c568831SAndroid Build Coastguard Worker if (init == 0) {
5426*7c568831SAndroid Build Coastguard Worker values2[j] = xmlXPathNodeToNumberInternal(ctxt,
5427*7c568831SAndroid Build Coastguard Worker ns2->nodeTab[j]);
5428*7c568831SAndroid Build Coastguard Worker }
5429*7c568831SAndroid Build Coastguard Worker if (xmlXPathIsNaN(values2[j]))
5430*7c568831SAndroid Build Coastguard Worker continue;
5431*7c568831SAndroid Build Coastguard Worker if (inf && strict)
5432*7c568831SAndroid Build Coastguard Worker ret = (val1 < values2[j]);
5433*7c568831SAndroid Build Coastguard Worker else if (inf && !strict)
5434*7c568831SAndroid Build Coastguard Worker ret = (val1 <= values2[j]);
5435*7c568831SAndroid Build Coastguard Worker else if (!inf && strict)
5436*7c568831SAndroid Build Coastguard Worker ret = (val1 > values2[j]);
5437*7c568831SAndroid Build Coastguard Worker else if (!inf && !strict)
5438*7c568831SAndroid Build Coastguard Worker ret = (val1 >= values2[j]);
5439*7c568831SAndroid Build Coastguard Worker if (ret)
5440*7c568831SAndroid Build Coastguard Worker break;
5441*7c568831SAndroid Build Coastguard Worker }
5442*7c568831SAndroid Build Coastguard Worker if (ret)
5443*7c568831SAndroid Build Coastguard Worker break;
5444*7c568831SAndroid Build Coastguard Worker init = 1;
5445*7c568831SAndroid Build Coastguard Worker }
5446*7c568831SAndroid Build Coastguard Worker xmlFree(values2);
5447*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(arg1);
5448*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(arg2);
5449*7c568831SAndroid Build Coastguard Worker return(ret);
5450*7c568831SAndroid Build Coastguard Worker }
5451*7c568831SAndroid Build Coastguard Worker
5452*7c568831SAndroid Build Coastguard Worker /**
5453*7c568831SAndroid Build Coastguard Worker * xmlXPathCompareNodeSetValue:
5454*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
5455*7c568831SAndroid Build Coastguard Worker * @inf: less than (1) or greater than (0)
5456*7c568831SAndroid Build Coastguard Worker * @strict: is the comparison strict
5457*7c568831SAndroid Build Coastguard Worker * @arg: the node set
5458*7c568831SAndroid Build Coastguard Worker * @val: the value
5459*7c568831SAndroid Build Coastguard Worker *
5460*7c568831SAndroid Build Coastguard Worker * Implement the compare operation between a nodeset and a value
5461*7c568831SAndroid Build Coastguard Worker * @ns < @val (1, 1, ...
5462*7c568831SAndroid Build Coastguard Worker * @ns <= @val (1, 0, ...
5463*7c568831SAndroid Build Coastguard Worker * @ns > @val (0, 1, ...
5464*7c568831SAndroid Build Coastguard Worker * @ns >= @val (0, 0, ...
5465*7c568831SAndroid Build Coastguard Worker *
5466*7c568831SAndroid Build Coastguard Worker * If one object to be compared is a node-set and the other is a boolean,
5467*7c568831SAndroid Build Coastguard Worker * then the comparison will be true if and only if the result of performing
5468*7c568831SAndroid Build Coastguard Worker * the comparison on the boolean and on the result of converting
5469*7c568831SAndroid Build Coastguard Worker * the node-set to a boolean using the boolean function is true.
5470*7c568831SAndroid Build Coastguard Worker *
5471*7c568831SAndroid Build Coastguard Worker * Returns 0 or 1 depending on the results of the test.
5472*7c568831SAndroid Build Coastguard Worker */
5473*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCompareNodeSetValue(xmlXPathParserContextPtr ctxt,int inf,int strict,xmlXPathObjectPtr arg,xmlXPathObjectPtr val)5474*7c568831SAndroid Build Coastguard Worker xmlXPathCompareNodeSetValue(xmlXPathParserContextPtr ctxt, int inf, int strict,
5475*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr arg, xmlXPathObjectPtr val) {
5476*7c568831SAndroid Build Coastguard Worker if ((val == NULL) || (arg == NULL) ||
5477*7c568831SAndroid Build Coastguard Worker ((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE)))
5478*7c568831SAndroid Build Coastguard Worker return(0);
5479*7c568831SAndroid Build Coastguard Worker
5480*7c568831SAndroid Build Coastguard Worker switch(val->type) {
5481*7c568831SAndroid Build Coastguard Worker case XPATH_NUMBER:
5482*7c568831SAndroid Build Coastguard Worker return(xmlXPathCompareNodeSetFloat(ctxt, inf, strict, arg, val));
5483*7c568831SAndroid Build Coastguard Worker case XPATH_NODESET:
5484*7c568831SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
5485*7c568831SAndroid Build Coastguard Worker return(xmlXPathCompareNodeSets(ctxt, inf, strict, arg, val));
5486*7c568831SAndroid Build Coastguard Worker case XPATH_STRING:
5487*7c568831SAndroid Build Coastguard Worker return(xmlXPathCompareNodeSetString(ctxt, inf, strict, arg, val));
5488*7c568831SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
5489*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, arg);
5490*7c568831SAndroid Build Coastguard Worker xmlXPathBooleanFunction(ctxt, 1);
5491*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, val);
5492*7c568831SAndroid Build Coastguard Worker return(xmlXPathCompareValues(ctxt, inf, strict));
5493*7c568831SAndroid Build Coastguard Worker default:
5494*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg);
5495*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, val);
5496*7c568831SAndroid Build Coastguard Worker XP_ERROR0(XPATH_INVALID_TYPE);
5497*7c568831SAndroid Build Coastguard Worker }
5498*7c568831SAndroid Build Coastguard Worker return(0);
5499*7c568831SAndroid Build Coastguard Worker }
5500*7c568831SAndroid Build Coastguard Worker
5501*7c568831SAndroid Build Coastguard Worker /**
5502*7c568831SAndroid Build Coastguard Worker * xmlXPathEqualNodeSetString:
5503*7c568831SAndroid Build Coastguard Worker * @arg: the nodeset object argument
5504*7c568831SAndroid Build Coastguard Worker * @str: the string to compare to.
5505*7c568831SAndroid Build Coastguard Worker * @neq: flag to show whether for '=' (0) or '!=' (1)
5506*7c568831SAndroid Build Coastguard Worker *
5507*7c568831SAndroid Build Coastguard Worker * Implement the equal operation on XPath objects content: @arg1 == @arg2
5508*7c568831SAndroid Build Coastguard Worker * If one object to be compared is a node-set and the other is a string,
5509*7c568831SAndroid Build Coastguard Worker * then the comparison will be true if and only if there is a node in
5510*7c568831SAndroid Build Coastguard Worker * the node-set such that the result of performing the comparison on the
5511*7c568831SAndroid Build Coastguard Worker * string-value of the node and the other string is true.
5512*7c568831SAndroid Build Coastguard Worker *
5513*7c568831SAndroid Build Coastguard Worker * Returns 0 or 1 depending on the results of the test.
5514*7c568831SAndroid Build Coastguard Worker */
5515*7c568831SAndroid Build Coastguard Worker static int
xmlXPathEqualNodeSetString(xmlXPathParserContextPtr ctxt,xmlXPathObjectPtr arg,const xmlChar * str,int neq)5516*7c568831SAndroid Build Coastguard Worker xmlXPathEqualNodeSetString(xmlXPathParserContextPtr ctxt,
5517*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr arg, const xmlChar * str, int neq)
5518*7c568831SAndroid Build Coastguard Worker {
5519*7c568831SAndroid Build Coastguard Worker int i;
5520*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr ns;
5521*7c568831SAndroid Build Coastguard Worker xmlChar *str2;
5522*7c568831SAndroid Build Coastguard Worker unsigned int hash;
5523*7c568831SAndroid Build Coastguard Worker
5524*7c568831SAndroid Build Coastguard Worker if ((str == NULL) || (arg == NULL) ||
5525*7c568831SAndroid Build Coastguard Worker ((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE)))
5526*7c568831SAndroid Build Coastguard Worker return (0);
5527*7c568831SAndroid Build Coastguard Worker ns = arg->nodesetval;
5528*7c568831SAndroid Build Coastguard Worker /*
5529*7c568831SAndroid Build Coastguard Worker * A NULL nodeset compared with a string is always false
5530*7c568831SAndroid Build Coastguard Worker * (since there is no node equal, and no node not equal)
5531*7c568831SAndroid Build Coastguard Worker */
5532*7c568831SAndroid Build Coastguard Worker if ((ns == NULL) || (ns->nodeNr <= 0) )
5533*7c568831SAndroid Build Coastguard Worker return (0);
5534*7c568831SAndroid Build Coastguard Worker hash = xmlXPathStringHash(str);
5535*7c568831SAndroid Build Coastguard Worker for (i = 0; i < ns->nodeNr; i++) {
5536*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeValHash(ns->nodeTab[i]) == hash) {
5537*7c568831SAndroid Build Coastguard Worker str2 = xmlNodeGetContent(ns->nodeTab[i]);
5538*7c568831SAndroid Build Coastguard Worker if (str2 == NULL) {
5539*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
5540*7c568831SAndroid Build Coastguard Worker return(0);
5541*7c568831SAndroid Build Coastguard Worker }
5542*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(str, str2)) {
5543*7c568831SAndroid Build Coastguard Worker xmlFree(str2);
5544*7c568831SAndroid Build Coastguard Worker if (neq)
5545*7c568831SAndroid Build Coastguard Worker continue;
5546*7c568831SAndroid Build Coastguard Worker return (1);
5547*7c568831SAndroid Build Coastguard Worker } else if (neq) {
5548*7c568831SAndroid Build Coastguard Worker xmlFree(str2);
5549*7c568831SAndroid Build Coastguard Worker return (1);
5550*7c568831SAndroid Build Coastguard Worker }
5551*7c568831SAndroid Build Coastguard Worker xmlFree(str2);
5552*7c568831SAndroid Build Coastguard Worker } else if (neq)
5553*7c568831SAndroid Build Coastguard Worker return (1);
5554*7c568831SAndroid Build Coastguard Worker }
5555*7c568831SAndroid Build Coastguard Worker return (0);
5556*7c568831SAndroid Build Coastguard Worker }
5557*7c568831SAndroid Build Coastguard Worker
5558*7c568831SAndroid Build Coastguard Worker /**
5559*7c568831SAndroid Build Coastguard Worker * xmlXPathEqualNodeSetFloat:
5560*7c568831SAndroid Build Coastguard Worker * @arg: the nodeset object argument
5561*7c568831SAndroid Build Coastguard Worker * @f: the float to compare to
5562*7c568831SAndroid Build Coastguard Worker * @neq: flag to show whether to compare '=' (0) or '!=' (1)
5563*7c568831SAndroid Build Coastguard Worker *
5564*7c568831SAndroid Build Coastguard Worker * Implement the equal operation on XPath objects content: @arg1 == @arg2
5565*7c568831SAndroid Build Coastguard Worker * If one object to be compared is a node-set and the other is a number,
5566*7c568831SAndroid Build Coastguard Worker * then the comparison will be true if and only if there is a node in
5567*7c568831SAndroid Build Coastguard Worker * the node-set such that the result of performing the comparison on the
5568*7c568831SAndroid Build Coastguard Worker * number to be compared and on the result of converting the string-value
5569*7c568831SAndroid Build Coastguard Worker * of that node to a number using the number function is true.
5570*7c568831SAndroid Build Coastguard Worker *
5571*7c568831SAndroid Build Coastguard Worker * Returns 0 or 1 depending on the results of the test.
5572*7c568831SAndroid Build Coastguard Worker */
5573*7c568831SAndroid Build Coastguard Worker static int
xmlXPathEqualNodeSetFloat(xmlXPathParserContextPtr ctxt,xmlXPathObjectPtr arg,double f,int neq)5574*7c568831SAndroid Build Coastguard Worker xmlXPathEqualNodeSetFloat(xmlXPathParserContextPtr ctxt,
5575*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr arg, double f, int neq) {
5576*7c568831SAndroid Build Coastguard Worker int i, ret=0;
5577*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr ns;
5578*7c568831SAndroid Build Coastguard Worker xmlChar *str2;
5579*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr val;
5580*7c568831SAndroid Build Coastguard Worker double v;
5581*7c568831SAndroid Build Coastguard Worker
5582*7c568831SAndroid Build Coastguard Worker if ((arg == NULL) ||
5583*7c568831SAndroid Build Coastguard Worker ((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE)))
5584*7c568831SAndroid Build Coastguard Worker return(0);
5585*7c568831SAndroid Build Coastguard Worker
5586*7c568831SAndroid Build Coastguard Worker ns = arg->nodesetval;
5587*7c568831SAndroid Build Coastguard Worker if (ns != NULL) {
5588*7c568831SAndroid Build Coastguard Worker for (i=0;i<ns->nodeNr;i++) {
5589*7c568831SAndroid Build Coastguard Worker str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
5590*7c568831SAndroid Build Coastguard Worker if (str2 != NULL) {
5591*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewString(ctxt, str2));
5592*7c568831SAndroid Build Coastguard Worker xmlFree(str2);
5593*7c568831SAndroid Build Coastguard Worker xmlXPathNumberFunction(ctxt, 1);
5594*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
5595*7c568831SAndroid Build Coastguard Worker val = valuePop(ctxt);
5596*7c568831SAndroid Build Coastguard Worker v = val->floatval;
5597*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, val);
5598*7c568831SAndroid Build Coastguard Worker if (!xmlXPathIsNaN(v)) {
5599*7c568831SAndroid Build Coastguard Worker if ((!neq) && (v==f)) {
5600*7c568831SAndroid Build Coastguard Worker ret = 1;
5601*7c568831SAndroid Build Coastguard Worker break;
5602*7c568831SAndroid Build Coastguard Worker } else if ((neq) && (v!=f)) {
5603*7c568831SAndroid Build Coastguard Worker ret = 1;
5604*7c568831SAndroid Build Coastguard Worker break;
5605*7c568831SAndroid Build Coastguard Worker }
5606*7c568831SAndroid Build Coastguard Worker } else { /* NaN is unequal to any value */
5607*7c568831SAndroid Build Coastguard Worker if (neq)
5608*7c568831SAndroid Build Coastguard Worker ret = 1;
5609*7c568831SAndroid Build Coastguard Worker }
5610*7c568831SAndroid Build Coastguard Worker } else {
5611*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
5612*7c568831SAndroid Build Coastguard Worker }
5613*7c568831SAndroid Build Coastguard Worker }
5614*7c568831SAndroid Build Coastguard Worker }
5615*7c568831SAndroid Build Coastguard Worker
5616*7c568831SAndroid Build Coastguard Worker return(ret);
5617*7c568831SAndroid Build Coastguard Worker }
5618*7c568831SAndroid Build Coastguard Worker
5619*7c568831SAndroid Build Coastguard Worker
5620*7c568831SAndroid Build Coastguard Worker /**
5621*7c568831SAndroid Build Coastguard Worker * xmlXPathEqualNodeSets:
5622*7c568831SAndroid Build Coastguard Worker * @arg1: first nodeset object argument
5623*7c568831SAndroid Build Coastguard Worker * @arg2: second nodeset object argument
5624*7c568831SAndroid Build Coastguard Worker * @neq: flag to show whether to test '=' (0) or '!=' (1)
5625*7c568831SAndroid Build Coastguard Worker *
5626*7c568831SAndroid Build Coastguard Worker * Implement the equal / not equal operation on XPath nodesets:
5627*7c568831SAndroid Build Coastguard Worker * @arg1 == @arg2 or @arg1 != @arg2
5628*7c568831SAndroid Build Coastguard Worker * If both objects to be compared are node-sets, then the comparison
5629*7c568831SAndroid Build Coastguard Worker * will be true if and only if there is a node in the first node-set and
5630*7c568831SAndroid Build Coastguard Worker * a node in the second node-set such that the result of performing the
5631*7c568831SAndroid Build Coastguard Worker * comparison on the string-values of the two nodes is true.
5632*7c568831SAndroid Build Coastguard Worker *
5633*7c568831SAndroid Build Coastguard Worker * (needless to say, this is a costly operation)
5634*7c568831SAndroid Build Coastguard Worker *
5635*7c568831SAndroid Build Coastguard Worker * Returns 0 or 1 depending on the results of the test.
5636*7c568831SAndroid Build Coastguard Worker */
5637*7c568831SAndroid Build Coastguard Worker static int
xmlXPathEqualNodeSets(xmlXPathParserContextPtr ctxt,xmlXPathObjectPtr arg1,xmlXPathObjectPtr arg2,int neq)5638*7c568831SAndroid Build Coastguard Worker xmlXPathEqualNodeSets(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr arg1,
5639*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr arg2, int neq) {
5640*7c568831SAndroid Build Coastguard Worker int i, j;
5641*7c568831SAndroid Build Coastguard Worker unsigned int *hashs1;
5642*7c568831SAndroid Build Coastguard Worker unsigned int *hashs2;
5643*7c568831SAndroid Build Coastguard Worker xmlChar **values1;
5644*7c568831SAndroid Build Coastguard Worker xmlChar **values2;
5645*7c568831SAndroid Build Coastguard Worker int ret = 0;
5646*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr ns1;
5647*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr ns2;
5648*7c568831SAndroid Build Coastguard Worker
5649*7c568831SAndroid Build Coastguard Worker if ((arg1 == NULL) ||
5650*7c568831SAndroid Build Coastguard Worker ((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE)))
5651*7c568831SAndroid Build Coastguard Worker return(0);
5652*7c568831SAndroid Build Coastguard Worker if ((arg2 == NULL) ||
5653*7c568831SAndroid Build Coastguard Worker ((arg2->type != XPATH_NODESET) && (arg2->type != XPATH_XSLT_TREE)))
5654*7c568831SAndroid Build Coastguard Worker return(0);
5655*7c568831SAndroid Build Coastguard Worker
5656*7c568831SAndroid Build Coastguard Worker ns1 = arg1->nodesetval;
5657*7c568831SAndroid Build Coastguard Worker ns2 = arg2->nodesetval;
5658*7c568831SAndroid Build Coastguard Worker
5659*7c568831SAndroid Build Coastguard Worker if ((ns1 == NULL) || (ns1->nodeNr <= 0))
5660*7c568831SAndroid Build Coastguard Worker return(0);
5661*7c568831SAndroid Build Coastguard Worker if ((ns2 == NULL) || (ns2->nodeNr <= 0))
5662*7c568831SAndroid Build Coastguard Worker return(0);
5663*7c568831SAndroid Build Coastguard Worker
5664*7c568831SAndroid Build Coastguard Worker /*
5665*7c568831SAndroid Build Coastguard Worker * for equal, check if there is a node pertaining to both sets
5666*7c568831SAndroid Build Coastguard Worker */
5667*7c568831SAndroid Build Coastguard Worker if (neq == 0)
5668*7c568831SAndroid Build Coastguard Worker for (i = 0;i < ns1->nodeNr;i++)
5669*7c568831SAndroid Build Coastguard Worker for (j = 0;j < ns2->nodeNr;j++)
5670*7c568831SAndroid Build Coastguard Worker if (ns1->nodeTab[i] == ns2->nodeTab[j])
5671*7c568831SAndroid Build Coastguard Worker return(1);
5672*7c568831SAndroid Build Coastguard Worker
5673*7c568831SAndroid Build Coastguard Worker values1 = (xmlChar **) xmlMalloc(ns1->nodeNr * sizeof(xmlChar *));
5674*7c568831SAndroid Build Coastguard Worker if (values1 == NULL) {
5675*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
5676*7c568831SAndroid Build Coastguard Worker return(0);
5677*7c568831SAndroid Build Coastguard Worker }
5678*7c568831SAndroid Build Coastguard Worker hashs1 = (unsigned int *) xmlMalloc(ns1->nodeNr * sizeof(unsigned int));
5679*7c568831SAndroid Build Coastguard Worker if (hashs1 == NULL) {
5680*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
5681*7c568831SAndroid Build Coastguard Worker xmlFree(values1);
5682*7c568831SAndroid Build Coastguard Worker return(0);
5683*7c568831SAndroid Build Coastguard Worker }
5684*7c568831SAndroid Build Coastguard Worker memset(values1, 0, ns1->nodeNr * sizeof(xmlChar *));
5685*7c568831SAndroid Build Coastguard Worker values2 = (xmlChar **) xmlMalloc(ns2->nodeNr * sizeof(xmlChar *));
5686*7c568831SAndroid Build Coastguard Worker if (values2 == NULL) {
5687*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
5688*7c568831SAndroid Build Coastguard Worker xmlFree(hashs1);
5689*7c568831SAndroid Build Coastguard Worker xmlFree(values1);
5690*7c568831SAndroid Build Coastguard Worker return(0);
5691*7c568831SAndroid Build Coastguard Worker }
5692*7c568831SAndroid Build Coastguard Worker hashs2 = (unsigned int *) xmlMalloc(ns2->nodeNr * sizeof(unsigned int));
5693*7c568831SAndroid Build Coastguard Worker if (hashs2 == NULL) {
5694*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
5695*7c568831SAndroid Build Coastguard Worker xmlFree(hashs1);
5696*7c568831SAndroid Build Coastguard Worker xmlFree(values1);
5697*7c568831SAndroid Build Coastguard Worker xmlFree(values2);
5698*7c568831SAndroid Build Coastguard Worker return(0);
5699*7c568831SAndroid Build Coastguard Worker }
5700*7c568831SAndroid Build Coastguard Worker memset(values2, 0, ns2->nodeNr * sizeof(xmlChar *));
5701*7c568831SAndroid Build Coastguard Worker for (i = 0;i < ns1->nodeNr;i++) {
5702*7c568831SAndroid Build Coastguard Worker hashs1[i] = xmlXPathNodeValHash(ns1->nodeTab[i]);
5703*7c568831SAndroid Build Coastguard Worker for (j = 0;j < ns2->nodeNr;j++) {
5704*7c568831SAndroid Build Coastguard Worker if (i == 0)
5705*7c568831SAndroid Build Coastguard Worker hashs2[j] = xmlXPathNodeValHash(ns2->nodeTab[j]);
5706*7c568831SAndroid Build Coastguard Worker if (hashs1[i] != hashs2[j]) {
5707*7c568831SAndroid Build Coastguard Worker if (neq) {
5708*7c568831SAndroid Build Coastguard Worker ret = 1;
5709*7c568831SAndroid Build Coastguard Worker break;
5710*7c568831SAndroid Build Coastguard Worker }
5711*7c568831SAndroid Build Coastguard Worker }
5712*7c568831SAndroid Build Coastguard Worker else {
5713*7c568831SAndroid Build Coastguard Worker if (values1[i] == NULL) {
5714*7c568831SAndroid Build Coastguard Worker values1[i] = xmlNodeGetContent(ns1->nodeTab[i]);
5715*7c568831SAndroid Build Coastguard Worker if (values1[i] == NULL)
5716*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
5717*7c568831SAndroid Build Coastguard Worker }
5718*7c568831SAndroid Build Coastguard Worker if (values2[j] == NULL) {
5719*7c568831SAndroid Build Coastguard Worker values2[j] = xmlNodeGetContent(ns2->nodeTab[j]);
5720*7c568831SAndroid Build Coastguard Worker if (values2[j] == NULL)
5721*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
5722*7c568831SAndroid Build Coastguard Worker }
5723*7c568831SAndroid Build Coastguard Worker ret = xmlStrEqual(values1[i], values2[j]) ^ neq;
5724*7c568831SAndroid Build Coastguard Worker if (ret)
5725*7c568831SAndroid Build Coastguard Worker break;
5726*7c568831SAndroid Build Coastguard Worker }
5727*7c568831SAndroid Build Coastguard Worker }
5728*7c568831SAndroid Build Coastguard Worker if (ret)
5729*7c568831SAndroid Build Coastguard Worker break;
5730*7c568831SAndroid Build Coastguard Worker }
5731*7c568831SAndroid Build Coastguard Worker for (i = 0;i < ns1->nodeNr;i++)
5732*7c568831SAndroid Build Coastguard Worker if (values1[i] != NULL)
5733*7c568831SAndroid Build Coastguard Worker xmlFree(values1[i]);
5734*7c568831SAndroid Build Coastguard Worker for (j = 0;j < ns2->nodeNr;j++)
5735*7c568831SAndroid Build Coastguard Worker if (values2[j] != NULL)
5736*7c568831SAndroid Build Coastguard Worker xmlFree(values2[j]);
5737*7c568831SAndroid Build Coastguard Worker xmlFree(values1);
5738*7c568831SAndroid Build Coastguard Worker xmlFree(values2);
5739*7c568831SAndroid Build Coastguard Worker xmlFree(hashs1);
5740*7c568831SAndroid Build Coastguard Worker xmlFree(hashs2);
5741*7c568831SAndroid Build Coastguard Worker return(ret);
5742*7c568831SAndroid Build Coastguard Worker }
5743*7c568831SAndroid Build Coastguard Worker
5744*7c568831SAndroid Build Coastguard Worker static int
xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt,xmlXPathObjectPtr arg1,xmlXPathObjectPtr arg2)5745*7c568831SAndroid Build Coastguard Worker xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt,
5746*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2) {
5747*7c568831SAndroid Build Coastguard Worker int ret = 0;
5748*7c568831SAndroid Build Coastguard Worker /*
5749*7c568831SAndroid Build Coastguard Worker *At this point we are assured neither arg1 nor arg2
5750*7c568831SAndroid Build Coastguard Worker *is a nodeset, so we can just pick the appropriate routine.
5751*7c568831SAndroid Build Coastguard Worker */
5752*7c568831SAndroid Build Coastguard Worker switch (arg1->type) {
5753*7c568831SAndroid Build Coastguard Worker case XPATH_UNDEFINED:
5754*7c568831SAndroid Build Coastguard Worker break;
5755*7c568831SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
5756*7c568831SAndroid Build Coastguard Worker switch (arg2->type) {
5757*7c568831SAndroid Build Coastguard Worker case XPATH_UNDEFINED:
5758*7c568831SAndroid Build Coastguard Worker break;
5759*7c568831SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
5760*7c568831SAndroid Build Coastguard Worker ret = (arg1->boolval == arg2->boolval);
5761*7c568831SAndroid Build Coastguard Worker break;
5762*7c568831SAndroid Build Coastguard Worker case XPATH_NUMBER:
5763*7c568831SAndroid Build Coastguard Worker ret = (arg1->boolval ==
5764*7c568831SAndroid Build Coastguard Worker xmlXPathCastNumberToBoolean(arg2->floatval));
5765*7c568831SAndroid Build Coastguard Worker break;
5766*7c568831SAndroid Build Coastguard Worker case XPATH_STRING:
5767*7c568831SAndroid Build Coastguard Worker if ((arg2->stringval == NULL) ||
5768*7c568831SAndroid Build Coastguard Worker (arg2->stringval[0] == 0)) ret = 0;
5769*7c568831SAndroid Build Coastguard Worker else
5770*7c568831SAndroid Build Coastguard Worker ret = 1;
5771*7c568831SAndroid Build Coastguard Worker ret = (arg1->boolval == ret);
5772*7c568831SAndroid Build Coastguard Worker break;
5773*7c568831SAndroid Build Coastguard Worker case XPATH_USERS:
5774*7c568831SAndroid Build Coastguard Worker /* TODO */
5775*7c568831SAndroid Build Coastguard Worker break;
5776*7c568831SAndroid Build Coastguard Worker case XPATH_NODESET:
5777*7c568831SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
5778*7c568831SAndroid Build Coastguard Worker break;
5779*7c568831SAndroid Build Coastguard Worker }
5780*7c568831SAndroid Build Coastguard Worker break;
5781*7c568831SAndroid Build Coastguard Worker case XPATH_NUMBER:
5782*7c568831SAndroid Build Coastguard Worker switch (arg2->type) {
5783*7c568831SAndroid Build Coastguard Worker case XPATH_UNDEFINED:
5784*7c568831SAndroid Build Coastguard Worker break;
5785*7c568831SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
5786*7c568831SAndroid Build Coastguard Worker ret = (arg2->boolval==
5787*7c568831SAndroid Build Coastguard Worker xmlXPathCastNumberToBoolean(arg1->floatval));
5788*7c568831SAndroid Build Coastguard Worker break;
5789*7c568831SAndroid Build Coastguard Worker case XPATH_STRING:
5790*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, arg2);
5791*7c568831SAndroid Build Coastguard Worker xmlXPathNumberFunction(ctxt, 1);
5792*7c568831SAndroid Build Coastguard Worker arg2 = valuePop(ctxt);
5793*7c568831SAndroid Build Coastguard Worker if (ctxt->error)
5794*7c568831SAndroid Build Coastguard Worker break;
5795*7c568831SAndroid Build Coastguard Worker /* Falls through. */
5796*7c568831SAndroid Build Coastguard Worker case XPATH_NUMBER:
5797*7c568831SAndroid Build Coastguard Worker /* Hand check NaN and Infinity equalities */
5798*7c568831SAndroid Build Coastguard Worker if (xmlXPathIsNaN(arg1->floatval) ||
5799*7c568831SAndroid Build Coastguard Worker xmlXPathIsNaN(arg2->floatval)) {
5800*7c568831SAndroid Build Coastguard Worker ret = 0;
5801*7c568831SAndroid Build Coastguard Worker } else if (xmlXPathIsInf(arg1->floatval) == 1) {
5802*7c568831SAndroid Build Coastguard Worker if (xmlXPathIsInf(arg2->floatval) == 1)
5803*7c568831SAndroid Build Coastguard Worker ret = 1;
5804*7c568831SAndroid Build Coastguard Worker else
5805*7c568831SAndroid Build Coastguard Worker ret = 0;
5806*7c568831SAndroid Build Coastguard Worker } else if (xmlXPathIsInf(arg1->floatval) == -1) {
5807*7c568831SAndroid Build Coastguard Worker if (xmlXPathIsInf(arg2->floatval) == -1)
5808*7c568831SAndroid Build Coastguard Worker ret = 1;
5809*7c568831SAndroid Build Coastguard Worker else
5810*7c568831SAndroid Build Coastguard Worker ret = 0;
5811*7c568831SAndroid Build Coastguard Worker } else if (xmlXPathIsInf(arg2->floatval) == 1) {
5812*7c568831SAndroid Build Coastguard Worker if (xmlXPathIsInf(arg1->floatval) == 1)
5813*7c568831SAndroid Build Coastguard Worker ret = 1;
5814*7c568831SAndroid Build Coastguard Worker else
5815*7c568831SAndroid Build Coastguard Worker ret = 0;
5816*7c568831SAndroid Build Coastguard Worker } else if (xmlXPathIsInf(arg2->floatval) == -1) {
5817*7c568831SAndroid Build Coastguard Worker if (xmlXPathIsInf(arg1->floatval) == -1)
5818*7c568831SAndroid Build Coastguard Worker ret = 1;
5819*7c568831SAndroid Build Coastguard Worker else
5820*7c568831SAndroid Build Coastguard Worker ret = 0;
5821*7c568831SAndroid Build Coastguard Worker } else {
5822*7c568831SAndroid Build Coastguard Worker ret = (arg1->floatval == arg2->floatval);
5823*7c568831SAndroid Build Coastguard Worker }
5824*7c568831SAndroid Build Coastguard Worker break;
5825*7c568831SAndroid Build Coastguard Worker case XPATH_USERS:
5826*7c568831SAndroid Build Coastguard Worker /* TODO */
5827*7c568831SAndroid Build Coastguard Worker break;
5828*7c568831SAndroid Build Coastguard Worker case XPATH_NODESET:
5829*7c568831SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
5830*7c568831SAndroid Build Coastguard Worker break;
5831*7c568831SAndroid Build Coastguard Worker }
5832*7c568831SAndroid Build Coastguard Worker break;
5833*7c568831SAndroid Build Coastguard Worker case XPATH_STRING:
5834*7c568831SAndroid Build Coastguard Worker switch (arg2->type) {
5835*7c568831SAndroid Build Coastguard Worker case XPATH_UNDEFINED:
5836*7c568831SAndroid Build Coastguard Worker break;
5837*7c568831SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
5838*7c568831SAndroid Build Coastguard Worker if ((arg1->stringval == NULL) ||
5839*7c568831SAndroid Build Coastguard Worker (arg1->stringval[0] == 0)) ret = 0;
5840*7c568831SAndroid Build Coastguard Worker else
5841*7c568831SAndroid Build Coastguard Worker ret = 1;
5842*7c568831SAndroid Build Coastguard Worker ret = (arg2->boolval == ret);
5843*7c568831SAndroid Build Coastguard Worker break;
5844*7c568831SAndroid Build Coastguard Worker case XPATH_STRING:
5845*7c568831SAndroid Build Coastguard Worker ret = xmlStrEqual(arg1->stringval, arg2->stringval);
5846*7c568831SAndroid Build Coastguard Worker break;
5847*7c568831SAndroid Build Coastguard Worker case XPATH_NUMBER:
5848*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, arg1);
5849*7c568831SAndroid Build Coastguard Worker xmlXPathNumberFunction(ctxt, 1);
5850*7c568831SAndroid Build Coastguard Worker arg1 = valuePop(ctxt);
5851*7c568831SAndroid Build Coastguard Worker if (ctxt->error)
5852*7c568831SAndroid Build Coastguard Worker break;
5853*7c568831SAndroid Build Coastguard Worker /* Hand check NaN and Infinity equalities */
5854*7c568831SAndroid Build Coastguard Worker if (xmlXPathIsNaN(arg1->floatval) ||
5855*7c568831SAndroid Build Coastguard Worker xmlXPathIsNaN(arg2->floatval)) {
5856*7c568831SAndroid Build Coastguard Worker ret = 0;
5857*7c568831SAndroid Build Coastguard Worker } else if (xmlXPathIsInf(arg1->floatval) == 1) {
5858*7c568831SAndroid Build Coastguard Worker if (xmlXPathIsInf(arg2->floatval) == 1)
5859*7c568831SAndroid Build Coastguard Worker ret = 1;
5860*7c568831SAndroid Build Coastguard Worker else
5861*7c568831SAndroid Build Coastguard Worker ret = 0;
5862*7c568831SAndroid Build Coastguard Worker } else if (xmlXPathIsInf(arg1->floatval) == -1) {
5863*7c568831SAndroid Build Coastguard Worker if (xmlXPathIsInf(arg2->floatval) == -1)
5864*7c568831SAndroid Build Coastguard Worker ret = 1;
5865*7c568831SAndroid Build Coastguard Worker else
5866*7c568831SAndroid Build Coastguard Worker ret = 0;
5867*7c568831SAndroid Build Coastguard Worker } else if (xmlXPathIsInf(arg2->floatval) == 1) {
5868*7c568831SAndroid Build Coastguard Worker if (xmlXPathIsInf(arg1->floatval) == 1)
5869*7c568831SAndroid Build Coastguard Worker ret = 1;
5870*7c568831SAndroid Build Coastguard Worker else
5871*7c568831SAndroid Build Coastguard Worker ret = 0;
5872*7c568831SAndroid Build Coastguard Worker } else if (xmlXPathIsInf(arg2->floatval) == -1) {
5873*7c568831SAndroid Build Coastguard Worker if (xmlXPathIsInf(arg1->floatval) == -1)
5874*7c568831SAndroid Build Coastguard Worker ret = 1;
5875*7c568831SAndroid Build Coastguard Worker else
5876*7c568831SAndroid Build Coastguard Worker ret = 0;
5877*7c568831SAndroid Build Coastguard Worker } else {
5878*7c568831SAndroid Build Coastguard Worker ret = (arg1->floatval == arg2->floatval);
5879*7c568831SAndroid Build Coastguard Worker }
5880*7c568831SAndroid Build Coastguard Worker break;
5881*7c568831SAndroid Build Coastguard Worker case XPATH_USERS:
5882*7c568831SAndroid Build Coastguard Worker /* TODO */
5883*7c568831SAndroid Build Coastguard Worker break;
5884*7c568831SAndroid Build Coastguard Worker case XPATH_NODESET:
5885*7c568831SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
5886*7c568831SAndroid Build Coastguard Worker break;
5887*7c568831SAndroid Build Coastguard Worker }
5888*7c568831SAndroid Build Coastguard Worker break;
5889*7c568831SAndroid Build Coastguard Worker case XPATH_USERS:
5890*7c568831SAndroid Build Coastguard Worker /* TODO */
5891*7c568831SAndroid Build Coastguard Worker break;
5892*7c568831SAndroid Build Coastguard Worker case XPATH_NODESET:
5893*7c568831SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
5894*7c568831SAndroid Build Coastguard Worker break;
5895*7c568831SAndroid Build Coastguard Worker }
5896*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
5897*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
5898*7c568831SAndroid Build Coastguard Worker return(ret);
5899*7c568831SAndroid Build Coastguard Worker }
5900*7c568831SAndroid Build Coastguard Worker
5901*7c568831SAndroid Build Coastguard Worker /**
5902*7c568831SAndroid Build Coastguard Worker * xmlXPathEqualValues:
5903*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
5904*7c568831SAndroid Build Coastguard Worker *
5905*7c568831SAndroid Build Coastguard Worker * Implement the equal operation on XPath objects content: @arg1 == @arg2
5906*7c568831SAndroid Build Coastguard Worker *
5907*7c568831SAndroid Build Coastguard Worker * Returns 0 or 1 depending on the results of the test.
5908*7c568831SAndroid Build Coastguard Worker */
5909*7c568831SAndroid Build Coastguard Worker int
xmlXPathEqualValues(xmlXPathParserContextPtr ctxt)5910*7c568831SAndroid Build Coastguard Worker xmlXPathEqualValues(xmlXPathParserContextPtr ctxt) {
5911*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr arg1, arg2, argtmp;
5912*7c568831SAndroid Build Coastguard Worker int ret = 0;
5913*7c568831SAndroid Build Coastguard Worker
5914*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(0);
5915*7c568831SAndroid Build Coastguard Worker arg2 = valuePop(ctxt);
5916*7c568831SAndroid Build Coastguard Worker arg1 = valuePop(ctxt);
5917*7c568831SAndroid Build Coastguard Worker if ((arg1 == NULL) || (arg2 == NULL)) {
5918*7c568831SAndroid Build Coastguard Worker if (arg1 != NULL)
5919*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
5920*7c568831SAndroid Build Coastguard Worker else
5921*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
5922*7c568831SAndroid Build Coastguard Worker XP_ERROR0(XPATH_INVALID_OPERAND);
5923*7c568831SAndroid Build Coastguard Worker }
5924*7c568831SAndroid Build Coastguard Worker
5925*7c568831SAndroid Build Coastguard Worker if (arg1 == arg2) {
5926*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(arg1);
5927*7c568831SAndroid Build Coastguard Worker return(1);
5928*7c568831SAndroid Build Coastguard Worker }
5929*7c568831SAndroid Build Coastguard Worker
5930*7c568831SAndroid Build Coastguard Worker /*
5931*7c568831SAndroid Build Coastguard Worker *If either argument is a nodeset, it's a 'special case'
5932*7c568831SAndroid Build Coastguard Worker */
5933*7c568831SAndroid Build Coastguard Worker if ((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE) ||
5934*7c568831SAndroid Build Coastguard Worker (arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
5935*7c568831SAndroid Build Coastguard Worker /*
5936*7c568831SAndroid Build Coastguard Worker *Hack it to assure arg1 is the nodeset
5937*7c568831SAndroid Build Coastguard Worker */
5938*7c568831SAndroid Build Coastguard Worker if ((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE)) {
5939*7c568831SAndroid Build Coastguard Worker argtmp = arg2;
5940*7c568831SAndroid Build Coastguard Worker arg2 = arg1;
5941*7c568831SAndroid Build Coastguard Worker arg1 = argtmp;
5942*7c568831SAndroid Build Coastguard Worker }
5943*7c568831SAndroid Build Coastguard Worker switch (arg2->type) {
5944*7c568831SAndroid Build Coastguard Worker case XPATH_UNDEFINED:
5945*7c568831SAndroid Build Coastguard Worker break;
5946*7c568831SAndroid Build Coastguard Worker case XPATH_NODESET:
5947*7c568831SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
5948*7c568831SAndroid Build Coastguard Worker ret = xmlXPathEqualNodeSets(ctxt, arg1, arg2, 0);
5949*7c568831SAndroid Build Coastguard Worker break;
5950*7c568831SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
5951*7c568831SAndroid Build Coastguard Worker if ((arg1->nodesetval == NULL) ||
5952*7c568831SAndroid Build Coastguard Worker (arg1->nodesetval->nodeNr == 0)) ret = 0;
5953*7c568831SAndroid Build Coastguard Worker else
5954*7c568831SAndroid Build Coastguard Worker ret = 1;
5955*7c568831SAndroid Build Coastguard Worker ret = (ret == arg2->boolval);
5956*7c568831SAndroid Build Coastguard Worker break;
5957*7c568831SAndroid Build Coastguard Worker case XPATH_NUMBER:
5958*7c568831SAndroid Build Coastguard Worker ret = xmlXPathEqualNodeSetFloat(ctxt, arg1, arg2->floatval, 0);
5959*7c568831SAndroid Build Coastguard Worker break;
5960*7c568831SAndroid Build Coastguard Worker case XPATH_STRING:
5961*7c568831SAndroid Build Coastguard Worker ret = xmlXPathEqualNodeSetString(ctxt, arg1,
5962*7c568831SAndroid Build Coastguard Worker arg2->stringval, 0);
5963*7c568831SAndroid Build Coastguard Worker break;
5964*7c568831SAndroid Build Coastguard Worker case XPATH_USERS:
5965*7c568831SAndroid Build Coastguard Worker /* TODO */
5966*7c568831SAndroid Build Coastguard Worker break;
5967*7c568831SAndroid Build Coastguard Worker }
5968*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
5969*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
5970*7c568831SAndroid Build Coastguard Worker return(ret);
5971*7c568831SAndroid Build Coastguard Worker }
5972*7c568831SAndroid Build Coastguard Worker
5973*7c568831SAndroid Build Coastguard Worker return (xmlXPathEqualValuesCommon(ctxt, arg1, arg2));
5974*7c568831SAndroid Build Coastguard Worker }
5975*7c568831SAndroid Build Coastguard Worker
5976*7c568831SAndroid Build Coastguard Worker /**
5977*7c568831SAndroid Build Coastguard Worker * xmlXPathNotEqualValues:
5978*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
5979*7c568831SAndroid Build Coastguard Worker *
5980*7c568831SAndroid Build Coastguard Worker * Implement the equal operation on XPath objects content: @arg1 == @arg2
5981*7c568831SAndroid Build Coastguard Worker *
5982*7c568831SAndroid Build Coastguard Worker * Returns 0 or 1 depending on the results of the test.
5983*7c568831SAndroid Build Coastguard Worker */
5984*7c568831SAndroid Build Coastguard Worker int
xmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt)5985*7c568831SAndroid Build Coastguard Worker xmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt) {
5986*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr arg1, arg2, argtmp;
5987*7c568831SAndroid Build Coastguard Worker int ret = 0;
5988*7c568831SAndroid Build Coastguard Worker
5989*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(0);
5990*7c568831SAndroid Build Coastguard Worker arg2 = valuePop(ctxt);
5991*7c568831SAndroid Build Coastguard Worker arg1 = valuePop(ctxt);
5992*7c568831SAndroid Build Coastguard Worker if ((arg1 == NULL) || (arg2 == NULL)) {
5993*7c568831SAndroid Build Coastguard Worker if (arg1 != NULL)
5994*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
5995*7c568831SAndroid Build Coastguard Worker else
5996*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
5997*7c568831SAndroid Build Coastguard Worker XP_ERROR0(XPATH_INVALID_OPERAND);
5998*7c568831SAndroid Build Coastguard Worker }
5999*7c568831SAndroid Build Coastguard Worker
6000*7c568831SAndroid Build Coastguard Worker if (arg1 == arg2) {
6001*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
6002*7c568831SAndroid Build Coastguard Worker return(0);
6003*7c568831SAndroid Build Coastguard Worker }
6004*7c568831SAndroid Build Coastguard Worker
6005*7c568831SAndroid Build Coastguard Worker /*
6006*7c568831SAndroid Build Coastguard Worker *If either argument is a nodeset, it's a 'special case'
6007*7c568831SAndroid Build Coastguard Worker */
6008*7c568831SAndroid Build Coastguard Worker if ((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE) ||
6009*7c568831SAndroid Build Coastguard Worker (arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
6010*7c568831SAndroid Build Coastguard Worker /*
6011*7c568831SAndroid Build Coastguard Worker *Hack it to assure arg1 is the nodeset
6012*7c568831SAndroid Build Coastguard Worker */
6013*7c568831SAndroid Build Coastguard Worker if ((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE)) {
6014*7c568831SAndroid Build Coastguard Worker argtmp = arg2;
6015*7c568831SAndroid Build Coastguard Worker arg2 = arg1;
6016*7c568831SAndroid Build Coastguard Worker arg1 = argtmp;
6017*7c568831SAndroid Build Coastguard Worker }
6018*7c568831SAndroid Build Coastguard Worker switch (arg2->type) {
6019*7c568831SAndroid Build Coastguard Worker case XPATH_UNDEFINED:
6020*7c568831SAndroid Build Coastguard Worker break;
6021*7c568831SAndroid Build Coastguard Worker case XPATH_NODESET:
6022*7c568831SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
6023*7c568831SAndroid Build Coastguard Worker ret = xmlXPathEqualNodeSets(ctxt, arg1, arg2, 1);
6024*7c568831SAndroid Build Coastguard Worker break;
6025*7c568831SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
6026*7c568831SAndroid Build Coastguard Worker if ((arg1->nodesetval == NULL) ||
6027*7c568831SAndroid Build Coastguard Worker (arg1->nodesetval->nodeNr == 0)) ret = 0;
6028*7c568831SAndroid Build Coastguard Worker else
6029*7c568831SAndroid Build Coastguard Worker ret = 1;
6030*7c568831SAndroid Build Coastguard Worker ret = (ret != arg2->boolval);
6031*7c568831SAndroid Build Coastguard Worker break;
6032*7c568831SAndroid Build Coastguard Worker case XPATH_NUMBER:
6033*7c568831SAndroid Build Coastguard Worker ret = xmlXPathEqualNodeSetFloat(ctxt, arg1, arg2->floatval, 1);
6034*7c568831SAndroid Build Coastguard Worker break;
6035*7c568831SAndroid Build Coastguard Worker case XPATH_STRING:
6036*7c568831SAndroid Build Coastguard Worker ret = xmlXPathEqualNodeSetString(ctxt, arg1,
6037*7c568831SAndroid Build Coastguard Worker arg2->stringval, 1);
6038*7c568831SAndroid Build Coastguard Worker break;
6039*7c568831SAndroid Build Coastguard Worker case XPATH_USERS:
6040*7c568831SAndroid Build Coastguard Worker /* TODO */
6041*7c568831SAndroid Build Coastguard Worker break;
6042*7c568831SAndroid Build Coastguard Worker }
6043*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
6044*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
6045*7c568831SAndroid Build Coastguard Worker return(ret);
6046*7c568831SAndroid Build Coastguard Worker }
6047*7c568831SAndroid Build Coastguard Worker
6048*7c568831SAndroid Build Coastguard Worker return (!xmlXPathEqualValuesCommon(ctxt, arg1, arg2));
6049*7c568831SAndroid Build Coastguard Worker }
6050*7c568831SAndroid Build Coastguard Worker
6051*7c568831SAndroid Build Coastguard Worker /**
6052*7c568831SAndroid Build Coastguard Worker * xmlXPathCompareValues:
6053*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6054*7c568831SAndroid Build Coastguard Worker * @inf: less than (1) or greater than (0)
6055*7c568831SAndroid Build Coastguard Worker * @strict: is the comparison strict
6056*7c568831SAndroid Build Coastguard Worker *
6057*7c568831SAndroid Build Coastguard Worker * Implement the compare operation on XPath objects:
6058*7c568831SAndroid Build Coastguard Worker * @arg1 < @arg2 (1, 1, ...
6059*7c568831SAndroid Build Coastguard Worker * @arg1 <= @arg2 (1, 0, ...
6060*7c568831SAndroid Build Coastguard Worker * @arg1 > @arg2 (0, 1, ...
6061*7c568831SAndroid Build Coastguard Worker * @arg1 >= @arg2 (0, 0, ...
6062*7c568831SAndroid Build Coastguard Worker *
6063*7c568831SAndroid Build Coastguard Worker * When neither object to be compared is a node-set and the operator is
6064*7c568831SAndroid Build Coastguard Worker * <=, <, >=, >, then the objects are compared by converted both objects
6065*7c568831SAndroid Build Coastguard Worker * to numbers and comparing the numbers according to IEEE 754. The <
6066*7c568831SAndroid Build Coastguard Worker * comparison will be true if and only if the first number is less than the
6067*7c568831SAndroid Build Coastguard Worker * second number. The <= comparison will be true if and only if the first
6068*7c568831SAndroid Build Coastguard Worker * number is less than or equal to the second number. The > comparison
6069*7c568831SAndroid Build Coastguard Worker * will be true if and only if the first number is greater than the second
6070*7c568831SAndroid Build Coastguard Worker * number. The >= comparison will be true if and only if the first number
6071*7c568831SAndroid Build Coastguard Worker * is greater than or equal to the second number.
6072*7c568831SAndroid Build Coastguard Worker *
6073*7c568831SAndroid Build Coastguard Worker * Returns 1 if the comparison succeeded, 0 if it failed
6074*7c568831SAndroid Build Coastguard Worker */
6075*7c568831SAndroid Build Coastguard Worker int
xmlXPathCompareValues(xmlXPathParserContextPtr ctxt,int inf,int strict)6076*7c568831SAndroid Build Coastguard Worker xmlXPathCompareValues(xmlXPathParserContextPtr ctxt, int inf, int strict) {
6077*7c568831SAndroid Build Coastguard Worker int ret = 0, arg1i = 0, arg2i = 0;
6078*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr arg1, arg2;
6079*7c568831SAndroid Build Coastguard Worker
6080*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(0);
6081*7c568831SAndroid Build Coastguard Worker arg2 = valuePop(ctxt);
6082*7c568831SAndroid Build Coastguard Worker arg1 = valuePop(ctxt);
6083*7c568831SAndroid Build Coastguard Worker if ((arg1 == NULL) || (arg2 == NULL)) {
6084*7c568831SAndroid Build Coastguard Worker if (arg1 != NULL)
6085*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
6086*7c568831SAndroid Build Coastguard Worker else
6087*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
6088*7c568831SAndroid Build Coastguard Worker XP_ERROR0(XPATH_INVALID_OPERAND);
6089*7c568831SAndroid Build Coastguard Worker }
6090*7c568831SAndroid Build Coastguard Worker
6091*7c568831SAndroid Build Coastguard Worker if ((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE) ||
6092*7c568831SAndroid Build Coastguard Worker (arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
6093*7c568831SAndroid Build Coastguard Worker /*
6094*7c568831SAndroid Build Coastguard Worker * If either argument is a XPATH_NODESET or XPATH_XSLT_TREE the two arguments
6095*7c568831SAndroid Build Coastguard Worker * are not freed from within this routine; they will be freed from the
6096*7c568831SAndroid Build Coastguard Worker * called routine, e.g. xmlXPathCompareNodeSets or xmlXPathCompareNodeSetValue
6097*7c568831SAndroid Build Coastguard Worker */
6098*7c568831SAndroid Build Coastguard Worker if (((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE)) &&
6099*7c568831SAndroid Build Coastguard Worker ((arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE))){
6100*7c568831SAndroid Build Coastguard Worker ret = xmlXPathCompareNodeSets(ctxt, inf, strict, arg1, arg2);
6101*7c568831SAndroid Build Coastguard Worker } else {
6102*7c568831SAndroid Build Coastguard Worker if ((arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
6103*7c568831SAndroid Build Coastguard Worker ret = xmlXPathCompareNodeSetValue(ctxt, inf, strict,
6104*7c568831SAndroid Build Coastguard Worker arg1, arg2);
6105*7c568831SAndroid Build Coastguard Worker } else {
6106*7c568831SAndroid Build Coastguard Worker ret = xmlXPathCompareNodeSetValue(ctxt, !inf, strict,
6107*7c568831SAndroid Build Coastguard Worker arg2, arg1);
6108*7c568831SAndroid Build Coastguard Worker }
6109*7c568831SAndroid Build Coastguard Worker }
6110*7c568831SAndroid Build Coastguard Worker return(ret);
6111*7c568831SAndroid Build Coastguard Worker }
6112*7c568831SAndroid Build Coastguard Worker
6113*7c568831SAndroid Build Coastguard Worker if (arg1->type != XPATH_NUMBER) {
6114*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, arg1);
6115*7c568831SAndroid Build Coastguard Worker xmlXPathNumberFunction(ctxt, 1);
6116*7c568831SAndroid Build Coastguard Worker arg1 = valuePop(ctxt);
6117*7c568831SAndroid Build Coastguard Worker }
6118*7c568831SAndroid Build Coastguard Worker if (arg2->type != XPATH_NUMBER) {
6119*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, arg2);
6120*7c568831SAndroid Build Coastguard Worker xmlXPathNumberFunction(ctxt, 1);
6121*7c568831SAndroid Build Coastguard Worker arg2 = valuePop(ctxt);
6122*7c568831SAndroid Build Coastguard Worker }
6123*7c568831SAndroid Build Coastguard Worker if (ctxt->error)
6124*7c568831SAndroid Build Coastguard Worker goto error;
6125*7c568831SAndroid Build Coastguard Worker /*
6126*7c568831SAndroid Build Coastguard Worker * Add tests for infinity and nan
6127*7c568831SAndroid Build Coastguard Worker * => feedback on 3.4 for Inf and NaN
6128*7c568831SAndroid Build Coastguard Worker */
6129*7c568831SAndroid Build Coastguard Worker /* Hand check NaN and Infinity comparisons */
6130*7c568831SAndroid Build Coastguard Worker if (xmlXPathIsNaN(arg1->floatval) || xmlXPathIsNaN(arg2->floatval)) {
6131*7c568831SAndroid Build Coastguard Worker ret=0;
6132*7c568831SAndroid Build Coastguard Worker } else {
6133*7c568831SAndroid Build Coastguard Worker arg1i=xmlXPathIsInf(arg1->floatval);
6134*7c568831SAndroid Build Coastguard Worker arg2i=xmlXPathIsInf(arg2->floatval);
6135*7c568831SAndroid Build Coastguard Worker if (inf && strict) {
6136*7c568831SAndroid Build Coastguard Worker if ((arg1i == -1 && arg2i != -1) ||
6137*7c568831SAndroid Build Coastguard Worker (arg2i == 1 && arg1i != 1)) {
6138*7c568831SAndroid Build Coastguard Worker ret = 1;
6139*7c568831SAndroid Build Coastguard Worker } else if (arg1i == 0 && arg2i == 0) {
6140*7c568831SAndroid Build Coastguard Worker ret = (arg1->floatval < arg2->floatval);
6141*7c568831SAndroid Build Coastguard Worker } else {
6142*7c568831SAndroid Build Coastguard Worker ret = 0;
6143*7c568831SAndroid Build Coastguard Worker }
6144*7c568831SAndroid Build Coastguard Worker }
6145*7c568831SAndroid Build Coastguard Worker else if (inf && !strict) {
6146*7c568831SAndroid Build Coastguard Worker if (arg1i == -1 || arg2i == 1) {
6147*7c568831SAndroid Build Coastguard Worker ret = 1;
6148*7c568831SAndroid Build Coastguard Worker } else if (arg1i == 0 && arg2i == 0) {
6149*7c568831SAndroid Build Coastguard Worker ret = (arg1->floatval <= arg2->floatval);
6150*7c568831SAndroid Build Coastguard Worker } else {
6151*7c568831SAndroid Build Coastguard Worker ret = 0;
6152*7c568831SAndroid Build Coastguard Worker }
6153*7c568831SAndroid Build Coastguard Worker }
6154*7c568831SAndroid Build Coastguard Worker else if (!inf && strict) {
6155*7c568831SAndroid Build Coastguard Worker if ((arg1i == 1 && arg2i != 1) ||
6156*7c568831SAndroid Build Coastguard Worker (arg2i == -1 && arg1i != -1)) {
6157*7c568831SAndroid Build Coastguard Worker ret = 1;
6158*7c568831SAndroid Build Coastguard Worker } else if (arg1i == 0 && arg2i == 0) {
6159*7c568831SAndroid Build Coastguard Worker ret = (arg1->floatval > arg2->floatval);
6160*7c568831SAndroid Build Coastguard Worker } else {
6161*7c568831SAndroid Build Coastguard Worker ret = 0;
6162*7c568831SAndroid Build Coastguard Worker }
6163*7c568831SAndroid Build Coastguard Worker }
6164*7c568831SAndroid Build Coastguard Worker else if (!inf && !strict) {
6165*7c568831SAndroid Build Coastguard Worker if (arg1i == 1 || arg2i == -1) {
6166*7c568831SAndroid Build Coastguard Worker ret = 1;
6167*7c568831SAndroid Build Coastguard Worker } else if (arg1i == 0 && arg2i == 0) {
6168*7c568831SAndroid Build Coastguard Worker ret = (arg1->floatval >= arg2->floatval);
6169*7c568831SAndroid Build Coastguard Worker } else {
6170*7c568831SAndroid Build Coastguard Worker ret = 0;
6171*7c568831SAndroid Build Coastguard Worker }
6172*7c568831SAndroid Build Coastguard Worker }
6173*7c568831SAndroid Build Coastguard Worker }
6174*7c568831SAndroid Build Coastguard Worker error:
6175*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
6176*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
6177*7c568831SAndroid Build Coastguard Worker return(ret);
6178*7c568831SAndroid Build Coastguard Worker }
6179*7c568831SAndroid Build Coastguard Worker
6180*7c568831SAndroid Build Coastguard Worker /**
6181*7c568831SAndroid Build Coastguard Worker * xmlXPathValueFlipSign:
6182*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6183*7c568831SAndroid Build Coastguard Worker *
6184*7c568831SAndroid Build Coastguard Worker * Implement the unary - operation on an XPath object
6185*7c568831SAndroid Build Coastguard Worker * The numeric operators convert their operands to numbers as if
6186*7c568831SAndroid Build Coastguard Worker * by calling the number function.
6187*7c568831SAndroid Build Coastguard Worker */
6188*7c568831SAndroid Build Coastguard Worker void
xmlXPathValueFlipSign(xmlXPathParserContextPtr ctxt)6189*7c568831SAndroid Build Coastguard Worker xmlXPathValueFlipSign(xmlXPathParserContextPtr ctxt) {
6190*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return;
6191*7c568831SAndroid Build Coastguard Worker CAST_TO_NUMBER;
6192*7c568831SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_NUMBER);
6193*7c568831SAndroid Build Coastguard Worker ctxt->value->floatval = -ctxt->value->floatval;
6194*7c568831SAndroid Build Coastguard Worker }
6195*7c568831SAndroid Build Coastguard Worker
6196*7c568831SAndroid Build Coastguard Worker /**
6197*7c568831SAndroid Build Coastguard Worker * xmlXPathAddValues:
6198*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6199*7c568831SAndroid Build Coastguard Worker *
6200*7c568831SAndroid Build Coastguard Worker * Implement the add operation on XPath objects:
6201*7c568831SAndroid Build Coastguard Worker * The numeric operators convert their operands to numbers as if
6202*7c568831SAndroid Build Coastguard Worker * by calling the number function.
6203*7c568831SAndroid Build Coastguard Worker */
6204*7c568831SAndroid Build Coastguard Worker void
xmlXPathAddValues(xmlXPathParserContextPtr ctxt)6205*7c568831SAndroid Build Coastguard Worker xmlXPathAddValues(xmlXPathParserContextPtr ctxt) {
6206*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr arg;
6207*7c568831SAndroid Build Coastguard Worker double val;
6208*7c568831SAndroid Build Coastguard Worker
6209*7c568831SAndroid Build Coastguard Worker arg = valuePop(ctxt);
6210*7c568831SAndroid Build Coastguard Worker if (arg == NULL)
6211*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_OPERAND);
6212*7c568831SAndroid Build Coastguard Worker val = xmlXPathCastToNumberInternal(ctxt, arg);
6213*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg);
6214*7c568831SAndroid Build Coastguard Worker CAST_TO_NUMBER;
6215*7c568831SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_NUMBER);
6216*7c568831SAndroid Build Coastguard Worker ctxt->value->floatval += val;
6217*7c568831SAndroid Build Coastguard Worker }
6218*7c568831SAndroid Build Coastguard Worker
6219*7c568831SAndroid Build Coastguard Worker /**
6220*7c568831SAndroid Build Coastguard Worker * xmlXPathSubValues:
6221*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6222*7c568831SAndroid Build Coastguard Worker *
6223*7c568831SAndroid Build Coastguard Worker * Implement the subtraction operation on XPath objects:
6224*7c568831SAndroid Build Coastguard Worker * The numeric operators convert their operands to numbers as if
6225*7c568831SAndroid Build Coastguard Worker * by calling the number function.
6226*7c568831SAndroid Build Coastguard Worker */
6227*7c568831SAndroid Build Coastguard Worker void
xmlXPathSubValues(xmlXPathParserContextPtr ctxt)6228*7c568831SAndroid Build Coastguard Worker xmlXPathSubValues(xmlXPathParserContextPtr ctxt) {
6229*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr arg;
6230*7c568831SAndroid Build Coastguard Worker double val;
6231*7c568831SAndroid Build Coastguard Worker
6232*7c568831SAndroid Build Coastguard Worker arg = valuePop(ctxt);
6233*7c568831SAndroid Build Coastguard Worker if (arg == NULL)
6234*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_OPERAND);
6235*7c568831SAndroid Build Coastguard Worker val = xmlXPathCastToNumberInternal(ctxt, arg);
6236*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg);
6237*7c568831SAndroid Build Coastguard Worker CAST_TO_NUMBER;
6238*7c568831SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_NUMBER);
6239*7c568831SAndroid Build Coastguard Worker ctxt->value->floatval -= val;
6240*7c568831SAndroid Build Coastguard Worker }
6241*7c568831SAndroid Build Coastguard Worker
6242*7c568831SAndroid Build Coastguard Worker /**
6243*7c568831SAndroid Build Coastguard Worker * xmlXPathMultValues:
6244*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6245*7c568831SAndroid Build Coastguard Worker *
6246*7c568831SAndroid Build Coastguard Worker * Implement the multiply operation on XPath objects:
6247*7c568831SAndroid Build Coastguard Worker * The numeric operators convert their operands to numbers as if
6248*7c568831SAndroid Build Coastguard Worker * by calling the number function.
6249*7c568831SAndroid Build Coastguard Worker */
6250*7c568831SAndroid Build Coastguard Worker void
xmlXPathMultValues(xmlXPathParserContextPtr ctxt)6251*7c568831SAndroid Build Coastguard Worker xmlXPathMultValues(xmlXPathParserContextPtr ctxt) {
6252*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr arg;
6253*7c568831SAndroid Build Coastguard Worker double val;
6254*7c568831SAndroid Build Coastguard Worker
6255*7c568831SAndroid Build Coastguard Worker arg = valuePop(ctxt);
6256*7c568831SAndroid Build Coastguard Worker if (arg == NULL)
6257*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_OPERAND);
6258*7c568831SAndroid Build Coastguard Worker val = xmlXPathCastToNumberInternal(ctxt, arg);
6259*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg);
6260*7c568831SAndroid Build Coastguard Worker CAST_TO_NUMBER;
6261*7c568831SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_NUMBER);
6262*7c568831SAndroid Build Coastguard Worker ctxt->value->floatval *= val;
6263*7c568831SAndroid Build Coastguard Worker }
6264*7c568831SAndroid Build Coastguard Worker
6265*7c568831SAndroid Build Coastguard Worker /**
6266*7c568831SAndroid Build Coastguard Worker * xmlXPathDivValues:
6267*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6268*7c568831SAndroid Build Coastguard Worker *
6269*7c568831SAndroid Build Coastguard Worker * Implement the div operation on XPath objects @arg1 / @arg2:
6270*7c568831SAndroid Build Coastguard Worker * The numeric operators convert their operands to numbers as if
6271*7c568831SAndroid Build Coastguard Worker * by calling the number function.
6272*7c568831SAndroid Build Coastguard Worker */
6273*7c568831SAndroid Build Coastguard Worker ATTRIBUTE_NO_SANITIZE("float-divide-by-zero")
6274*7c568831SAndroid Build Coastguard Worker void
xmlXPathDivValues(xmlXPathParserContextPtr ctxt)6275*7c568831SAndroid Build Coastguard Worker xmlXPathDivValues(xmlXPathParserContextPtr ctxt) {
6276*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr arg;
6277*7c568831SAndroid Build Coastguard Worker double val;
6278*7c568831SAndroid Build Coastguard Worker
6279*7c568831SAndroid Build Coastguard Worker arg = valuePop(ctxt);
6280*7c568831SAndroid Build Coastguard Worker if (arg == NULL)
6281*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_OPERAND);
6282*7c568831SAndroid Build Coastguard Worker val = xmlXPathCastToNumberInternal(ctxt, arg);
6283*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg);
6284*7c568831SAndroid Build Coastguard Worker CAST_TO_NUMBER;
6285*7c568831SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_NUMBER);
6286*7c568831SAndroid Build Coastguard Worker ctxt->value->floatval /= val;
6287*7c568831SAndroid Build Coastguard Worker }
6288*7c568831SAndroid Build Coastguard Worker
6289*7c568831SAndroid Build Coastguard Worker /**
6290*7c568831SAndroid Build Coastguard Worker * xmlXPathModValues:
6291*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6292*7c568831SAndroid Build Coastguard Worker *
6293*7c568831SAndroid Build Coastguard Worker * Implement the mod operation on XPath objects: @arg1 / @arg2
6294*7c568831SAndroid Build Coastguard Worker * The numeric operators convert their operands to numbers as if
6295*7c568831SAndroid Build Coastguard Worker * by calling the number function.
6296*7c568831SAndroid Build Coastguard Worker */
6297*7c568831SAndroid Build Coastguard Worker void
xmlXPathModValues(xmlXPathParserContextPtr ctxt)6298*7c568831SAndroid Build Coastguard Worker xmlXPathModValues(xmlXPathParserContextPtr ctxt) {
6299*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr arg;
6300*7c568831SAndroid Build Coastguard Worker double arg1, arg2;
6301*7c568831SAndroid Build Coastguard Worker
6302*7c568831SAndroid Build Coastguard Worker arg = valuePop(ctxt);
6303*7c568831SAndroid Build Coastguard Worker if (arg == NULL)
6304*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_OPERAND);
6305*7c568831SAndroid Build Coastguard Worker arg2 = xmlXPathCastToNumberInternal(ctxt, arg);
6306*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg);
6307*7c568831SAndroid Build Coastguard Worker CAST_TO_NUMBER;
6308*7c568831SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_NUMBER);
6309*7c568831SAndroid Build Coastguard Worker arg1 = ctxt->value->floatval;
6310*7c568831SAndroid Build Coastguard Worker if (arg2 == 0)
6311*7c568831SAndroid Build Coastguard Worker ctxt->value->floatval = xmlXPathNAN;
6312*7c568831SAndroid Build Coastguard Worker else {
6313*7c568831SAndroid Build Coastguard Worker ctxt->value->floatval = fmod(arg1, arg2);
6314*7c568831SAndroid Build Coastguard Worker }
6315*7c568831SAndroid Build Coastguard Worker }
6316*7c568831SAndroid Build Coastguard Worker
6317*7c568831SAndroid Build Coastguard Worker /************************************************************************
6318*7c568831SAndroid Build Coastguard Worker * *
6319*7c568831SAndroid Build Coastguard Worker * The traversal functions *
6320*7c568831SAndroid Build Coastguard Worker * *
6321*7c568831SAndroid Build Coastguard Worker ************************************************************************/
6322*7c568831SAndroid Build Coastguard Worker
6323*7c568831SAndroid Build Coastguard Worker /*
6324*7c568831SAndroid Build Coastguard Worker * A traversal function enumerates nodes along an axis.
6325*7c568831SAndroid Build Coastguard Worker * Initially it must be called with NULL, and it indicates
6326*7c568831SAndroid Build Coastguard Worker * termination on the axis by returning NULL.
6327*7c568831SAndroid Build Coastguard Worker */
6328*7c568831SAndroid Build Coastguard Worker typedef xmlNodePtr (*xmlXPathTraversalFunction)
6329*7c568831SAndroid Build Coastguard Worker (xmlXPathParserContextPtr ctxt, xmlNodePtr cur);
6330*7c568831SAndroid Build Coastguard Worker
6331*7c568831SAndroid Build Coastguard Worker /*
6332*7c568831SAndroid Build Coastguard Worker * xmlXPathTraversalFunctionExt:
6333*7c568831SAndroid Build Coastguard Worker * A traversal function enumerates nodes along an axis.
6334*7c568831SAndroid Build Coastguard Worker * Initially it must be called with NULL, and it indicates
6335*7c568831SAndroid Build Coastguard Worker * termination on the axis by returning NULL.
6336*7c568831SAndroid Build Coastguard Worker * The context node of the traversal is specified via @contextNode.
6337*7c568831SAndroid Build Coastguard Worker */
6338*7c568831SAndroid Build Coastguard Worker typedef xmlNodePtr (*xmlXPathTraversalFunctionExt)
6339*7c568831SAndroid Build Coastguard Worker (xmlNodePtr cur, xmlNodePtr contextNode);
6340*7c568831SAndroid Build Coastguard Worker
6341*7c568831SAndroid Build Coastguard Worker /*
6342*7c568831SAndroid Build Coastguard Worker * xmlXPathNodeSetMergeFunction:
6343*7c568831SAndroid Build Coastguard Worker * Used for merging node sets in xmlXPathCollectAndTest().
6344*7c568831SAndroid Build Coastguard Worker */
6345*7c568831SAndroid Build Coastguard Worker typedef xmlNodeSetPtr (*xmlXPathNodeSetMergeFunction)
6346*7c568831SAndroid Build Coastguard Worker (xmlNodeSetPtr, xmlNodeSetPtr);
6347*7c568831SAndroid Build Coastguard Worker
6348*7c568831SAndroid Build Coastguard Worker
6349*7c568831SAndroid Build Coastguard Worker /**
6350*7c568831SAndroid Build Coastguard Worker * xmlXPathNextSelf:
6351*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6352*7c568831SAndroid Build Coastguard Worker * @cur: the current node in the traversal
6353*7c568831SAndroid Build Coastguard Worker *
6354*7c568831SAndroid Build Coastguard Worker * Traversal function for the "self" direction
6355*7c568831SAndroid Build Coastguard Worker * The self axis contains just the context node itself
6356*7c568831SAndroid Build Coastguard Worker *
6357*7c568831SAndroid Build Coastguard Worker * Returns the next element following that axis
6358*7c568831SAndroid Build Coastguard Worker */
6359*7c568831SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextSelf(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6360*7c568831SAndroid Build Coastguard Worker xmlXPathNextSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6361*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6362*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
6363*7c568831SAndroid Build Coastguard Worker return(ctxt->context->node);
6364*7c568831SAndroid Build Coastguard Worker return(NULL);
6365*7c568831SAndroid Build Coastguard Worker }
6366*7c568831SAndroid Build Coastguard Worker
6367*7c568831SAndroid Build Coastguard Worker /**
6368*7c568831SAndroid Build Coastguard Worker * xmlXPathNextChild:
6369*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6370*7c568831SAndroid Build Coastguard Worker * @cur: the current node in the traversal
6371*7c568831SAndroid Build Coastguard Worker *
6372*7c568831SAndroid Build Coastguard Worker * Traversal function for the "child" direction
6373*7c568831SAndroid Build Coastguard Worker * The child axis contains the children of the context node in document order.
6374*7c568831SAndroid Build Coastguard Worker *
6375*7c568831SAndroid Build Coastguard Worker * Returns the next element following that axis
6376*7c568831SAndroid Build Coastguard Worker */
6377*7c568831SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextChild(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6378*7c568831SAndroid Build Coastguard Worker xmlXPathNextChild(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6379*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6380*7c568831SAndroid Build Coastguard Worker if (cur == NULL) {
6381*7c568831SAndroid Build Coastguard Worker if (ctxt->context->node == NULL) return(NULL);
6382*7c568831SAndroid Build Coastguard Worker switch (ctxt->context->node->type) {
6383*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
6384*7c568831SAndroid Build Coastguard Worker case XML_TEXT_NODE:
6385*7c568831SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
6386*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_REF_NODE:
6387*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_NODE:
6388*7c568831SAndroid Build Coastguard Worker case XML_PI_NODE:
6389*7c568831SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
6390*7c568831SAndroid Build Coastguard Worker case XML_NOTATION_NODE:
6391*7c568831SAndroid Build Coastguard Worker case XML_DTD_NODE:
6392*7c568831SAndroid Build Coastguard Worker return(ctxt->context->node->children);
6393*7c568831SAndroid Build Coastguard Worker case XML_DOCUMENT_NODE:
6394*7c568831SAndroid Build Coastguard Worker case XML_DOCUMENT_TYPE_NODE:
6395*7c568831SAndroid Build Coastguard Worker case XML_DOCUMENT_FRAG_NODE:
6396*7c568831SAndroid Build Coastguard Worker case XML_HTML_DOCUMENT_NODE:
6397*7c568831SAndroid Build Coastguard Worker return(((xmlDocPtr) ctxt->context->node)->children);
6398*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_DECL:
6399*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_DECL:
6400*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_DECL:
6401*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE:
6402*7c568831SAndroid Build Coastguard Worker case XML_NAMESPACE_DECL:
6403*7c568831SAndroid Build Coastguard Worker case XML_XINCLUDE_START:
6404*7c568831SAndroid Build Coastguard Worker case XML_XINCLUDE_END:
6405*7c568831SAndroid Build Coastguard Worker return(NULL);
6406*7c568831SAndroid Build Coastguard Worker }
6407*7c568831SAndroid Build Coastguard Worker return(NULL);
6408*7c568831SAndroid Build Coastguard Worker }
6409*7c568831SAndroid Build Coastguard Worker if ((cur->type == XML_DOCUMENT_NODE) ||
6410*7c568831SAndroid Build Coastguard Worker (cur->type == XML_HTML_DOCUMENT_NODE))
6411*7c568831SAndroid Build Coastguard Worker return(NULL);
6412*7c568831SAndroid Build Coastguard Worker return(cur->next);
6413*7c568831SAndroid Build Coastguard Worker }
6414*7c568831SAndroid Build Coastguard Worker
6415*7c568831SAndroid Build Coastguard Worker /**
6416*7c568831SAndroid Build Coastguard Worker * xmlXPathNextChildElement:
6417*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6418*7c568831SAndroid Build Coastguard Worker * @cur: the current node in the traversal
6419*7c568831SAndroid Build Coastguard Worker *
6420*7c568831SAndroid Build Coastguard Worker * Traversal function for the "child" direction and nodes of type element.
6421*7c568831SAndroid Build Coastguard Worker * The child axis contains the children of the context node in document order.
6422*7c568831SAndroid Build Coastguard Worker *
6423*7c568831SAndroid Build Coastguard Worker * Returns the next element following that axis
6424*7c568831SAndroid Build Coastguard Worker */
6425*7c568831SAndroid Build Coastguard Worker static xmlNodePtr
xmlXPathNextChildElement(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6426*7c568831SAndroid Build Coastguard Worker xmlXPathNextChildElement(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6427*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6428*7c568831SAndroid Build Coastguard Worker if (cur == NULL) {
6429*7c568831SAndroid Build Coastguard Worker cur = ctxt->context->node;
6430*7c568831SAndroid Build Coastguard Worker if (cur == NULL) return(NULL);
6431*7c568831SAndroid Build Coastguard Worker /*
6432*7c568831SAndroid Build Coastguard Worker * Get the first element child.
6433*7c568831SAndroid Build Coastguard Worker */
6434*7c568831SAndroid Build Coastguard Worker switch (cur->type) {
6435*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
6436*7c568831SAndroid Build Coastguard Worker case XML_DOCUMENT_FRAG_NODE:
6437*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_REF_NODE: /* URGENT TODO: entify-refs as well? */
6438*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_NODE:
6439*7c568831SAndroid Build Coastguard Worker cur = cur->children;
6440*7c568831SAndroid Build Coastguard Worker if (cur != NULL) {
6441*7c568831SAndroid Build Coastguard Worker if (cur->type == XML_ELEMENT_NODE)
6442*7c568831SAndroid Build Coastguard Worker return(cur);
6443*7c568831SAndroid Build Coastguard Worker do {
6444*7c568831SAndroid Build Coastguard Worker cur = cur->next;
6445*7c568831SAndroid Build Coastguard Worker } while ((cur != NULL) &&
6446*7c568831SAndroid Build Coastguard Worker (cur->type != XML_ELEMENT_NODE));
6447*7c568831SAndroid Build Coastguard Worker return(cur);
6448*7c568831SAndroid Build Coastguard Worker }
6449*7c568831SAndroid Build Coastguard Worker return(NULL);
6450*7c568831SAndroid Build Coastguard Worker case XML_DOCUMENT_NODE:
6451*7c568831SAndroid Build Coastguard Worker case XML_HTML_DOCUMENT_NODE:
6452*7c568831SAndroid Build Coastguard Worker return(xmlDocGetRootElement((xmlDocPtr) cur));
6453*7c568831SAndroid Build Coastguard Worker default:
6454*7c568831SAndroid Build Coastguard Worker return(NULL);
6455*7c568831SAndroid Build Coastguard Worker }
6456*7c568831SAndroid Build Coastguard Worker return(NULL);
6457*7c568831SAndroid Build Coastguard Worker }
6458*7c568831SAndroid Build Coastguard Worker /*
6459*7c568831SAndroid Build Coastguard Worker * Get the next sibling element node.
6460*7c568831SAndroid Build Coastguard Worker */
6461*7c568831SAndroid Build Coastguard Worker switch (cur->type) {
6462*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
6463*7c568831SAndroid Build Coastguard Worker case XML_TEXT_NODE:
6464*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_REF_NODE:
6465*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_NODE:
6466*7c568831SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
6467*7c568831SAndroid Build Coastguard Worker case XML_PI_NODE:
6468*7c568831SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
6469*7c568831SAndroid Build Coastguard Worker case XML_XINCLUDE_END:
6470*7c568831SAndroid Build Coastguard Worker break;
6471*7c568831SAndroid Build Coastguard Worker /* case XML_DTD_NODE: */ /* URGENT TODO: DTD-node as well? */
6472*7c568831SAndroid Build Coastguard Worker default:
6473*7c568831SAndroid Build Coastguard Worker return(NULL);
6474*7c568831SAndroid Build Coastguard Worker }
6475*7c568831SAndroid Build Coastguard Worker if (cur->next != NULL) {
6476*7c568831SAndroid Build Coastguard Worker if (cur->next->type == XML_ELEMENT_NODE)
6477*7c568831SAndroid Build Coastguard Worker return(cur->next);
6478*7c568831SAndroid Build Coastguard Worker cur = cur->next;
6479*7c568831SAndroid Build Coastguard Worker do {
6480*7c568831SAndroid Build Coastguard Worker cur = cur->next;
6481*7c568831SAndroid Build Coastguard Worker } while ((cur != NULL) && (cur->type != XML_ELEMENT_NODE));
6482*7c568831SAndroid Build Coastguard Worker return(cur);
6483*7c568831SAndroid Build Coastguard Worker }
6484*7c568831SAndroid Build Coastguard Worker return(NULL);
6485*7c568831SAndroid Build Coastguard Worker }
6486*7c568831SAndroid Build Coastguard Worker
6487*7c568831SAndroid Build Coastguard Worker /**
6488*7c568831SAndroid Build Coastguard Worker * xmlXPathNextDescendant:
6489*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6490*7c568831SAndroid Build Coastguard Worker * @cur: the current node in the traversal
6491*7c568831SAndroid Build Coastguard Worker *
6492*7c568831SAndroid Build Coastguard Worker * Traversal function for the "descendant" direction
6493*7c568831SAndroid Build Coastguard Worker * the descendant axis contains the descendants of the context node in document
6494*7c568831SAndroid Build Coastguard Worker * order; a descendant is a child or a child of a child and so on.
6495*7c568831SAndroid Build Coastguard Worker *
6496*7c568831SAndroid Build Coastguard Worker * Returns the next element following that axis
6497*7c568831SAndroid Build Coastguard Worker */
6498*7c568831SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextDescendant(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6499*7c568831SAndroid Build Coastguard Worker xmlXPathNextDescendant(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6500*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6501*7c568831SAndroid Build Coastguard Worker if (cur == NULL) {
6502*7c568831SAndroid Build Coastguard Worker if (ctxt->context->node == NULL)
6503*7c568831SAndroid Build Coastguard Worker return(NULL);
6504*7c568831SAndroid Build Coastguard Worker if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
6505*7c568831SAndroid Build Coastguard Worker (ctxt->context->node->type == XML_NAMESPACE_DECL))
6506*7c568831SAndroid Build Coastguard Worker return(NULL);
6507*7c568831SAndroid Build Coastguard Worker
6508*7c568831SAndroid Build Coastguard Worker if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc)
6509*7c568831SAndroid Build Coastguard Worker return(ctxt->context->doc->children);
6510*7c568831SAndroid Build Coastguard Worker return(ctxt->context->node->children);
6511*7c568831SAndroid Build Coastguard Worker }
6512*7c568831SAndroid Build Coastguard Worker
6513*7c568831SAndroid Build Coastguard Worker if (cur->type == XML_NAMESPACE_DECL)
6514*7c568831SAndroid Build Coastguard Worker return(NULL);
6515*7c568831SAndroid Build Coastguard Worker if (cur->children != NULL) {
6516*7c568831SAndroid Build Coastguard Worker /*
6517*7c568831SAndroid Build Coastguard Worker * Do not descend on entities declarations
6518*7c568831SAndroid Build Coastguard Worker */
6519*7c568831SAndroid Build Coastguard Worker if (cur->children->type != XML_ENTITY_DECL) {
6520*7c568831SAndroid Build Coastguard Worker cur = cur->children;
6521*7c568831SAndroid Build Coastguard Worker /*
6522*7c568831SAndroid Build Coastguard Worker * Skip DTDs
6523*7c568831SAndroid Build Coastguard Worker */
6524*7c568831SAndroid Build Coastguard Worker if (cur->type != XML_DTD_NODE)
6525*7c568831SAndroid Build Coastguard Worker return(cur);
6526*7c568831SAndroid Build Coastguard Worker }
6527*7c568831SAndroid Build Coastguard Worker }
6528*7c568831SAndroid Build Coastguard Worker
6529*7c568831SAndroid Build Coastguard Worker if (cur == ctxt->context->node) return(NULL);
6530*7c568831SAndroid Build Coastguard Worker
6531*7c568831SAndroid Build Coastguard Worker while (cur->next != NULL) {
6532*7c568831SAndroid Build Coastguard Worker cur = cur->next;
6533*7c568831SAndroid Build Coastguard Worker if ((cur->type != XML_ENTITY_DECL) &&
6534*7c568831SAndroid Build Coastguard Worker (cur->type != XML_DTD_NODE))
6535*7c568831SAndroid Build Coastguard Worker return(cur);
6536*7c568831SAndroid Build Coastguard Worker }
6537*7c568831SAndroid Build Coastguard Worker
6538*7c568831SAndroid Build Coastguard Worker do {
6539*7c568831SAndroid Build Coastguard Worker cur = cur->parent;
6540*7c568831SAndroid Build Coastguard Worker if (cur == NULL) break;
6541*7c568831SAndroid Build Coastguard Worker if (cur == ctxt->context->node) return(NULL);
6542*7c568831SAndroid Build Coastguard Worker if (cur->next != NULL) {
6543*7c568831SAndroid Build Coastguard Worker cur = cur->next;
6544*7c568831SAndroid Build Coastguard Worker return(cur);
6545*7c568831SAndroid Build Coastguard Worker }
6546*7c568831SAndroid Build Coastguard Worker } while (cur != NULL);
6547*7c568831SAndroid Build Coastguard Worker return(cur);
6548*7c568831SAndroid Build Coastguard Worker }
6549*7c568831SAndroid Build Coastguard Worker
6550*7c568831SAndroid Build Coastguard Worker /**
6551*7c568831SAndroid Build Coastguard Worker * xmlXPathNextDescendantOrSelf:
6552*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6553*7c568831SAndroid Build Coastguard Worker * @cur: the current node in the traversal
6554*7c568831SAndroid Build Coastguard Worker *
6555*7c568831SAndroid Build Coastguard Worker * Traversal function for the "descendant-or-self" direction
6556*7c568831SAndroid Build Coastguard Worker * the descendant-or-self axis contains the context node and the descendants
6557*7c568831SAndroid Build Coastguard Worker * of the context node in document order; thus the context node is the first
6558*7c568831SAndroid Build Coastguard Worker * node on the axis, and the first child of the context node is the second node
6559*7c568831SAndroid Build Coastguard Worker * on the axis
6560*7c568831SAndroid Build Coastguard Worker *
6561*7c568831SAndroid Build Coastguard Worker * Returns the next element following that axis
6562*7c568831SAndroid Build Coastguard Worker */
6563*7c568831SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextDescendantOrSelf(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6564*7c568831SAndroid Build Coastguard Worker xmlXPathNextDescendantOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6565*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6566*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
6567*7c568831SAndroid Build Coastguard Worker return(ctxt->context->node);
6568*7c568831SAndroid Build Coastguard Worker
6569*7c568831SAndroid Build Coastguard Worker if (ctxt->context->node == NULL)
6570*7c568831SAndroid Build Coastguard Worker return(NULL);
6571*7c568831SAndroid Build Coastguard Worker if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
6572*7c568831SAndroid Build Coastguard Worker (ctxt->context->node->type == XML_NAMESPACE_DECL))
6573*7c568831SAndroid Build Coastguard Worker return(NULL);
6574*7c568831SAndroid Build Coastguard Worker
6575*7c568831SAndroid Build Coastguard Worker return(xmlXPathNextDescendant(ctxt, cur));
6576*7c568831SAndroid Build Coastguard Worker }
6577*7c568831SAndroid Build Coastguard Worker
6578*7c568831SAndroid Build Coastguard Worker /**
6579*7c568831SAndroid Build Coastguard Worker * xmlXPathNextParent:
6580*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6581*7c568831SAndroid Build Coastguard Worker * @cur: the current node in the traversal
6582*7c568831SAndroid Build Coastguard Worker *
6583*7c568831SAndroid Build Coastguard Worker * Traversal function for the "parent" direction
6584*7c568831SAndroid Build Coastguard Worker * The parent axis contains the parent of the context node, if there is one.
6585*7c568831SAndroid Build Coastguard Worker *
6586*7c568831SAndroid Build Coastguard Worker * Returns the next element following that axis
6587*7c568831SAndroid Build Coastguard Worker */
6588*7c568831SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextParent(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6589*7c568831SAndroid Build Coastguard Worker xmlXPathNextParent(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6590*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6591*7c568831SAndroid Build Coastguard Worker /*
6592*7c568831SAndroid Build Coastguard Worker * the parent of an attribute or namespace node is the element
6593*7c568831SAndroid Build Coastguard Worker * to which the attribute or namespace node is attached
6594*7c568831SAndroid Build Coastguard Worker * Namespace handling !!!
6595*7c568831SAndroid Build Coastguard Worker */
6596*7c568831SAndroid Build Coastguard Worker if (cur == NULL) {
6597*7c568831SAndroid Build Coastguard Worker if (ctxt->context->node == NULL) return(NULL);
6598*7c568831SAndroid Build Coastguard Worker switch (ctxt->context->node->type) {
6599*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
6600*7c568831SAndroid Build Coastguard Worker case XML_TEXT_NODE:
6601*7c568831SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
6602*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_REF_NODE:
6603*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_NODE:
6604*7c568831SAndroid Build Coastguard Worker case XML_PI_NODE:
6605*7c568831SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
6606*7c568831SAndroid Build Coastguard Worker case XML_NOTATION_NODE:
6607*7c568831SAndroid Build Coastguard Worker case XML_DTD_NODE:
6608*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_DECL:
6609*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_DECL:
6610*7c568831SAndroid Build Coastguard Worker case XML_XINCLUDE_START:
6611*7c568831SAndroid Build Coastguard Worker case XML_XINCLUDE_END:
6612*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_DECL:
6613*7c568831SAndroid Build Coastguard Worker if (ctxt->context->node->parent == NULL)
6614*7c568831SAndroid Build Coastguard Worker return((xmlNodePtr) ctxt->context->doc);
6615*7c568831SAndroid Build Coastguard Worker if ((ctxt->context->node->parent->type == XML_ELEMENT_NODE) &&
6616*7c568831SAndroid Build Coastguard Worker ((ctxt->context->node->parent->name[0] == ' ') ||
6617*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(ctxt->context->node->parent->name,
6618*7c568831SAndroid Build Coastguard Worker BAD_CAST "fake node libxslt"))))
6619*7c568831SAndroid Build Coastguard Worker return(NULL);
6620*7c568831SAndroid Build Coastguard Worker return(ctxt->context->node->parent);
6621*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE: {
6622*7c568831SAndroid Build Coastguard Worker xmlAttrPtr att = (xmlAttrPtr) ctxt->context->node;
6623*7c568831SAndroid Build Coastguard Worker
6624*7c568831SAndroid Build Coastguard Worker return(att->parent);
6625*7c568831SAndroid Build Coastguard Worker }
6626*7c568831SAndroid Build Coastguard Worker case XML_DOCUMENT_NODE:
6627*7c568831SAndroid Build Coastguard Worker case XML_DOCUMENT_TYPE_NODE:
6628*7c568831SAndroid Build Coastguard Worker case XML_DOCUMENT_FRAG_NODE:
6629*7c568831SAndroid Build Coastguard Worker case XML_HTML_DOCUMENT_NODE:
6630*7c568831SAndroid Build Coastguard Worker return(NULL);
6631*7c568831SAndroid Build Coastguard Worker case XML_NAMESPACE_DECL: {
6632*7c568831SAndroid Build Coastguard Worker xmlNsPtr ns = (xmlNsPtr) ctxt->context->node;
6633*7c568831SAndroid Build Coastguard Worker
6634*7c568831SAndroid Build Coastguard Worker if ((ns->next != NULL) &&
6635*7c568831SAndroid Build Coastguard Worker (ns->next->type != XML_NAMESPACE_DECL))
6636*7c568831SAndroid Build Coastguard Worker return((xmlNodePtr) ns->next);
6637*7c568831SAndroid Build Coastguard Worker return(NULL);
6638*7c568831SAndroid Build Coastguard Worker }
6639*7c568831SAndroid Build Coastguard Worker }
6640*7c568831SAndroid Build Coastguard Worker }
6641*7c568831SAndroid Build Coastguard Worker return(NULL);
6642*7c568831SAndroid Build Coastguard Worker }
6643*7c568831SAndroid Build Coastguard Worker
6644*7c568831SAndroid Build Coastguard Worker /**
6645*7c568831SAndroid Build Coastguard Worker * xmlXPathNextAncestor:
6646*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6647*7c568831SAndroid Build Coastguard Worker * @cur: the current node in the traversal
6648*7c568831SAndroid Build Coastguard Worker *
6649*7c568831SAndroid Build Coastguard Worker * Traversal function for the "ancestor" direction
6650*7c568831SAndroid Build Coastguard Worker * the ancestor axis contains the ancestors of the context node; the ancestors
6651*7c568831SAndroid Build Coastguard Worker * of the context node consist of the parent of context node and the parent's
6652*7c568831SAndroid Build Coastguard Worker * parent and so on; the nodes are ordered in reverse document order; thus the
6653*7c568831SAndroid Build Coastguard Worker * parent is the first node on the axis, and the parent's parent is the second
6654*7c568831SAndroid Build Coastguard Worker * node on the axis
6655*7c568831SAndroid Build Coastguard Worker *
6656*7c568831SAndroid Build Coastguard Worker * Returns the next element following that axis
6657*7c568831SAndroid Build Coastguard Worker */
6658*7c568831SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextAncestor(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6659*7c568831SAndroid Build Coastguard Worker xmlXPathNextAncestor(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6660*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6661*7c568831SAndroid Build Coastguard Worker /*
6662*7c568831SAndroid Build Coastguard Worker * the parent of an attribute or namespace node is the element
6663*7c568831SAndroid Build Coastguard Worker * to which the attribute or namespace node is attached
6664*7c568831SAndroid Build Coastguard Worker * !!!!!!!!!!!!!
6665*7c568831SAndroid Build Coastguard Worker */
6666*7c568831SAndroid Build Coastguard Worker if (cur == NULL) {
6667*7c568831SAndroid Build Coastguard Worker if (ctxt->context->node == NULL) return(NULL);
6668*7c568831SAndroid Build Coastguard Worker switch (ctxt->context->node->type) {
6669*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
6670*7c568831SAndroid Build Coastguard Worker case XML_TEXT_NODE:
6671*7c568831SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
6672*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_REF_NODE:
6673*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_NODE:
6674*7c568831SAndroid Build Coastguard Worker case XML_PI_NODE:
6675*7c568831SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
6676*7c568831SAndroid Build Coastguard Worker case XML_DTD_NODE:
6677*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_DECL:
6678*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_DECL:
6679*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_DECL:
6680*7c568831SAndroid Build Coastguard Worker case XML_NOTATION_NODE:
6681*7c568831SAndroid Build Coastguard Worker case XML_XINCLUDE_START:
6682*7c568831SAndroid Build Coastguard Worker case XML_XINCLUDE_END:
6683*7c568831SAndroid Build Coastguard Worker if (ctxt->context->node->parent == NULL)
6684*7c568831SAndroid Build Coastguard Worker return((xmlNodePtr) ctxt->context->doc);
6685*7c568831SAndroid Build Coastguard Worker if ((ctxt->context->node->parent->type == XML_ELEMENT_NODE) &&
6686*7c568831SAndroid Build Coastguard Worker ((ctxt->context->node->parent->name[0] == ' ') ||
6687*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(ctxt->context->node->parent->name,
6688*7c568831SAndroid Build Coastguard Worker BAD_CAST "fake node libxslt"))))
6689*7c568831SAndroid Build Coastguard Worker return(NULL);
6690*7c568831SAndroid Build Coastguard Worker return(ctxt->context->node->parent);
6691*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE: {
6692*7c568831SAndroid Build Coastguard Worker xmlAttrPtr tmp = (xmlAttrPtr) ctxt->context->node;
6693*7c568831SAndroid Build Coastguard Worker
6694*7c568831SAndroid Build Coastguard Worker return(tmp->parent);
6695*7c568831SAndroid Build Coastguard Worker }
6696*7c568831SAndroid Build Coastguard Worker case XML_DOCUMENT_NODE:
6697*7c568831SAndroid Build Coastguard Worker case XML_DOCUMENT_TYPE_NODE:
6698*7c568831SAndroid Build Coastguard Worker case XML_DOCUMENT_FRAG_NODE:
6699*7c568831SAndroid Build Coastguard Worker case XML_HTML_DOCUMENT_NODE:
6700*7c568831SAndroid Build Coastguard Worker return(NULL);
6701*7c568831SAndroid Build Coastguard Worker case XML_NAMESPACE_DECL: {
6702*7c568831SAndroid Build Coastguard Worker xmlNsPtr ns = (xmlNsPtr) ctxt->context->node;
6703*7c568831SAndroid Build Coastguard Worker
6704*7c568831SAndroid Build Coastguard Worker if ((ns->next != NULL) &&
6705*7c568831SAndroid Build Coastguard Worker (ns->next->type != XML_NAMESPACE_DECL))
6706*7c568831SAndroid Build Coastguard Worker return((xmlNodePtr) ns->next);
6707*7c568831SAndroid Build Coastguard Worker /* Bad, how did that namespace end up here ? */
6708*7c568831SAndroid Build Coastguard Worker return(NULL);
6709*7c568831SAndroid Build Coastguard Worker }
6710*7c568831SAndroid Build Coastguard Worker }
6711*7c568831SAndroid Build Coastguard Worker return(NULL);
6712*7c568831SAndroid Build Coastguard Worker }
6713*7c568831SAndroid Build Coastguard Worker if (cur == ctxt->context->doc->children)
6714*7c568831SAndroid Build Coastguard Worker return((xmlNodePtr) ctxt->context->doc);
6715*7c568831SAndroid Build Coastguard Worker if (cur == (xmlNodePtr) ctxt->context->doc)
6716*7c568831SAndroid Build Coastguard Worker return(NULL);
6717*7c568831SAndroid Build Coastguard Worker switch (cur->type) {
6718*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
6719*7c568831SAndroid Build Coastguard Worker case XML_TEXT_NODE:
6720*7c568831SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
6721*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_REF_NODE:
6722*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_NODE:
6723*7c568831SAndroid Build Coastguard Worker case XML_PI_NODE:
6724*7c568831SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
6725*7c568831SAndroid Build Coastguard Worker case XML_NOTATION_NODE:
6726*7c568831SAndroid Build Coastguard Worker case XML_DTD_NODE:
6727*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_DECL:
6728*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_DECL:
6729*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_DECL:
6730*7c568831SAndroid Build Coastguard Worker case XML_XINCLUDE_START:
6731*7c568831SAndroid Build Coastguard Worker case XML_XINCLUDE_END:
6732*7c568831SAndroid Build Coastguard Worker if (cur->parent == NULL)
6733*7c568831SAndroid Build Coastguard Worker return(NULL);
6734*7c568831SAndroid Build Coastguard Worker if ((cur->parent->type == XML_ELEMENT_NODE) &&
6735*7c568831SAndroid Build Coastguard Worker ((cur->parent->name[0] == ' ') ||
6736*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(cur->parent->name,
6737*7c568831SAndroid Build Coastguard Worker BAD_CAST "fake node libxslt"))))
6738*7c568831SAndroid Build Coastguard Worker return(NULL);
6739*7c568831SAndroid Build Coastguard Worker return(cur->parent);
6740*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE: {
6741*7c568831SAndroid Build Coastguard Worker xmlAttrPtr att = (xmlAttrPtr) cur;
6742*7c568831SAndroid Build Coastguard Worker
6743*7c568831SAndroid Build Coastguard Worker return(att->parent);
6744*7c568831SAndroid Build Coastguard Worker }
6745*7c568831SAndroid Build Coastguard Worker case XML_NAMESPACE_DECL: {
6746*7c568831SAndroid Build Coastguard Worker xmlNsPtr ns = (xmlNsPtr) cur;
6747*7c568831SAndroid Build Coastguard Worker
6748*7c568831SAndroid Build Coastguard Worker if ((ns->next != NULL) &&
6749*7c568831SAndroid Build Coastguard Worker (ns->next->type != XML_NAMESPACE_DECL))
6750*7c568831SAndroid Build Coastguard Worker return((xmlNodePtr) ns->next);
6751*7c568831SAndroid Build Coastguard Worker /* Bad, how did that namespace end up here ? */
6752*7c568831SAndroid Build Coastguard Worker return(NULL);
6753*7c568831SAndroid Build Coastguard Worker }
6754*7c568831SAndroid Build Coastguard Worker case XML_DOCUMENT_NODE:
6755*7c568831SAndroid Build Coastguard Worker case XML_DOCUMENT_TYPE_NODE:
6756*7c568831SAndroid Build Coastguard Worker case XML_DOCUMENT_FRAG_NODE:
6757*7c568831SAndroid Build Coastguard Worker case XML_HTML_DOCUMENT_NODE:
6758*7c568831SAndroid Build Coastguard Worker return(NULL);
6759*7c568831SAndroid Build Coastguard Worker }
6760*7c568831SAndroid Build Coastguard Worker return(NULL);
6761*7c568831SAndroid Build Coastguard Worker }
6762*7c568831SAndroid Build Coastguard Worker
6763*7c568831SAndroid Build Coastguard Worker /**
6764*7c568831SAndroid Build Coastguard Worker * xmlXPathNextAncestorOrSelf:
6765*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6766*7c568831SAndroid Build Coastguard Worker * @cur: the current node in the traversal
6767*7c568831SAndroid Build Coastguard Worker *
6768*7c568831SAndroid Build Coastguard Worker * Traversal function for the "ancestor-or-self" direction
6769*7c568831SAndroid Build Coastguard Worker * he ancestor-or-self axis contains the context node and ancestors of
6770*7c568831SAndroid Build Coastguard Worker * the context node in reverse document order; thus the context node is
6771*7c568831SAndroid Build Coastguard Worker * the first node on the axis, and the context node's parent the second;
6772*7c568831SAndroid Build Coastguard Worker * parent here is defined the same as with the parent axis.
6773*7c568831SAndroid Build Coastguard Worker *
6774*7c568831SAndroid Build Coastguard Worker * Returns the next element following that axis
6775*7c568831SAndroid Build Coastguard Worker */
6776*7c568831SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextAncestorOrSelf(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6777*7c568831SAndroid Build Coastguard Worker xmlXPathNextAncestorOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6778*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6779*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
6780*7c568831SAndroid Build Coastguard Worker return(ctxt->context->node);
6781*7c568831SAndroid Build Coastguard Worker return(xmlXPathNextAncestor(ctxt, cur));
6782*7c568831SAndroid Build Coastguard Worker }
6783*7c568831SAndroid Build Coastguard Worker
6784*7c568831SAndroid Build Coastguard Worker /**
6785*7c568831SAndroid Build Coastguard Worker * xmlXPathNextFollowingSibling:
6786*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6787*7c568831SAndroid Build Coastguard Worker * @cur: the current node in the traversal
6788*7c568831SAndroid Build Coastguard Worker *
6789*7c568831SAndroid Build Coastguard Worker * Traversal function for the "following-sibling" direction
6790*7c568831SAndroid Build Coastguard Worker * The following-sibling axis contains the following siblings of the context
6791*7c568831SAndroid Build Coastguard Worker * node in document order.
6792*7c568831SAndroid Build Coastguard Worker *
6793*7c568831SAndroid Build Coastguard Worker * Returns the next element following that axis
6794*7c568831SAndroid Build Coastguard Worker */
6795*7c568831SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextFollowingSibling(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6796*7c568831SAndroid Build Coastguard Worker xmlXPathNextFollowingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6797*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6798*7c568831SAndroid Build Coastguard Worker if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
6799*7c568831SAndroid Build Coastguard Worker (ctxt->context->node->type == XML_NAMESPACE_DECL))
6800*7c568831SAndroid Build Coastguard Worker return(NULL);
6801*7c568831SAndroid Build Coastguard Worker if (cur == (xmlNodePtr) ctxt->context->doc)
6802*7c568831SAndroid Build Coastguard Worker return(NULL);
6803*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
6804*7c568831SAndroid Build Coastguard Worker return(ctxt->context->node->next);
6805*7c568831SAndroid Build Coastguard Worker return(cur->next);
6806*7c568831SAndroid Build Coastguard Worker }
6807*7c568831SAndroid Build Coastguard Worker
6808*7c568831SAndroid Build Coastguard Worker /**
6809*7c568831SAndroid Build Coastguard Worker * xmlXPathNextPrecedingSibling:
6810*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6811*7c568831SAndroid Build Coastguard Worker * @cur: the current node in the traversal
6812*7c568831SAndroid Build Coastguard Worker *
6813*7c568831SAndroid Build Coastguard Worker * Traversal function for the "preceding-sibling" direction
6814*7c568831SAndroid Build Coastguard Worker * The preceding-sibling axis contains the preceding siblings of the context
6815*7c568831SAndroid Build Coastguard Worker * node in reverse document order; the first preceding sibling is first on the
6816*7c568831SAndroid Build Coastguard Worker * axis; the sibling preceding that node is the second on the axis and so on.
6817*7c568831SAndroid Build Coastguard Worker *
6818*7c568831SAndroid Build Coastguard Worker * Returns the next element following that axis
6819*7c568831SAndroid Build Coastguard Worker */
6820*7c568831SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextPrecedingSibling(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6821*7c568831SAndroid Build Coastguard Worker xmlXPathNextPrecedingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6822*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6823*7c568831SAndroid Build Coastguard Worker if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
6824*7c568831SAndroid Build Coastguard Worker (ctxt->context->node->type == XML_NAMESPACE_DECL))
6825*7c568831SAndroid Build Coastguard Worker return(NULL);
6826*7c568831SAndroid Build Coastguard Worker if (cur == (xmlNodePtr) ctxt->context->doc)
6827*7c568831SAndroid Build Coastguard Worker return(NULL);
6828*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
6829*7c568831SAndroid Build Coastguard Worker return(ctxt->context->node->prev);
6830*7c568831SAndroid Build Coastguard Worker if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE)) {
6831*7c568831SAndroid Build Coastguard Worker cur = cur->prev;
6832*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
6833*7c568831SAndroid Build Coastguard Worker return(ctxt->context->node->prev);
6834*7c568831SAndroid Build Coastguard Worker }
6835*7c568831SAndroid Build Coastguard Worker return(cur->prev);
6836*7c568831SAndroid Build Coastguard Worker }
6837*7c568831SAndroid Build Coastguard Worker
6838*7c568831SAndroid Build Coastguard Worker /**
6839*7c568831SAndroid Build Coastguard Worker * xmlXPathNextFollowing:
6840*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6841*7c568831SAndroid Build Coastguard Worker * @cur: the current node in the traversal
6842*7c568831SAndroid Build Coastguard Worker *
6843*7c568831SAndroid Build Coastguard Worker * Traversal function for the "following" direction
6844*7c568831SAndroid Build Coastguard Worker * The following axis contains all nodes in the same document as the context
6845*7c568831SAndroid Build Coastguard Worker * node that are after the context node in document order, excluding any
6846*7c568831SAndroid Build Coastguard Worker * descendants and excluding attribute nodes and namespace nodes; the nodes
6847*7c568831SAndroid Build Coastguard Worker * are ordered in document order
6848*7c568831SAndroid Build Coastguard Worker *
6849*7c568831SAndroid Build Coastguard Worker * Returns the next element following that axis
6850*7c568831SAndroid Build Coastguard Worker */
6851*7c568831SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextFollowing(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6852*7c568831SAndroid Build Coastguard Worker xmlXPathNextFollowing(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6853*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6854*7c568831SAndroid Build Coastguard Worker if ((cur != NULL) && (cur->type != XML_ATTRIBUTE_NODE) &&
6855*7c568831SAndroid Build Coastguard Worker (cur->type != XML_NAMESPACE_DECL) && (cur->children != NULL))
6856*7c568831SAndroid Build Coastguard Worker return(cur->children);
6857*7c568831SAndroid Build Coastguard Worker
6858*7c568831SAndroid Build Coastguard Worker if (cur == NULL) {
6859*7c568831SAndroid Build Coastguard Worker cur = ctxt->context->node;
6860*7c568831SAndroid Build Coastguard Worker if (cur->type == XML_ATTRIBUTE_NODE) {
6861*7c568831SAndroid Build Coastguard Worker cur = cur->parent;
6862*7c568831SAndroid Build Coastguard Worker } else if (cur->type == XML_NAMESPACE_DECL) {
6863*7c568831SAndroid Build Coastguard Worker xmlNsPtr ns = (xmlNsPtr) cur;
6864*7c568831SAndroid Build Coastguard Worker
6865*7c568831SAndroid Build Coastguard Worker if ((ns->next == NULL) ||
6866*7c568831SAndroid Build Coastguard Worker (ns->next->type == XML_NAMESPACE_DECL))
6867*7c568831SAndroid Build Coastguard Worker return (NULL);
6868*7c568831SAndroid Build Coastguard Worker cur = (xmlNodePtr) ns->next;
6869*7c568831SAndroid Build Coastguard Worker }
6870*7c568831SAndroid Build Coastguard Worker }
6871*7c568831SAndroid Build Coastguard Worker if (cur == NULL) return(NULL) ; /* ERROR */
6872*7c568831SAndroid Build Coastguard Worker if (cur->next != NULL) return(cur->next) ;
6873*7c568831SAndroid Build Coastguard Worker do {
6874*7c568831SAndroid Build Coastguard Worker cur = cur->parent;
6875*7c568831SAndroid Build Coastguard Worker if (cur == NULL) break;
6876*7c568831SAndroid Build Coastguard Worker if (cur == (xmlNodePtr) ctxt->context->doc) return(NULL);
6877*7c568831SAndroid Build Coastguard Worker if (cur->next != NULL) return(cur->next);
6878*7c568831SAndroid Build Coastguard Worker } while (cur != NULL);
6879*7c568831SAndroid Build Coastguard Worker return(cur);
6880*7c568831SAndroid Build Coastguard Worker }
6881*7c568831SAndroid Build Coastguard Worker
6882*7c568831SAndroid Build Coastguard Worker /*
6883*7c568831SAndroid Build Coastguard Worker * xmlXPathIsAncestor:
6884*7c568831SAndroid Build Coastguard Worker * @ancestor: the ancestor node
6885*7c568831SAndroid Build Coastguard Worker * @node: the current node
6886*7c568831SAndroid Build Coastguard Worker *
6887*7c568831SAndroid Build Coastguard Worker * Check that @ancestor is a @node's ancestor
6888*7c568831SAndroid Build Coastguard Worker *
6889*7c568831SAndroid Build Coastguard Worker * returns 1 if @ancestor is a @node's ancestor, 0 otherwise.
6890*7c568831SAndroid Build Coastguard Worker */
6891*7c568831SAndroid Build Coastguard Worker static int
xmlXPathIsAncestor(xmlNodePtr ancestor,xmlNodePtr node)6892*7c568831SAndroid Build Coastguard Worker xmlXPathIsAncestor(xmlNodePtr ancestor, xmlNodePtr node) {
6893*7c568831SAndroid Build Coastguard Worker if ((ancestor == NULL) || (node == NULL)) return(0);
6894*7c568831SAndroid Build Coastguard Worker if (node->type == XML_NAMESPACE_DECL)
6895*7c568831SAndroid Build Coastguard Worker return(0);
6896*7c568831SAndroid Build Coastguard Worker if (ancestor->type == XML_NAMESPACE_DECL)
6897*7c568831SAndroid Build Coastguard Worker return(0);
6898*7c568831SAndroid Build Coastguard Worker /* nodes need to be in the same document */
6899*7c568831SAndroid Build Coastguard Worker if (ancestor->doc != node->doc) return(0);
6900*7c568831SAndroid Build Coastguard Worker /* avoid searching if ancestor or node is the root node */
6901*7c568831SAndroid Build Coastguard Worker if (ancestor == (xmlNodePtr) node->doc) return(1);
6902*7c568831SAndroid Build Coastguard Worker if (node == (xmlNodePtr) ancestor->doc) return(0);
6903*7c568831SAndroid Build Coastguard Worker while (node->parent != NULL) {
6904*7c568831SAndroid Build Coastguard Worker if (node->parent == ancestor)
6905*7c568831SAndroid Build Coastguard Worker return(1);
6906*7c568831SAndroid Build Coastguard Worker node = node->parent;
6907*7c568831SAndroid Build Coastguard Worker }
6908*7c568831SAndroid Build Coastguard Worker return(0);
6909*7c568831SAndroid Build Coastguard Worker }
6910*7c568831SAndroid Build Coastguard Worker
6911*7c568831SAndroid Build Coastguard Worker /**
6912*7c568831SAndroid Build Coastguard Worker * xmlXPathNextPreceding:
6913*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6914*7c568831SAndroid Build Coastguard Worker * @cur: the current node in the traversal
6915*7c568831SAndroid Build Coastguard Worker *
6916*7c568831SAndroid Build Coastguard Worker * Traversal function for the "preceding" direction
6917*7c568831SAndroid Build Coastguard Worker * the preceding axis contains all nodes in the same document as the context
6918*7c568831SAndroid Build Coastguard Worker * node that are before the context node in document order, excluding any
6919*7c568831SAndroid Build Coastguard Worker * ancestors and excluding attribute nodes and namespace nodes; the nodes are
6920*7c568831SAndroid Build Coastguard Worker * ordered in reverse document order
6921*7c568831SAndroid Build Coastguard Worker *
6922*7c568831SAndroid Build Coastguard Worker * Returns the next element following that axis
6923*7c568831SAndroid Build Coastguard Worker */
6924*7c568831SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextPreceding(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6925*7c568831SAndroid Build Coastguard Worker xmlXPathNextPreceding(xmlXPathParserContextPtr ctxt, xmlNodePtr cur)
6926*7c568831SAndroid Build Coastguard Worker {
6927*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6928*7c568831SAndroid Build Coastguard Worker if (cur == NULL) {
6929*7c568831SAndroid Build Coastguard Worker cur = ctxt->context->node;
6930*7c568831SAndroid Build Coastguard Worker if (cur->type == XML_ATTRIBUTE_NODE) {
6931*7c568831SAndroid Build Coastguard Worker cur = cur->parent;
6932*7c568831SAndroid Build Coastguard Worker } else if (cur->type == XML_NAMESPACE_DECL) {
6933*7c568831SAndroid Build Coastguard Worker xmlNsPtr ns = (xmlNsPtr) cur;
6934*7c568831SAndroid Build Coastguard Worker
6935*7c568831SAndroid Build Coastguard Worker if ((ns->next == NULL) ||
6936*7c568831SAndroid Build Coastguard Worker (ns->next->type == XML_NAMESPACE_DECL))
6937*7c568831SAndroid Build Coastguard Worker return (NULL);
6938*7c568831SAndroid Build Coastguard Worker cur = (xmlNodePtr) ns->next;
6939*7c568831SAndroid Build Coastguard Worker }
6940*7c568831SAndroid Build Coastguard Worker }
6941*7c568831SAndroid Build Coastguard Worker if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
6942*7c568831SAndroid Build Coastguard Worker return (NULL);
6943*7c568831SAndroid Build Coastguard Worker if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE))
6944*7c568831SAndroid Build Coastguard Worker cur = cur->prev;
6945*7c568831SAndroid Build Coastguard Worker do {
6946*7c568831SAndroid Build Coastguard Worker if (cur->prev != NULL) {
6947*7c568831SAndroid Build Coastguard Worker for (cur = cur->prev; cur->last != NULL; cur = cur->last) ;
6948*7c568831SAndroid Build Coastguard Worker return (cur);
6949*7c568831SAndroid Build Coastguard Worker }
6950*7c568831SAndroid Build Coastguard Worker
6951*7c568831SAndroid Build Coastguard Worker cur = cur->parent;
6952*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
6953*7c568831SAndroid Build Coastguard Worker return (NULL);
6954*7c568831SAndroid Build Coastguard Worker if (cur == ctxt->context->doc->children)
6955*7c568831SAndroid Build Coastguard Worker return (NULL);
6956*7c568831SAndroid Build Coastguard Worker } while (xmlXPathIsAncestor(cur, ctxt->context->node));
6957*7c568831SAndroid Build Coastguard Worker return (cur);
6958*7c568831SAndroid Build Coastguard Worker }
6959*7c568831SAndroid Build Coastguard Worker
6960*7c568831SAndroid Build Coastguard Worker /**
6961*7c568831SAndroid Build Coastguard Worker * xmlXPathNextPrecedingInternal:
6962*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6963*7c568831SAndroid Build Coastguard Worker * @cur: the current node in the traversal
6964*7c568831SAndroid Build Coastguard Worker *
6965*7c568831SAndroid Build Coastguard Worker * Traversal function for the "preceding" direction
6966*7c568831SAndroid Build Coastguard Worker * the preceding axis contains all nodes in the same document as the context
6967*7c568831SAndroid Build Coastguard Worker * node that are before the context node in document order, excluding any
6968*7c568831SAndroid Build Coastguard Worker * ancestors and excluding attribute nodes and namespace nodes; the nodes are
6969*7c568831SAndroid Build Coastguard Worker * ordered in reverse document order
6970*7c568831SAndroid Build Coastguard Worker * This is a faster implementation but internal only since it requires a
6971*7c568831SAndroid Build Coastguard Worker * state kept in the parser context: ctxt->ancestor.
6972*7c568831SAndroid Build Coastguard Worker *
6973*7c568831SAndroid Build Coastguard Worker * Returns the next element following that axis
6974*7c568831SAndroid Build Coastguard Worker */
6975*7c568831SAndroid Build Coastguard Worker static xmlNodePtr
xmlXPathNextPrecedingInternal(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6976*7c568831SAndroid Build Coastguard Worker xmlXPathNextPrecedingInternal(xmlXPathParserContextPtr ctxt,
6977*7c568831SAndroid Build Coastguard Worker xmlNodePtr cur)
6978*7c568831SAndroid Build Coastguard Worker {
6979*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6980*7c568831SAndroid Build Coastguard Worker if (cur == NULL) {
6981*7c568831SAndroid Build Coastguard Worker cur = ctxt->context->node;
6982*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
6983*7c568831SAndroid Build Coastguard Worker return (NULL);
6984*7c568831SAndroid Build Coastguard Worker if (cur->type == XML_ATTRIBUTE_NODE) {
6985*7c568831SAndroid Build Coastguard Worker cur = cur->parent;
6986*7c568831SAndroid Build Coastguard Worker } else if (cur->type == XML_NAMESPACE_DECL) {
6987*7c568831SAndroid Build Coastguard Worker xmlNsPtr ns = (xmlNsPtr) cur;
6988*7c568831SAndroid Build Coastguard Worker
6989*7c568831SAndroid Build Coastguard Worker if ((ns->next == NULL) ||
6990*7c568831SAndroid Build Coastguard Worker (ns->next->type == XML_NAMESPACE_DECL))
6991*7c568831SAndroid Build Coastguard Worker return (NULL);
6992*7c568831SAndroid Build Coastguard Worker cur = (xmlNodePtr) ns->next;
6993*7c568831SAndroid Build Coastguard Worker }
6994*7c568831SAndroid Build Coastguard Worker ctxt->ancestor = cur->parent;
6995*7c568831SAndroid Build Coastguard Worker }
6996*7c568831SAndroid Build Coastguard Worker if (cur->type == XML_NAMESPACE_DECL)
6997*7c568831SAndroid Build Coastguard Worker return(NULL);
6998*7c568831SAndroid Build Coastguard Worker if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE))
6999*7c568831SAndroid Build Coastguard Worker cur = cur->prev;
7000*7c568831SAndroid Build Coastguard Worker while (cur->prev == NULL) {
7001*7c568831SAndroid Build Coastguard Worker cur = cur->parent;
7002*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
7003*7c568831SAndroid Build Coastguard Worker return (NULL);
7004*7c568831SAndroid Build Coastguard Worker if (cur == ctxt->context->doc->children)
7005*7c568831SAndroid Build Coastguard Worker return (NULL);
7006*7c568831SAndroid Build Coastguard Worker if (cur != ctxt->ancestor)
7007*7c568831SAndroid Build Coastguard Worker return (cur);
7008*7c568831SAndroid Build Coastguard Worker ctxt->ancestor = cur->parent;
7009*7c568831SAndroid Build Coastguard Worker }
7010*7c568831SAndroid Build Coastguard Worker cur = cur->prev;
7011*7c568831SAndroid Build Coastguard Worker while (cur->last != NULL)
7012*7c568831SAndroid Build Coastguard Worker cur = cur->last;
7013*7c568831SAndroid Build Coastguard Worker return (cur);
7014*7c568831SAndroid Build Coastguard Worker }
7015*7c568831SAndroid Build Coastguard Worker
7016*7c568831SAndroid Build Coastguard Worker /**
7017*7c568831SAndroid Build Coastguard Worker * xmlXPathNextNamespace:
7018*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7019*7c568831SAndroid Build Coastguard Worker * @cur: the current attribute in the traversal
7020*7c568831SAndroid Build Coastguard Worker *
7021*7c568831SAndroid Build Coastguard Worker * Traversal function for the "namespace" direction
7022*7c568831SAndroid Build Coastguard Worker * the namespace axis contains the namespace nodes of the context node;
7023*7c568831SAndroid Build Coastguard Worker * the order of nodes on this axis is implementation-defined; the axis will
7024*7c568831SAndroid Build Coastguard Worker * be empty unless the context node is an element
7025*7c568831SAndroid Build Coastguard Worker *
7026*7c568831SAndroid Build Coastguard Worker * We keep the XML namespace node at the end of the list.
7027*7c568831SAndroid Build Coastguard Worker *
7028*7c568831SAndroid Build Coastguard Worker * Returns the next element following that axis
7029*7c568831SAndroid Build Coastguard Worker */
7030*7c568831SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)7031*7c568831SAndroid Build Coastguard Worker xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
7032*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
7033*7c568831SAndroid Build Coastguard Worker if (ctxt->context->node->type != XML_ELEMENT_NODE) return(NULL);
7034*7c568831SAndroid Build Coastguard Worker if (cur == NULL) {
7035*7c568831SAndroid Build Coastguard Worker if (ctxt->context->tmpNsList != NULL)
7036*7c568831SAndroid Build Coastguard Worker xmlFree(ctxt->context->tmpNsList);
7037*7c568831SAndroid Build Coastguard Worker ctxt->context->tmpNsNr = 0;
7038*7c568831SAndroid Build Coastguard Worker if (xmlGetNsListSafe(ctxt->context->doc, ctxt->context->node,
7039*7c568831SAndroid Build Coastguard Worker &ctxt->context->tmpNsList) < 0) {
7040*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7041*7c568831SAndroid Build Coastguard Worker return(NULL);
7042*7c568831SAndroid Build Coastguard Worker }
7043*7c568831SAndroid Build Coastguard Worker if (ctxt->context->tmpNsList != NULL) {
7044*7c568831SAndroid Build Coastguard Worker while (ctxt->context->tmpNsList[ctxt->context->tmpNsNr] != NULL) {
7045*7c568831SAndroid Build Coastguard Worker ctxt->context->tmpNsNr++;
7046*7c568831SAndroid Build Coastguard Worker }
7047*7c568831SAndroid Build Coastguard Worker }
7048*7c568831SAndroid Build Coastguard Worker return((xmlNodePtr) xmlXPathXMLNamespace);
7049*7c568831SAndroid Build Coastguard Worker }
7050*7c568831SAndroid Build Coastguard Worker if (ctxt->context->tmpNsNr > 0) {
7051*7c568831SAndroid Build Coastguard Worker return (xmlNodePtr)ctxt->context->tmpNsList[--ctxt->context->tmpNsNr];
7052*7c568831SAndroid Build Coastguard Worker } else {
7053*7c568831SAndroid Build Coastguard Worker if (ctxt->context->tmpNsList != NULL)
7054*7c568831SAndroid Build Coastguard Worker xmlFree(ctxt->context->tmpNsList);
7055*7c568831SAndroid Build Coastguard Worker ctxt->context->tmpNsList = NULL;
7056*7c568831SAndroid Build Coastguard Worker return(NULL);
7057*7c568831SAndroid Build Coastguard Worker }
7058*7c568831SAndroid Build Coastguard Worker }
7059*7c568831SAndroid Build Coastguard Worker
7060*7c568831SAndroid Build Coastguard Worker /**
7061*7c568831SAndroid Build Coastguard Worker * xmlXPathNextAttribute:
7062*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7063*7c568831SAndroid Build Coastguard Worker * @cur: the current attribute in the traversal
7064*7c568831SAndroid Build Coastguard Worker *
7065*7c568831SAndroid Build Coastguard Worker * Traversal function for the "attribute" direction
7066*7c568831SAndroid Build Coastguard Worker * TODO: support DTD inherited default attributes
7067*7c568831SAndroid Build Coastguard Worker *
7068*7c568831SAndroid Build Coastguard Worker * Returns the next element following that axis
7069*7c568831SAndroid Build Coastguard Worker */
7070*7c568831SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextAttribute(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)7071*7c568831SAndroid Build Coastguard Worker xmlXPathNextAttribute(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
7072*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
7073*7c568831SAndroid Build Coastguard Worker if (ctxt->context->node == NULL)
7074*7c568831SAndroid Build Coastguard Worker return(NULL);
7075*7c568831SAndroid Build Coastguard Worker if (ctxt->context->node->type != XML_ELEMENT_NODE)
7076*7c568831SAndroid Build Coastguard Worker return(NULL);
7077*7c568831SAndroid Build Coastguard Worker if (cur == NULL) {
7078*7c568831SAndroid Build Coastguard Worker if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc)
7079*7c568831SAndroid Build Coastguard Worker return(NULL);
7080*7c568831SAndroid Build Coastguard Worker return((xmlNodePtr)ctxt->context->node->properties);
7081*7c568831SAndroid Build Coastguard Worker }
7082*7c568831SAndroid Build Coastguard Worker return((xmlNodePtr)cur->next);
7083*7c568831SAndroid Build Coastguard Worker }
7084*7c568831SAndroid Build Coastguard Worker
7085*7c568831SAndroid Build Coastguard Worker /************************************************************************
7086*7c568831SAndroid Build Coastguard Worker * *
7087*7c568831SAndroid Build Coastguard Worker * NodeTest Functions *
7088*7c568831SAndroid Build Coastguard Worker * *
7089*7c568831SAndroid Build Coastguard Worker ************************************************************************/
7090*7c568831SAndroid Build Coastguard Worker
7091*7c568831SAndroid Build Coastguard Worker #define IS_FUNCTION 200
7092*7c568831SAndroid Build Coastguard Worker
7093*7c568831SAndroid Build Coastguard Worker
7094*7c568831SAndroid Build Coastguard Worker /************************************************************************
7095*7c568831SAndroid Build Coastguard Worker * *
7096*7c568831SAndroid Build Coastguard Worker * Implicit tree core function library *
7097*7c568831SAndroid Build Coastguard Worker * *
7098*7c568831SAndroid Build Coastguard Worker ************************************************************************/
7099*7c568831SAndroid Build Coastguard Worker
7100*7c568831SAndroid Build Coastguard Worker /**
7101*7c568831SAndroid Build Coastguard Worker * xmlXPathRoot:
7102*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7103*7c568831SAndroid Build Coastguard Worker *
7104*7c568831SAndroid Build Coastguard Worker * Initialize the context to the root of the document
7105*7c568831SAndroid Build Coastguard Worker */
7106*7c568831SAndroid Build Coastguard Worker void
xmlXPathRoot(xmlXPathParserContextPtr ctxt)7107*7c568831SAndroid Build Coastguard Worker xmlXPathRoot(xmlXPathParserContextPtr ctxt) {
7108*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL))
7109*7c568831SAndroid Build Coastguard Worker return;
7110*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt,
7111*7c568831SAndroid Build Coastguard Worker (xmlNodePtr) ctxt->context->doc));
7112*7c568831SAndroid Build Coastguard Worker }
7113*7c568831SAndroid Build Coastguard Worker
7114*7c568831SAndroid Build Coastguard Worker /************************************************************************
7115*7c568831SAndroid Build Coastguard Worker * *
7116*7c568831SAndroid Build Coastguard Worker * The explicit core function library *
7117*7c568831SAndroid Build Coastguard Worker *http://www.w3.org/Style/XSL/Group/1999/07/xpath-19990705.html#corelib *
7118*7c568831SAndroid Build Coastguard Worker * *
7119*7c568831SAndroid Build Coastguard Worker ************************************************************************/
7120*7c568831SAndroid Build Coastguard Worker
7121*7c568831SAndroid Build Coastguard Worker
7122*7c568831SAndroid Build Coastguard Worker /**
7123*7c568831SAndroid Build Coastguard Worker * xmlXPathLastFunction:
7124*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7125*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
7126*7c568831SAndroid Build Coastguard Worker *
7127*7c568831SAndroid Build Coastguard Worker * Implement the last() XPath function
7128*7c568831SAndroid Build Coastguard Worker * number last()
7129*7c568831SAndroid Build Coastguard Worker * The last function returns the number of nodes in the context node list.
7130*7c568831SAndroid Build Coastguard Worker */
7131*7c568831SAndroid Build Coastguard Worker void
xmlXPathLastFunction(xmlXPathParserContextPtr ctxt,int nargs)7132*7c568831SAndroid Build Coastguard Worker xmlXPathLastFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7133*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(0);
7134*7c568831SAndroid Build Coastguard Worker if (ctxt->context->contextSize >= 0) {
7135*7c568831SAndroid Build Coastguard Worker valuePush(ctxt,
7136*7c568831SAndroid Build Coastguard Worker xmlXPathCacheNewFloat(ctxt, (double) ctxt->context->contextSize));
7137*7c568831SAndroid Build Coastguard Worker } else {
7138*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_CTXT_SIZE);
7139*7c568831SAndroid Build Coastguard Worker }
7140*7c568831SAndroid Build Coastguard Worker }
7141*7c568831SAndroid Build Coastguard Worker
7142*7c568831SAndroid Build Coastguard Worker /**
7143*7c568831SAndroid Build Coastguard Worker * xmlXPathPositionFunction:
7144*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7145*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
7146*7c568831SAndroid Build Coastguard Worker *
7147*7c568831SAndroid Build Coastguard Worker * Implement the position() XPath function
7148*7c568831SAndroid Build Coastguard Worker * number position()
7149*7c568831SAndroid Build Coastguard Worker * The position function returns the position of the context node in the
7150*7c568831SAndroid Build Coastguard Worker * context node list. The first position is 1, and so the last position
7151*7c568831SAndroid Build Coastguard Worker * will be equal to last().
7152*7c568831SAndroid Build Coastguard Worker */
7153*7c568831SAndroid Build Coastguard Worker void
xmlXPathPositionFunction(xmlXPathParserContextPtr ctxt,int nargs)7154*7c568831SAndroid Build Coastguard Worker xmlXPathPositionFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7155*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(0);
7156*7c568831SAndroid Build Coastguard Worker if (ctxt->context->proximityPosition >= 0) {
7157*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewFloat(ctxt,
7158*7c568831SAndroid Build Coastguard Worker (double) ctxt->context->proximityPosition));
7159*7c568831SAndroid Build Coastguard Worker } else {
7160*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_CTXT_POSITION);
7161*7c568831SAndroid Build Coastguard Worker }
7162*7c568831SAndroid Build Coastguard Worker }
7163*7c568831SAndroid Build Coastguard Worker
7164*7c568831SAndroid Build Coastguard Worker /**
7165*7c568831SAndroid Build Coastguard Worker * xmlXPathCountFunction:
7166*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7167*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
7168*7c568831SAndroid Build Coastguard Worker *
7169*7c568831SAndroid Build Coastguard Worker * Implement the count() XPath function
7170*7c568831SAndroid Build Coastguard Worker * number count(node-set)
7171*7c568831SAndroid Build Coastguard Worker */
7172*7c568831SAndroid Build Coastguard Worker void
xmlXPathCountFunction(xmlXPathParserContextPtr ctxt,int nargs)7173*7c568831SAndroid Build Coastguard Worker xmlXPathCountFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7174*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr cur;
7175*7c568831SAndroid Build Coastguard Worker
7176*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(1);
7177*7c568831SAndroid Build Coastguard Worker if ((ctxt->value == NULL) ||
7178*7c568831SAndroid Build Coastguard Worker ((ctxt->value->type != XPATH_NODESET) &&
7179*7c568831SAndroid Build Coastguard Worker (ctxt->value->type != XPATH_XSLT_TREE)))
7180*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_TYPE);
7181*7c568831SAndroid Build Coastguard Worker cur = valuePop(ctxt);
7182*7c568831SAndroid Build Coastguard Worker
7183*7c568831SAndroid Build Coastguard Worker if ((cur == NULL) || (cur->nodesetval == NULL))
7184*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, 0.0));
7185*7c568831SAndroid Build Coastguard Worker else
7186*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewFloat(ctxt,
7187*7c568831SAndroid Build Coastguard Worker (double) cur->nodesetval->nodeNr));
7188*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, cur);
7189*7c568831SAndroid Build Coastguard Worker }
7190*7c568831SAndroid Build Coastguard Worker
7191*7c568831SAndroid Build Coastguard Worker /**
7192*7c568831SAndroid Build Coastguard Worker * xmlXPathGetElementsByIds:
7193*7c568831SAndroid Build Coastguard Worker * @doc: the document
7194*7c568831SAndroid Build Coastguard Worker * @ids: a whitespace separated list of IDs
7195*7c568831SAndroid Build Coastguard Worker *
7196*7c568831SAndroid Build Coastguard Worker * Selects elements by their unique ID.
7197*7c568831SAndroid Build Coastguard Worker *
7198*7c568831SAndroid Build Coastguard Worker * Returns a node-set of selected elements.
7199*7c568831SAndroid Build Coastguard Worker */
7200*7c568831SAndroid Build Coastguard Worker static xmlNodeSetPtr
xmlXPathGetElementsByIds(xmlDocPtr doc,const xmlChar * ids)7201*7c568831SAndroid Build Coastguard Worker xmlXPathGetElementsByIds (xmlDocPtr doc, const xmlChar *ids) {
7202*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr ret;
7203*7c568831SAndroid Build Coastguard Worker const xmlChar *cur = ids;
7204*7c568831SAndroid Build Coastguard Worker xmlChar *ID;
7205*7c568831SAndroid Build Coastguard Worker xmlAttrPtr attr;
7206*7c568831SAndroid Build Coastguard Worker xmlNodePtr elem = NULL;
7207*7c568831SAndroid Build Coastguard Worker
7208*7c568831SAndroid Build Coastguard Worker if (ids == NULL) return(NULL);
7209*7c568831SAndroid Build Coastguard Worker
7210*7c568831SAndroid Build Coastguard Worker ret = xmlXPathNodeSetCreate(NULL);
7211*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
7212*7c568831SAndroid Build Coastguard Worker return(ret);
7213*7c568831SAndroid Build Coastguard Worker
7214*7c568831SAndroid Build Coastguard Worker while (IS_BLANK_CH(*cur)) cur++;
7215*7c568831SAndroid Build Coastguard Worker while (*cur != 0) {
7216*7c568831SAndroid Build Coastguard Worker while ((!IS_BLANK_CH(*cur)) && (*cur != 0))
7217*7c568831SAndroid Build Coastguard Worker cur++;
7218*7c568831SAndroid Build Coastguard Worker
7219*7c568831SAndroid Build Coastguard Worker ID = xmlStrndup(ids, cur - ids);
7220*7c568831SAndroid Build Coastguard Worker if (ID == NULL) {
7221*7c568831SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(ret);
7222*7c568831SAndroid Build Coastguard Worker return(NULL);
7223*7c568831SAndroid Build Coastguard Worker }
7224*7c568831SAndroid Build Coastguard Worker /*
7225*7c568831SAndroid Build Coastguard Worker * We used to check the fact that the value passed
7226*7c568831SAndroid Build Coastguard Worker * was an NCName, but this generated much troubles for
7227*7c568831SAndroid Build Coastguard Worker * me and Aleksey Sanin, people blatantly violated that
7228*7c568831SAndroid Build Coastguard Worker * constraint, like Visa3D spec.
7229*7c568831SAndroid Build Coastguard Worker * if (xmlValidateNCName(ID, 1) == 0)
7230*7c568831SAndroid Build Coastguard Worker */
7231*7c568831SAndroid Build Coastguard Worker attr = xmlGetID(doc, ID);
7232*7c568831SAndroid Build Coastguard Worker xmlFree(ID);
7233*7c568831SAndroid Build Coastguard Worker if (attr != NULL) {
7234*7c568831SAndroid Build Coastguard Worker if (attr->type == XML_ATTRIBUTE_NODE)
7235*7c568831SAndroid Build Coastguard Worker elem = attr->parent;
7236*7c568831SAndroid Build Coastguard Worker else if (attr->type == XML_ELEMENT_NODE)
7237*7c568831SAndroid Build Coastguard Worker elem = (xmlNodePtr) attr;
7238*7c568831SAndroid Build Coastguard Worker else
7239*7c568831SAndroid Build Coastguard Worker elem = NULL;
7240*7c568831SAndroid Build Coastguard Worker if (elem != NULL) {
7241*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetAdd(ret, elem) < 0) {
7242*7c568831SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(ret);
7243*7c568831SAndroid Build Coastguard Worker return(NULL);
7244*7c568831SAndroid Build Coastguard Worker }
7245*7c568831SAndroid Build Coastguard Worker }
7246*7c568831SAndroid Build Coastguard Worker }
7247*7c568831SAndroid Build Coastguard Worker
7248*7c568831SAndroid Build Coastguard Worker while (IS_BLANK_CH(*cur)) cur++;
7249*7c568831SAndroid Build Coastguard Worker ids = cur;
7250*7c568831SAndroid Build Coastguard Worker }
7251*7c568831SAndroid Build Coastguard Worker return(ret);
7252*7c568831SAndroid Build Coastguard Worker }
7253*7c568831SAndroid Build Coastguard Worker
7254*7c568831SAndroid Build Coastguard Worker /**
7255*7c568831SAndroid Build Coastguard Worker * xmlXPathIdFunction:
7256*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7257*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
7258*7c568831SAndroid Build Coastguard Worker *
7259*7c568831SAndroid Build Coastguard Worker * Implement the id() XPath function
7260*7c568831SAndroid Build Coastguard Worker * node-set id(object)
7261*7c568831SAndroid Build Coastguard Worker * The id function selects elements by their unique ID
7262*7c568831SAndroid Build Coastguard Worker * (see [5.2.1 Unique IDs]). When the argument to id is of type node-set,
7263*7c568831SAndroid Build Coastguard Worker * then the result is the union of the result of applying id to the
7264*7c568831SAndroid Build Coastguard Worker * string value of each of the nodes in the argument node-set. When the
7265*7c568831SAndroid Build Coastguard Worker * argument to id is of any other type, the argument is converted to a
7266*7c568831SAndroid Build Coastguard Worker * string as if by a call to the string function; the string is split
7267*7c568831SAndroid Build Coastguard Worker * into a whitespace-separated list of tokens (whitespace is any sequence
7268*7c568831SAndroid Build Coastguard Worker * of characters matching the production S); the result is a node-set
7269*7c568831SAndroid Build Coastguard Worker * containing the elements in the same document as the context node that
7270*7c568831SAndroid Build Coastguard Worker * have a unique ID equal to any of the tokens in the list.
7271*7c568831SAndroid Build Coastguard Worker */
7272*7c568831SAndroid Build Coastguard Worker void
xmlXPathIdFunction(xmlXPathParserContextPtr ctxt,int nargs)7273*7c568831SAndroid Build Coastguard Worker xmlXPathIdFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7274*7c568831SAndroid Build Coastguard Worker xmlChar *tokens;
7275*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr ret;
7276*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr obj;
7277*7c568831SAndroid Build Coastguard Worker
7278*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(1);
7279*7c568831SAndroid Build Coastguard Worker obj = valuePop(ctxt);
7280*7c568831SAndroid Build Coastguard Worker if (obj == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
7281*7c568831SAndroid Build Coastguard Worker if ((obj->type == XPATH_NODESET) || (obj->type == XPATH_XSLT_TREE)) {
7282*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr ns;
7283*7c568831SAndroid Build Coastguard Worker int i;
7284*7c568831SAndroid Build Coastguard Worker
7285*7c568831SAndroid Build Coastguard Worker ret = xmlXPathNodeSetCreate(NULL);
7286*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
7287*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7288*7c568831SAndroid Build Coastguard Worker
7289*7c568831SAndroid Build Coastguard Worker if (obj->nodesetval != NULL) {
7290*7c568831SAndroid Build Coastguard Worker for (i = 0; i < obj->nodesetval->nodeNr; i++) {
7291*7c568831SAndroid Build Coastguard Worker tokens =
7292*7c568831SAndroid Build Coastguard Worker xmlXPathCastNodeToString(obj->nodesetval->nodeTab[i]);
7293*7c568831SAndroid Build Coastguard Worker if (tokens == NULL)
7294*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7295*7c568831SAndroid Build Coastguard Worker ns = xmlXPathGetElementsByIds(ctxt->context->doc, tokens);
7296*7c568831SAndroid Build Coastguard Worker if (ns == NULL)
7297*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7298*7c568831SAndroid Build Coastguard Worker ret = xmlXPathNodeSetMerge(ret, ns);
7299*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
7300*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7301*7c568831SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(ns);
7302*7c568831SAndroid Build Coastguard Worker if (tokens != NULL)
7303*7c568831SAndroid Build Coastguard Worker xmlFree(tokens);
7304*7c568831SAndroid Build Coastguard Worker }
7305*7c568831SAndroid Build Coastguard Worker }
7306*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, obj);
7307*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt, ret));
7308*7c568831SAndroid Build Coastguard Worker return;
7309*7c568831SAndroid Build Coastguard Worker }
7310*7c568831SAndroid Build Coastguard Worker tokens = xmlXPathCastToString(obj);
7311*7c568831SAndroid Build Coastguard Worker if (tokens == NULL)
7312*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7313*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, obj);
7314*7c568831SAndroid Build Coastguard Worker ret = xmlXPathGetElementsByIds(ctxt->context->doc, tokens);
7315*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
7316*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7317*7c568831SAndroid Build Coastguard Worker xmlFree(tokens);
7318*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt, ret));
7319*7c568831SAndroid Build Coastguard Worker }
7320*7c568831SAndroid Build Coastguard Worker
7321*7c568831SAndroid Build Coastguard Worker /**
7322*7c568831SAndroid Build Coastguard Worker * xmlXPathLocalNameFunction:
7323*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7324*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
7325*7c568831SAndroid Build Coastguard Worker *
7326*7c568831SAndroid Build Coastguard Worker * Implement the local-name() XPath function
7327*7c568831SAndroid Build Coastguard Worker * string local-name(node-set?)
7328*7c568831SAndroid Build Coastguard Worker * The local-name function returns a string containing the local part
7329*7c568831SAndroid Build Coastguard Worker * of the name of the node in the argument node-set that is first in
7330*7c568831SAndroid Build Coastguard Worker * document order. If the node-set is empty or the first node has no
7331*7c568831SAndroid Build Coastguard Worker * name, an empty string is returned. If the argument is omitted it
7332*7c568831SAndroid Build Coastguard Worker * defaults to the context node.
7333*7c568831SAndroid Build Coastguard Worker */
7334*7c568831SAndroid Build Coastguard Worker void
xmlXPathLocalNameFunction(xmlXPathParserContextPtr ctxt,int nargs)7335*7c568831SAndroid Build Coastguard Worker xmlXPathLocalNameFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7336*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr cur;
7337*7c568831SAndroid Build Coastguard Worker
7338*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL) return;
7339*7c568831SAndroid Build Coastguard Worker
7340*7c568831SAndroid Build Coastguard Worker if (nargs == 0) {
7341*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt, ctxt->context->node));
7342*7c568831SAndroid Build Coastguard Worker nargs = 1;
7343*7c568831SAndroid Build Coastguard Worker }
7344*7c568831SAndroid Build Coastguard Worker
7345*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(1);
7346*7c568831SAndroid Build Coastguard Worker if ((ctxt->value == NULL) ||
7347*7c568831SAndroid Build Coastguard Worker ((ctxt->value->type != XPATH_NODESET) &&
7348*7c568831SAndroid Build Coastguard Worker (ctxt->value->type != XPATH_XSLT_TREE)))
7349*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_TYPE);
7350*7c568831SAndroid Build Coastguard Worker cur = valuePop(ctxt);
7351*7c568831SAndroid Build Coastguard Worker
7352*7c568831SAndroid Build Coastguard Worker if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
7353*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
7354*7c568831SAndroid Build Coastguard Worker } else {
7355*7c568831SAndroid Build Coastguard Worker int i = 0; /* Should be first in document order !!!!! */
7356*7c568831SAndroid Build Coastguard Worker switch (cur->nodesetval->nodeTab[i]->type) {
7357*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
7358*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE:
7359*7c568831SAndroid Build Coastguard Worker case XML_PI_NODE:
7360*7c568831SAndroid Build Coastguard Worker if (cur->nodesetval->nodeTab[i]->name[0] == ' ')
7361*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
7362*7c568831SAndroid Build Coastguard Worker else
7363*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewString(ctxt,
7364*7c568831SAndroid Build Coastguard Worker cur->nodesetval->nodeTab[i]->name));
7365*7c568831SAndroid Build Coastguard Worker break;
7366*7c568831SAndroid Build Coastguard Worker case XML_NAMESPACE_DECL:
7367*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewString(ctxt,
7368*7c568831SAndroid Build Coastguard Worker ((xmlNsPtr)cur->nodesetval->nodeTab[i])->prefix));
7369*7c568831SAndroid Build Coastguard Worker break;
7370*7c568831SAndroid Build Coastguard Worker default:
7371*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
7372*7c568831SAndroid Build Coastguard Worker }
7373*7c568831SAndroid Build Coastguard Worker }
7374*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, cur);
7375*7c568831SAndroid Build Coastguard Worker }
7376*7c568831SAndroid Build Coastguard Worker
7377*7c568831SAndroid Build Coastguard Worker /**
7378*7c568831SAndroid Build Coastguard Worker * xmlXPathNamespaceURIFunction:
7379*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7380*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
7381*7c568831SAndroid Build Coastguard Worker *
7382*7c568831SAndroid Build Coastguard Worker * Implement the namespace-uri() XPath function
7383*7c568831SAndroid Build Coastguard Worker * string namespace-uri(node-set?)
7384*7c568831SAndroid Build Coastguard Worker * The namespace-uri function returns a string containing the
7385*7c568831SAndroid Build Coastguard Worker * namespace URI of the expanded name of the node in the argument
7386*7c568831SAndroid Build Coastguard Worker * node-set that is first in document order. If the node-set is empty,
7387*7c568831SAndroid Build Coastguard Worker * the first node has no name, or the expanded name has no namespace
7388*7c568831SAndroid Build Coastguard Worker * URI, an empty string is returned. If the argument is omitted it
7389*7c568831SAndroid Build Coastguard Worker * defaults to the context node.
7390*7c568831SAndroid Build Coastguard Worker */
7391*7c568831SAndroid Build Coastguard Worker void
xmlXPathNamespaceURIFunction(xmlXPathParserContextPtr ctxt,int nargs)7392*7c568831SAndroid Build Coastguard Worker xmlXPathNamespaceURIFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7393*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr cur;
7394*7c568831SAndroid Build Coastguard Worker
7395*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL) return;
7396*7c568831SAndroid Build Coastguard Worker
7397*7c568831SAndroid Build Coastguard Worker if (nargs == 0) {
7398*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt, ctxt->context->node));
7399*7c568831SAndroid Build Coastguard Worker nargs = 1;
7400*7c568831SAndroid Build Coastguard Worker }
7401*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(1);
7402*7c568831SAndroid Build Coastguard Worker if ((ctxt->value == NULL) ||
7403*7c568831SAndroid Build Coastguard Worker ((ctxt->value->type != XPATH_NODESET) &&
7404*7c568831SAndroid Build Coastguard Worker (ctxt->value->type != XPATH_XSLT_TREE)))
7405*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_TYPE);
7406*7c568831SAndroid Build Coastguard Worker cur = valuePop(ctxt);
7407*7c568831SAndroid Build Coastguard Worker
7408*7c568831SAndroid Build Coastguard Worker if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
7409*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
7410*7c568831SAndroid Build Coastguard Worker } else {
7411*7c568831SAndroid Build Coastguard Worker int i = 0; /* Should be first in document order !!!!! */
7412*7c568831SAndroid Build Coastguard Worker switch (cur->nodesetval->nodeTab[i]->type) {
7413*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
7414*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE:
7415*7c568831SAndroid Build Coastguard Worker if (cur->nodesetval->nodeTab[i]->ns == NULL)
7416*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
7417*7c568831SAndroid Build Coastguard Worker else
7418*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewString(ctxt,
7419*7c568831SAndroid Build Coastguard Worker cur->nodesetval->nodeTab[i]->ns->href));
7420*7c568831SAndroid Build Coastguard Worker break;
7421*7c568831SAndroid Build Coastguard Worker default:
7422*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
7423*7c568831SAndroid Build Coastguard Worker }
7424*7c568831SAndroid Build Coastguard Worker }
7425*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, cur);
7426*7c568831SAndroid Build Coastguard Worker }
7427*7c568831SAndroid Build Coastguard Worker
7428*7c568831SAndroid Build Coastguard Worker /**
7429*7c568831SAndroid Build Coastguard Worker * xmlXPathNameFunction:
7430*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7431*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
7432*7c568831SAndroid Build Coastguard Worker *
7433*7c568831SAndroid Build Coastguard Worker * Implement the name() XPath function
7434*7c568831SAndroid Build Coastguard Worker * string name(node-set?)
7435*7c568831SAndroid Build Coastguard Worker * The name function returns a string containing a QName representing
7436*7c568831SAndroid Build Coastguard Worker * the name of the node in the argument node-set that is first in document
7437*7c568831SAndroid Build Coastguard Worker * order. The QName must represent the name with respect to the namespace
7438*7c568831SAndroid Build Coastguard Worker * declarations in effect on the node whose name is being represented.
7439*7c568831SAndroid Build Coastguard Worker * Typically, this will be the form in which the name occurred in the XML
7440*7c568831SAndroid Build Coastguard Worker * source. This need not be the case if there are namespace declarations
7441*7c568831SAndroid Build Coastguard Worker * in effect on the node that associate multiple prefixes with the same
7442*7c568831SAndroid Build Coastguard Worker * namespace. However, an implementation may include information about
7443*7c568831SAndroid Build Coastguard Worker * the original prefix in its representation of nodes; in this case, an
7444*7c568831SAndroid Build Coastguard Worker * implementation can ensure that the returned string is always the same
7445*7c568831SAndroid Build Coastguard Worker * as the QName used in the XML source. If the argument it omitted it
7446*7c568831SAndroid Build Coastguard Worker * defaults to the context node.
7447*7c568831SAndroid Build Coastguard Worker * Libxml keep the original prefix so the "real qualified name" used is
7448*7c568831SAndroid Build Coastguard Worker * returned.
7449*7c568831SAndroid Build Coastguard Worker */
7450*7c568831SAndroid Build Coastguard Worker static void
xmlXPathNameFunction(xmlXPathParserContextPtr ctxt,int nargs)7451*7c568831SAndroid Build Coastguard Worker xmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs)
7452*7c568831SAndroid Build Coastguard Worker {
7453*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr cur;
7454*7c568831SAndroid Build Coastguard Worker
7455*7c568831SAndroid Build Coastguard Worker if (nargs == 0) {
7456*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt, ctxt->context->node));
7457*7c568831SAndroid Build Coastguard Worker nargs = 1;
7458*7c568831SAndroid Build Coastguard Worker }
7459*7c568831SAndroid Build Coastguard Worker
7460*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(1);
7461*7c568831SAndroid Build Coastguard Worker if ((ctxt->value == NULL) ||
7462*7c568831SAndroid Build Coastguard Worker ((ctxt->value->type != XPATH_NODESET) &&
7463*7c568831SAndroid Build Coastguard Worker (ctxt->value->type != XPATH_XSLT_TREE)))
7464*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_TYPE);
7465*7c568831SAndroid Build Coastguard Worker cur = valuePop(ctxt);
7466*7c568831SAndroid Build Coastguard Worker
7467*7c568831SAndroid Build Coastguard Worker if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
7468*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
7469*7c568831SAndroid Build Coastguard Worker } else {
7470*7c568831SAndroid Build Coastguard Worker int i = 0; /* Should be first in document order !!!!! */
7471*7c568831SAndroid Build Coastguard Worker
7472*7c568831SAndroid Build Coastguard Worker switch (cur->nodesetval->nodeTab[i]->type) {
7473*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
7474*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE:
7475*7c568831SAndroid Build Coastguard Worker if (cur->nodesetval->nodeTab[i]->name[0] == ' ')
7476*7c568831SAndroid Build Coastguard Worker valuePush(ctxt,
7477*7c568831SAndroid Build Coastguard Worker xmlXPathCacheNewCString(ctxt, ""));
7478*7c568831SAndroid Build Coastguard Worker else if ((cur->nodesetval->nodeTab[i]->ns == NULL) ||
7479*7c568831SAndroid Build Coastguard Worker (cur->nodesetval->nodeTab[i]->ns->prefix == NULL)) {
7480*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewString(ctxt,
7481*7c568831SAndroid Build Coastguard Worker cur->nodesetval->nodeTab[i]->name));
7482*7c568831SAndroid Build Coastguard Worker } else {
7483*7c568831SAndroid Build Coastguard Worker xmlChar *fullname;
7484*7c568831SAndroid Build Coastguard Worker
7485*7c568831SAndroid Build Coastguard Worker fullname = xmlBuildQName(cur->nodesetval->nodeTab[i]->name,
7486*7c568831SAndroid Build Coastguard Worker cur->nodesetval->nodeTab[i]->ns->prefix,
7487*7c568831SAndroid Build Coastguard Worker NULL, 0);
7488*7c568831SAndroid Build Coastguard Worker if (fullname == cur->nodesetval->nodeTab[i]->name)
7489*7c568831SAndroid Build Coastguard Worker fullname = xmlStrdup(cur->nodesetval->nodeTab[i]->name);
7490*7c568831SAndroid Build Coastguard Worker if (fullname == NULL)
7491*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7492*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheWrapString(ctxt, fullname));
7493*7c568831SAndroid Build Coastguard Worker }
7494*7c568831SAndroid Build Coastguard Worker break;
7495*7c568831SAndroid Build Coastguard Worker default:
7496*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt,
7497*7c568831SAndroid Build Coastguard Worker cur->nodesetval->nodeTab[i]));
7498*7c568831SAndroid Build Coastguard Worker xmlXPathLocalNameFunction(ctxt, 1);
7499*7c568831SAndroid Build Coastguard Worker }
7500*7c568831SAndroid Build Coastguard Worker }
7501*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, cur);
7502*7c568831SAndroid Build Coastguard Worker }
7503*7c568831SAndroid Build Coastguard Worker
7504*7c568831SAndroid Build Coastguard Worker
7505*7c568831SAndroid Build Coastguard Worker /**
7506*7c568831SAndroid Build Coastguard Worker * xmlXPathStringFunction:
7507*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7508*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
7509*7c568831SAndroid Build Coastguard Worker *
7510*7c568831SAndroid Build Coastguard Worker * Implement the string() XPath function
7511*7c568831SAndroid Build Coastguard Worker * string string(object?)
7512*7c568831SAndroid Build Coastguard Worker * The string function converts an object to a string as follows:
7513*7c568831SAndroid Build Coastguard Worker * - A node-set is converted to a string by returning the value of
7514*7c568831SAndroid Build Coastguard Worker * the node in the node-set that is first in document order.
7515*7c568831SAndroid Build Coastguard Worker * If the node-set is empty, an empty string is returned.
7516*7c568831SAndroid Build Coastguard Worker * - A number is converted to a string as follows
7517*7c568831SAndroid Build Coastguard Worker * + NaN is converted to the string NaN
7518*7c568831SAndroid Build Coastguard Worker * + positive zero is converted to the string 0
7519*7c568831SAndroid Build Coastguard Worker * + negative zero is converted to the string 0
7520*7c568831SAndroid Build Coastguard Worker * + positive infinity is converted to the string Infinity
7521*7c568831SAndroid Build Coastguard Worker * + negative infinity is converted to the string -Infinity
7522*7c568831SAndroid Build Coastguard Worker * + if the number is an integer, the number is represented in
7523*7c568831SAndroid Build Coastguard Worker * decimal form as a Number with no decimal point and no leading
7524*7c568831SAndroid Build Coastguard Worker * zeros, preceded by a minus sign (-) if the number is negative
7525*7c568831SAndroid Build Coastguard Worker * + otherwise, the number is represented in decimal form as a
7526*7c568831SAndroid Build Coastguard Worker * Number including a decimal point with at least one digit
7527*7c568831SAndroid Build Coastguard Worker * before the decimal point and at least one digit after the
7528*7c568831SAndroid Build Coastguard Worker * decimal point, preceded by a minus sign (-) if the number
7529*7c568831SAndroid Build Coastguard Worker * is negative; there must be no leading zeros before the decimal
7530*7c568831SAndroid Build Coastguard Worker * point apart possibly from the one required digit immediately
7531*7c568831SAndroid Build Coastguard Worker * before the decimal point; beyond the one required digit
7532*7c568831SAndroid Build Coastguard Worker * after the decimal point there must be as many, but only as
7533*7c568831SAndroid Build Coastguard Worker * many, more digits as are needed to uniquely distinguish the
7534*7c568831SAndroid Build Coastguard Worker * number from all other IEEE 754 numeric values.
7535*7c568831SAndroid Build Coastguard Worker * - The boolean false value is converted to the string false.
7536*7c568831SAndroid Build Coastguard Worker * The boolean true value is converted to the string true.
7537*7c568831SAndroid Build Coastguard Worker *
7538*7c568831SAndroid Build Coastguard Worker * If the argument is omitted, it defaults to a node-set with the
7539*7c568831SAndroid Build Coastguard Worker * context node as its only member.
7540*7c568831SAndroid Build Coastguard Worker */
7541*7c568831SAndroid Build Coastguard Worker void
xmlXPathStringFunction(xmlXPathParserContextPtr ctxt,int nargs)7542*7c568831SAndroid Build Coastguard Worker xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7543*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr cur;
7544*7c568831SAndroid Build Coastguard Worker xmlChar *stringval;
7545*7c568831SAndroid Build Coastguard Worker
7546*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL) return;
7547*7c568831SAndroid Build Coastguard Worker if (nargs == 0) {
7548*7c568831SAndroid Build Coastguard Worker stringval = xmlXPathCastNodeToString(ctxt->context->node);
7549*7c568831SAndroid Build Coastguard Worker if (stringval == NULL)
7550*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7551*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheWrapString(ctxt, stringval));
7552*7c568831SAndroid Build Coastguard Worker return;
7553*7c568831SAndroid Build Coastguard Worker }
7554*7c568831SAndroid Build Coastguard Worker
7555*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(1);
7556*7c568831SAndroid Build Coastguard Worker cur = valuePop(ctxt);
7557*7c568831SAndroid Build Coastguard Worker if (cur == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
7558*7c568831SAndroid Build Coastguard Worker if (cur->type != XPATH_STRING) {
7559*7c568831SAndroid Build Coastguard Worker stringval = xmlXPathCastToString(cur);
7560*7c568831SAndroid Build Coastguard Worker if (stringval == NULL)
7561*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7562*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, cur);
7563*7c568831SAndroid Build Coastguard Worker cur = xmlXPathCacheWrapString(ctxt, stringval);
7564*7c568831SAndroid Build Coastguard Worker }
7565*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, cur);
7566*7c568831SAndroid Build Coastguard Worker }
7567*7c568831SAndroid Build Coastguard Worker
7568*7c568831SAndroid Build Coastguard Worker /**
7569*7c568831SAndroid Build Coastguard Worker * xmlXPathStringLengthFunction:
7570*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7571*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
7572*7c568831SAndroid Build Coastguard Worker *
7573*7c568831SAndroid Build Coastguard Worker * Implement the string-length() XPath function
7574*7c568831SAndroid Build Coastguard Worker * number string-length(string?)
7575*7c568831SAndroid Build Coastguard Worker * The string-length returns the number of characters in the string
7576*7c568831SAndroid Build Coastguard Worker * (see [3.6 Strings]). If the argument is omitted, it defaults to
7577*7c568831SAndroid Build Coastguard Worker * the context node converted to a string, in other words the value
7578*7c568831SAndroid Build Coastguard Worker * of the context node.
7579*7c568831SAndroid Build Coastguard Worker */
7580*7c568831SAndroid Build Coastguard Worker void
xmlXPathStringLengthFunction(xmlXPathParserContextPtr ctxt,int nargs)7581*7c568831SAndroid Build Coastguard Worker xmlXPathStringLengthFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7582*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr cur;
7583*7c568831SAndroid Build Coastguard Worker
7584*7c568831SAndroid Build Coastguard Worker if (nargs == 0) {
7585*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL))
7586*7c568831SAndroid Build Coastguard Worker return;
7587*7c568831SAndroid Build Coastguard Worker if (ctxt->context->node == NULL) {
7588*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, 0));
7589*7c568831SAndroid Build Coastguard Worker } else {
7590*7c568831SAndroid Build Coastguard Worker xmlChar *content;
7591*7c568831SAndroid Build Coastguard Worker
7592*7c568831SAndroid Build Coastguard Worker content = xmlXPathCastNodeToString(ctxt->context->node);
7593*7c568831SAndroid Build Coastguard Worker if (content == NULL)
7594*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7595*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewFloat(ctxt,
7596*7c568831SAndroid Build Coastguard Worker xmlUTF8Strlen(content)));
7597*7c568831SAndroid Build Coastguard Worker xmlFree(content);
7598*7c568831SAndroid Build Coastguard Worker }
7599*7c568831SAndroid Build Coastguard Worker return;
7600*7c568831SAndroid Build Coastguard Worker }
7601*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(1);
7602*7c568831SAndroid Build Coastguard Worker CAST_TO_STRING;
7603*7c568831SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_STRING);
7604*7c568831SAndroid Build Coastguard Worker cur = valuePop(ctxt);
7605*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewFloat(ctxt,
7606*7c568831SAndroid Build Coastguard Worker xmlUTF8Strlen(cur->stringval)));
7607*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, cur);
7608*7c568831SAndroid Build Coastguard Worker }
7609*7c568831SAndroid Build Coastguard Worker
7610*7c568831SAndroid Build Coastguard Worker /**
7611*7c568831SAndroid Build Coastguard Worker * xmlXPathConcatFunction:
7612*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7613*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
7614*7c568831SAndroid Build Coastguard Worker *
7615*7c568831SAndroid Build Coastguard Worker * Implement the concat() XPath function
7616*7c568831SAndroid Build Coastguard Worker * string concat(string, string, string*)
7617*7c568831SAndroid Build Coastguard Worker * The concat function returns the concatenation of its arguments.
7618*7c568831SAndroid Build Coastguard Worker */
7619*7c568831SAndroid Build Coastguard Worker void
xmlXPathConcatFunction(xmlXPathParserContextPtr ctxt,int nargs)7620*7c568831SAndroid Build Coastguard Worker xmlXPathConcatFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7621*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr cur, newobj;
7622*7c568831SAndroid Build Coastguard Worker xmlChar *tmp;
7623*7c568831SAndroid Build Coastguard Worker
7624*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL) return;
7625*7c568831SAndroid Build Coastguard Worker if (nargs < 2) {
7626*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(2);
7627*7c568831SAndroid Build Coastguard Worker }
7628*7c568831SAndroid Build Coastguard Worker
7629*7c568831SAndroid Build Coastguard Worker CAST_TO_STRING;
7630*7c568831SAndroid Build Coastguard Worker cur = valuePop(ctxt);
7631*7c568831SAndroid Build Coastguard Worker if ((cur == NULL) || (cur->type != XPATH_STRING)) {
7632*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, cur);
7633*7c568831SAndroid Build Coastguard Worker return;
7634*7c568831SAndroid Build Coastguard Worker }
7635*7c568831SAndroid Build Coastguard Worker nargs--;
7636*7c568831SAndroid Build Coastguard Worker
7637*7c568831SAndroid Build Coastguard Worker while (nargs > 0) {
7638*7c568831SAndroid Build Coastguard Worker CAST_TO_STRING;
7639*7c568831SAndroid Build Coastguard Worker newobj = valuePop(ctxt);
7640*7c568831SAndroid Build Coastguard Worker if ((newobj == NULL) || (newobj->type != XPATH_STRING)) {
7641*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, newobj);
7642*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, cur);
7643*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_TYPE);
7644*7c568831SAndroid Build Coastguard Worker }
7645*7c568831SAndroid Build Coastguard Worker tmp = xmlStrcat(newobj->stringval, cur->stringval);
7646*7c568831SAndroid Build Coastguard Worker if (tmp == NULL)
7647*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7648*7c568831SAndroid Build Coastguard Worker newobj->stringval = cur->stringval;
7649*7c568831SAndroid Build Coastguard Worker cur->stringval = tmp;
7650*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, newobj);
7651*7c568831SAndroid Build Coastguard Worker nargs--;
7652*7c568831SAndroid Build Coastguard Worker }
7653*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, cur);
7654*7c568831SAndroid Build Coastguard Worker }
7655*7c568831SAndroid Build Coastguard Worker
7656*7c568831SAndroid Build Coastguard Worker /**
7657*7c568831SAndroid Build Coastguard Worker * xmlXPathContainsFunction:
7658*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7659*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
7660*7c568831SAndroid Build Coastguard Worker *
7661*7c568831SAndroid Build Coastguard Worker * Implement the contains() XPath function
7662*7c568831SAndroid Build Coastguard Worker * boolean contains(string, string)
7663*7c568831SAndroid Build Coastguard Worker * The contains function returns true if the first argument string
7664*7c568831SAndroid Build Coastguard Worker * contains the second argument string, and otherwise returns false.
7665*7c568831SAndroid Build Coastguard Worker */
7666*7c568831SAndroid Build Coastguard Worker void
xmlXPathContainsFunction(xmlXPathParserContextPtr ctxt,int nargs)7667*7c568831SAndroid Build Coastguard Worker xmlXPathContainsFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7668*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr hay, needle;
7669*7c568831SAndroid Build Coastguard Worker
7670*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(2);
7671*7c568831SAndroid Build Coastguard Worker CAST_TO_STRING;
7672*7c568831SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_STRING);
7673*7c568831SAndroid Build Coastguard Worker needle = valuePop(ctxt);
7674*7c568831SAndroid Build Coastguard Worker CAST_TO_STRING;
7675*7c568831SAndroid Build Coastguard Worker hay = valuePop(ctxt);
7676*7c568831SAndroid Build Coastguard Worker
7677*7c568831SAndroid Build Coastguard Worker if ((hay == NULL) || (hay->type != XPATH_STRING)) {
7678*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, hay);
7679*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, needle);
7680*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_TYPE);
7681*7c568831SAndroid Build Coastguard Worker }
7682*7c568831SAndroid Build Coastguard Worker if (xmlStrstr(hay->stringval, needle->stringval))
7683*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 1));
7684*7c568831SAndroid Build Coastguard Worker else
7685*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 0));
7686*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, hay);
7687*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, needle);
7688*7c568831SAndroid Build Coastguard Worker }
7689*7c568831SAndroid Build Coastguard Worker
7690*7c568831SAndroid Build Coastguard Worker /**
7691*7c568831SAndroid Build Coastguard Worker * xmlXPathStartsWithFunction:
7692*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7693*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
7694*7c568831SAndroid Build Coastguard Worker *
7695*7c568831SAndroid Build Coastguard Worker * Implement the starts-with() XPath function
7696*7c568831SAndroid Build Coastguard Worker * boolean starts-with(string, string)
7697*7c568831SAndroid Build Coastguard Worker * The starts-with function returns true if the first argument string
7698*7c568831SAndroid Build Coastguard Worker * starts with the second argument string, and otherwise returns false.
7699*7c568831SAndroid Build Coastguard Worker */
7700*7c568831SAndroid Build Coastguard Worker void
xmlXPathStartsWithFunction(xmlXPathParserContextPtr ctxt,int nargs)7701*7c568831SAndroid Build Coastguard Worker xmlXPathStartsWithFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7702*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr hay, needle;
7703*7c568831SAndroid Build Coastguard Worker int n;
7704*7c568831SAndroid Build Coastguard Worker
7705*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(2);
7706*7c568831SAndroid Build Coastguard Worker CAST_TO_STRING;
7707*7c568831SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_STRING);
7708*7c568831SAndroid Build Coastguard Worker needle = valuePop(ctxt);
7709*7c568831SAndroid Build Coastguard Worker CAST_TO_STRING;
7710*7c568831SAndroid Build Coastguard Worker hay = valuePop(ctxt);
7711*7c568831SAndroid Build Coastguard Worker
7712*7c568831SAndroid Build Coastguard Worker if ((hay == NULL) || (hay->type != XPATH_STRING)) {
7713*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, hay);
7714*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, needle);
7715*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_TYPE);
7716*7c568831SAndroid Build Coastguard Worker }
7717*7c568831SAndroid Build Coastguard Worker n = xmlStrlen(needle->stringval);
7718*7c568831SAndroid Build Coastguard Worker if (xmlStrncmp(hay->stringval, needle->stringval, n))
7719*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 0));
7720*7c568831SAndroid Build Coastguard Worker else
7721*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 1));
7722*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, hay);
7723*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, needle);
7724*7c568831SAndroid Build Coastguard Worker }
7725*7c568831SAndroid Build Coastguard Worker
7726*7c568831SAndroid Build Coastguard Worker /**
7727*7c568831SAndroid Build Coastguard Worker * xmlXPathSubstringFunction:
7728*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7729*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
7730*7c568831SAndroid Build Coastguard Worker *
7731*7c568831SAndroid Build Coastguard Worker * Implement the substring() XPath function
7732*7c568831SAndroid Build Coastguard Worker * string substring(string, number, number?)
7733*7c568831SAndroid Build Coastguard Worker * The substring function returns the substring of the first argument
7734*7c568831SAndroid Build Coastguard Worker * starting at the position specified in the second argument with
7735*7c568831SAndroid Build Coastguard Worker * length specified in the third argument. For example,
7736*7c568831SAndroid Build Coastguard Worker * substring("12345",2,3) returns "234". If the third argument is not
7737*7c568831SAndroid Build Coastguard Worker * specified, it returns the substring starting at the position specified
7738*7c568831SAndroid Build Coastguard Worker * in the second argument and continuing to the end of the string. For
7739*7c568831SAndroid Build Coastguard Worker * example, substring("12345",2) returns "2345". More precisely, each
7740*7c568831SAndroid Build Coastguard Worker * character in the string (see [3.6 Strings]) is considered to have a
7741*7c568831SAndroid Build Coastguard Worker * numeric position: the position of the first character is 1, the position
7742*7c568831SAndroid Build Coastguard Worker * of the second character is 2 and so on. The returned substring contains
7743*7c568831SAndroid Build Coastguard Worker * those characters for which the position of the character is greater than
7744*7c568831SAndroid Build Coastguard Worker * or equal to the second argument and, if the third argument is specified,
7745*7c568831SAndroid Build Coastguard Worker * less than the sum of the second and third arguments; the comparisons
7746*7c568831SAndroid Build Coastguard Worker * and addition used for the above follow the standard IEEE 754 rules. Thus:
7747*7c568831SAndroid Build Coastguard Worker * - substring("12345", 1.5, 2.6) returns "234"
7748*7c568831SAndroid Build Coastguard Worker * - substring("12345", 0, 3) returns "12"
7749*7c568831SAndroid Build Coastguard Worker * - substring("12345", 0 div 0, 3) returns ""
7750*7c568831SAndroid Build Coastguard Worker * - substring("12345", 1, 0 div 0) returns ""
7751*7c568831SAndroid Build Coastguard Worker * - substring("12345", -42, 1 div 0) returns "12345"
7752*7c568831SAndroid Build Coastguard Worker * - substring("12345", -1 div 0, 1 div 0) returns ""
7753*7c568831SAndroid Build Coastguard Worker */
7754*7c568831SAndroid Build Coastguard Worker void
xmlXPathSubstringFunction(xmlXPathParserContextPtr ctxt,int nargs)7755*7c568831SAndroid Build Coastguard Worker xmlXPathSubstringFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7756*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr str, start, len;
7757*7c568831SAndroid Build Coastguard Worker double le=0, in;
7758*7c568831SAndroid Build Coastguard Worker int i = 1, j = INT_MAX;
7759*7c568831SAndroid Build Coastguard Worker
7760*7c568831SAndroid Build Coastguard Worker if (nargs < 2) {
7761*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(2);
7762*7c568831SAndroid Build Coastguard Worker }
7763*7c568831SAndroid Build Coastguard Worker if (nargs > 3) {
7764*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(3);
7765*7c568831SAndroid Build Coastguard Worker }
7766*7c568831SAndroid Build Coastguard Worker /*
7767*7c568831SAndroid Build Coastguard Worker * take care of possible last (position) argument
7768*7c568831SAndroid Build Coastguard Worker */
7769*7c568831SAndroid Build Coastguard Worker if (nargs == 3) {
7770*7c568831SAndroid Build Coastguard Worker CAST_TO_NUMBER;
7771*7c568831SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_NUMBER);
7772*7c568831SAndroid Build Coastguard Worker len = valuePop(ctxt);
7773*7c568831SAndroid Build Coastguard Worker le = len->floatval;
7774*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, len);
7775*7c568831SAndroid Build Coastguard Worker }
7776*7c568831SAndroid Build Coastguard Worker
7777*7c568831SAndroid Build Coastguard Worker CAST_TO_NUMBER;
7778*7c568831SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_NUMBER);
7779*7c568831SAndroid Build Coastguard Worker start = valuePop(ctxt);
7780*7c568831SAndroid Build Coastguard Worker in = start->floatval;
7781*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, start);
7782*7c568831SAndroid Build Coastguard Worker CAST_TO_STRING;
7783*7c568831SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_STRING);
7784*7c568831SAndroid Build Coastguard Worker str = valuePop(ctxt);
7785*7c568831SAndroid Build Coastguard Worker
7786*7c568831SAndroid Build Coastguard Worker if (!(in < INT_MAX)) { /* Logical NOT to handle NaNs */
7787*7c568831SAndroid Build Coastguard Worker i = INT_MAX;
7788*7c568831SAndroid Build Coastguard Worker } else if (in >= 1.0) {
7789*7c568831SAndroid Build Coastguard Worker i = (int)in;
7790*7c568831SAndroid Build Coastguard Worker if (in - floor(in) >= 0.5)
7791*7c568831SAndroid Build Coastguard Worker i += 1;
7792*7c568831SAndroid Build Coastguard Worker }
7793*7c568831SAndroid Build Coastguard Worker
7794*7c568831SAndroid Build Coastguard Worker if (nargs == 3) {
7795*7c568831SAndroid Build Coastguard Worker double rin, rle, end;
7796*7c568831SAndroid Build Coastguard Worker
7797*7c568831SAndroid Build Coastguard Worker rin = floor(in);
7798*7c568831SAndroid Build Coastguard Worker if (in - rin >= 0.5)
7799*7c568831SAndroid Build Coastguard Worker rin += 1.0;
7800*7c568831SAndroid Build Coastguard Worker
7801*7c568831SAndroid Build Coastguard Worker rle = floor(le);
7802*7c568831SAndroid Build Coastguard Worker if (le - rle >= 0.5)
7803*7c568831SAndroid Build Coastguard Worker rle += 1.0;
7804*7c568831SAndroid Build Coastguard Worker
7805*7c568831SAndroid Build Coastguard Worker end = rin + rle;
7806*7c568831SAndroid Build Coastguard Worker if (!(end >= 1.0)) { /* Logical NOT to handle NaNs */
7807*7c568831SAndroid Build Coastguard Worker j = 1;
7808*7c568831SAndroid Build Coastguard Worker } else if (end < INT_MAX) {
7809*7c568831SAndroid Build Coastguard Worker j = (int)end;
7810*7c568831SAndroid Build Coastguard Worker }
7811*7c568831SAndroid Build Coastguard Worker }
7812*7c568831SAndroid Build Coastguard Worker
7813*7c568831SAndroid Build Coastguard Worker i -= 1;
7814*7c568831SAndroid Build Coastguard Worker j -= 1;
7815*7c568831SAndroid Build Coastguard Worker
7816*7c568831SAndroid Build Coastguard Worker if ((i < j) && (i < xmlUTF8Strlen(str->stringval))) {
7817*7c568831SAndroid Build Coastguard Worker xmlChar *ret = xmlUTF8Strsub(str->stringval, i, j - i);
7818*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
7819*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7820*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewString(ctxt, ret));
7821*7c568831SAndroid Build Coastguard Worker xmlFree(ret);
7822*7c568831SAndroid Build Coastguard Worker } else {
7823*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
7824*7c568831SAndroid Build Coastguard Worker }
7825*7c568831SAndroid Build Coastguard Worker
7826*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, str);
7827*7c568831SAndroid Build Coastguard Worker }
7828*7c568831SAndroid Build Coastguard Worker
7829*7c568831SAndroid Build Coastguard Worker /**
7830*7c568831SAndroid Build Coastguard Worker * xmlXPathSubstringBeforeFunction:
7831*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7832*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
7833*7c568831SAndroid Build Coastguard Worker *
7834*7c568831SAndroid Build Coastguard Worker * Implement the substring-before() XPath function
7835*7c568831SAndroid Build Coastguard Worker * string substring-before(string, string)
7836*7c568831SAndroid Build Coastguard Worker * The substring-before function returns the substring of the first
7837*7c568831SAndroid Build Coastguard Worker * argument string that precedes the first occurrence of the second
7838*7c568831SAndroid Build Coastguard Worker * argument string in the first argument string, or the empty string
7839*7c568831SAndroid Build Coastguard Worker * if the first argument string does not contain the second argument
7840*7c568831SAndroid Build Coastguard Worker * string. For example, substring-before("1999/04/01","/") returns 1999.
7841*7c568831SAndroid Build Coastguard Worker */
7842*7c568831SAndroid Build Coastguard Worker void
xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt,int nargs)7843*7c568831SAndroid Build Coastguard Worker xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7844*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr str = NULL;
7845*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr find = NULL;
7846*7c568831SAndroid Build Coastguard Worker const xmlChar *point;
7847*7c568831SAndroid Build Coastguard Worker xmlChar *result;
7848*7c568831SAndroid Build Coastguard Worker
7849*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(2);
7850*7c568831SAndroid Build Coastguard Worker CAST_TO_STRING;
7851*7c568831SAndroid Build Coastguard Worker find = valuePop(ctxt);
7852*7c568831SAndroid Build Coastguard Worker CAST_TO_STRING;
7853*7c568831SAndroid Build Coastguard Worker str = valuePop(ctxt);
7854*7c568831SAndroid Build Coastguard Worker if (ctxt->error != 0)
7855*7c568831SAndroid Build Coastguard Worker goto error;
7856*7c568831SAndroid Build Coastguard Worker
7857*7c568831SAndroid Build Coastguard Worker point = xmlStrstr(str->stringval, find->stringval);
7858*7c568831SAndroid Build Coastguard Worker if (point == NULL) {
7859*7c568831SAndroid Build Coastguard Worker result = xmlStrdup(BAD_CAST "");
7860*7c568831SAndroid Build Coastguard Worker } else {
7861*7c568831SAndroid Build Coastguard Worker result = xmlStrndup(str->stringval, point - str->stringval);
7862*7c568831SAndroid Build Coastguard Worker }
7863*7c568831SAndroid Build Coastguard Worker if (result == NULL) {
7864*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7865*7c568831SAndroid Build Coastguard Worker goto error;
7866*7c568831SAndroid Build Coastguard Worker }
7867*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheWrapString(ctxt, result));
7868*7c568831SAndroid Build Coastguard Worker
7869*7c568831SAndroid Build Coastguard Worker error:
7870*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, str);
7871*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, find);
7872*7c568831SAndroid Build Coastguard Worker }
7873*7c568831SAndroid Build Coastguard Worker
7874*7c568831SAndroid Build Coastguard Worker /**
7875*7c568831SAndroid Build Coastguard Worker * xmlXPathSubstringAfterFunction:
7876*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7877*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
7878*7c568831SAndroid Build Coastguard Worker *
7879*7c568831SAndroid Build Coastguard Worker * Implement the substring-after() XPath function
7880*7c568831SAndroid Build Coastguard Worker * string substring-after(string, string)
7881*7c568831SAndroid Build Coastguard Worker * The substring-after function returns the substring of the first
7882*7c568831SAndroid Build Coastguard Worker * argument string that follows the first occurrence of the second
7883*7c568831SAndroid Build Coastguard Worker * argument string in the first argument string, or the empty string
7884*7c568831SAndroid Build Coastguard Worker * if the first argument string does not contain the second argument
7885*7c568831SAndroid Build Coastguard Worker * string. For example, substring-after("1999/04/01","/") returns 04/01,
7886*7c568831SAndroid Build Coastguard Worker * and substring-after("1999/04/01","19") returns 99/04/01.
7887*7c568831SAndroid Build Coastguard Worker */
7888*7c568831SAndroid Build Coastguard Worker void
xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt,int nargs)7889*7c568831SAndroid Build Coastguard Worker xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7890*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr str = NULL;
7891*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr find = NULL;
7892*7c568831SAndroid Build Coastguard Worker const xmlChar *point;
7893*7c568831SAndroid Build Coastguard Worker xmlChar *result;
7894*7c568831SAndroid Build Coastguard Worker
7895*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(2);
7896*7c568831SAndroid Build Coastguard Worker CAST_TO_STRING;
7897*7c568831SAndroid Build Coastguard Worker find = valuePop(ctxt);
7898*7c568831SAndroid Build Coastguard Worker CAST_TO_STRING;
7899*7c568831SAndroid Build Coastguard Worker str = valuePop(ctxt);
7900*7c568831SAndroid Build Coastguard Worker if (ctxt->error != 0)
7901*7c568831SAndroid Build Coastguard Worker goto error;
7902*7c568831SAndroid Build Coastguard Worker
7903*7c568831SAndroid Build Coastguard Worker point = xmlStrstr(str->stringval, find->stringval);
7904*7c568831SAndroid Build Coastguard Worker if (point == NULL) {
7905*7c568831SAndroid Build Coastguard Worker result = xmlStrdup(BAD_CAST "");
7906*7c568831SAndroid Build Coastguard Worker } else {
7907*7c568831SAndroid Build Coastguard Worker result = xmlStrdup(point + xmlStrlen(find->stringval));
7908*7c568831SAndroid Build Coastguard Worker }
7909*7c568831SAndroid Build Coastguard Worker if (result == NULL) {
7910*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7911*7c568831SAndroid Build Coastguard Worker goto error;
7912*7c568831SAndroid Build Coastguard Worker }
7913*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheWrapString(ctxt, result));
7914*7c568831SAndroid Build Coastguard Worker
7915*7c568831SAndroid Build Coastguard Worker error:
7916*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, str);
7917*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, find);
7918*7c568831SAndroid Build Coastguard Worker }
7919*7c568831SAndroid Build Coastguard Worker
7920*7c568831SAndroid Build Coastguard Worker /**
7921*7c568831SAndroid Build Coastguard Worker * xmlXPathNormalizeFunction:
7922*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7923*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
7924*7c568831SAndroid Build Coastguard Worker *
7925*7c568831SAndroid Build Coastguard Worker * Implement the normalize-space() XPath function
7926*7c568831SAndroid Build Coastguard Worker * string normalize-space(string?)
7927*7c568831SAndroid Build Coastguard Worker * The normalize-space function returns the argument string with white
7928*7c568831SAndroid Build Coastguard Worker * space normalized by stripping leading and trailing whitespace
7929*7c568831SAndroid Build Coastguard Worker * and replacing sequences of whitespace characters by a single
7930*7c568831SAndroid Build Coastguard Worker * space. Whitespace characters are the same allowed by the S production
7931*7c568831SAndroid Build Coastguard Worker * in XML. If the argument is omitted, it defaults to the context
7932*7c568831SAndroid Build Coastguard Worker * node converted to a string, in other words the value of the context node.
7933*7c568831SAndroid Build Coastguard Worker */
7934*7c568831SAndroid Build Coastguard Worker void
xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt,int nargs)7935*7c568831SAndroid Build Coastguard Worker xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7936*7c568831SAndroid Build Coastguard Worker xmlChar *source, *target;
7937*7c568831SAndroid Build Coastguard Worker int blank;
7938*7c568831SAndroid Build Coastguard Worker
7939*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL) return;
7940*7c568831SAndroid Build Coastguard Worker if (nargs == 0) {
7941*7c568831SAndroid Build Coastguard Worker /* Use current context node */
7942*7c568831SAndroid Build Coastguard Worker source = xmlXPathCastNodeToString(ctxt->context->node);
7943*7c568831SAndroid Build Coastguard Worker if (source == NULL)
7944*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7945*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheWrapString(ctxt, source));
7946*7c568831SAndroid Build Coastguard Worker nargs = 1;
7947*7c568831SAndroid Build Coastguard Worker }
7948*7c568831SAndroid Build Coastguard Worker
7949*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(1);
7950*7c568831SAndroid Build Coastguard Worker CAST_TO_STRING;
7951*7c568831SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_STRING);
7952*7c568831SAndroid Build Coastguard Worker source = ctxt->value->stringval;
7953*7c568831SAndroid Build Coastguard Worker if (source == NULL)
7954*7c568831SAndroid Build Coastguard Worker return;
7955*7c568831SAndroid Build Coastguard Worker target = source;
7956*7c568831SAndroid Build Coastguard Worker
7957*7c568831SAndroid Build Coastguard Worker /* Skip leading whitespaces */
7958*7c568831SAndroid Build Coastguard Worker while (IS_BLANK_CH(*source))
7959*7c568831SAndroid Build Coastguard Worker source++;
7960*7c568831SAndroid Build Coastguard Worker
7961*7c568831SAndroid Build Coastguard Worker /* Collapse intermediate whitespaces, and skip trailing whitespaces */
7962*7c568831SAndroid Build Coastguard Worker blank = 0;
7963*7c568831SAndroid Build Coastguard Worker while (*source) {
7964*7c568831SAndroid Build Coastguard Worker if (IS_BLANK_CH(*source)) {
7965*7c568831SAndroid Build Coastguard Worker blank = 1;
7966*7c568831SAndroid Build Coastguard Worker } else {
7967*7c568831SAndroid Build Coastguard Worker if (blank) {
7968*7c568831SAndroid Build Coastguard Worker *target++ = 0x20;
7969*7c568831SAndroid Build Coastguard Worker blank = 0;
7970*7c568831SAndroid Build Coastguard Worker }
7971*7c568831SAndroid Build Coastguard Worker *target++ = *source;
7972*7c568831SAndroid Build Coastguard Worker }
7973*7c568831SAndroid Build Coastguard Worker source++;
7974*7c568831SAndroid Build Coastguard Worker }
7975*7c568831SAndroid Build Coastguard Worker *target = 0;
7976*7c568831SAndroid Build Coastguard Worker }
7977*7c568831SAndroid Build Coastguard Worker
7978*7c568831SAndroid Build Coastguard Worker /**
7979*7c568831SAndroid Build Coastguard Worker * xmlXPathTranslateFunction:
7980*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7981*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
7982*7c568831SAndroid Build Coastguard Worker *
7983*7c568831SAndroid Build Coastguard Worker * Implement the translate() XPath function
7984*7c568831SAndroid Build Coastguard Worker * string translate(string, string, string)
7985*7c568831SAndroid Build Coastguard Worker * The translate function returns the first argument string with
7986*7c568831SAndroid Build Coastguard Worker * occurrences of characters in the second argument string replaced
7987*7c568831SAndroid Build Coastguard Worker * by the character at the corresponding position in the third argument
7988*7c568831SAndroid Build Coastguard Worker * string. For example, translate("bar","abc","ABC") returns the string
7989*7c568831SAndroid Build Coastguard Worker * BAr. If there is a character in the second argument string with no
7990*7c568831SAndroid Build Coastguard Worker * character at a corresponding position in the third argument string
7991*7c568831SAndroid Build Coastguard Worker * (because the second argument string is longer than the third argument
7992*7c568831SAndroid Build Coastguard Worker * string), then occurrences of that character in the first argument
7993*7c568831SAndroid Build Coastguard Worker * string are removed. For example, translate("--aaa--","abc-","ABC")
7994*7c568831SAndroid Build Coastguard Worker * returns "AAA". If a character occurs more than once in second
7995*7c568831SAndroid Build Coastguard Worker * argument string, then the first occurrence determines the replacement
7996*7c568831SAndroid Build Coastguard Worker * character. If the third argument string is longer than the second
7997*7c568831SAndroid Build Coastguard Worker * argument string, then excess characters are ignored.
7998*7c568831SAndroid Build Coastguard Worker */
7999*7c568831SAndroid Build Coastguard Worker void
xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt,int nargs)8000*7c568831SAndroid Build Coastguard Worker xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8001*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr str = NULL;
8002*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr from = NULL;
8003*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr to = NULL;
8004*7c568831SAndroid Build Coastguard Worker xmlBufPtr target;
8005*7c568831SAndroid Build Coastguard Worker int offset, max;
8006*7c568831SAndroid Build Coastguard Worker int ch;
8007*7c568831SAndroid Build Coastguard Worker const xmlChar *point;
8008*7c568831SAndroid Build Coastguard Worker xmlChar *cptr, *content;
8009*7c568831SAndroid Build Coastguard Worker
8010*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(3);
8011*7c568831SAndroid Build Coastguard Worker
8012*7c568831SAndroid Build Coastguard Worker CAST_TO_STRING;
8013*7c568831SAndroid Build Coastguard Worker to = valuePop(ctxt);
8014*7c568831SAndroid Build Coastguard Worker CAST_TO_STRING;
8015*7c568831SAndroid Build Coastguard Worker from = valuePop(ctxt);
8016*7c568831SAndroid Build Coastguard Worker CAST_TO_STRING;
8017*7c568831SAndroid Build Coastguard Worker str = valuePop(ctxt);
8018*7c568831SAndroid Build Coastguard Worker if (ctxt->error != 0)
8019*7c568831SAndroid Build Coastguard Worker goto error;
8020*7c568831SAndroid Build Coastguard Worker
8021*7c568831SAndroid Build Coastguard Worker /*
8022*7c568831SAndroid Build Coastguard Worker * Account for quadratic runtime
8023*7c568831SAndroid Build Coastguard Worker */
8024*7c568831SAndroid Build Coastguard Worker if (ctxt->context->opLimit != 0) {
8025*7c568831SAndroid Build Coastguard Worker unsigned long f1 = xmlStrlen(from->stringval);
8026*7c568831SAndroid Build Coastguard Worker unsigned long f2 = xmlStrlen(str->stringval);
8027*7c568831SAndroid Build Coastguard Worker
8028*7c568831SAndroid Build Coastguard Worker if ((f1 > 0) && (f2 > 0)) {
8029*7c568831SAndroid Build Coastguard Worker unsigned long p;
8030*7c568831SAndroid Build Coastguard Worker
8031*7c568831SAndroid Build Coastguard Worker f1 = f1 / 10 + 1;
8032*7c568831SAndroid Build Coastguard Worker f2 = f2 / 10 + 1;
8033*7c568831SAndroid Build Coastguard Worker p = f1 > ULONG_MAX / f2 ? ULONG_MAX : f1 * f2;
8034*7c568831SAndroid Build Coastguard Worker if (xmlXPathCheckOpLimit(ctxt, p) < 0)
8035*7c568831SAndroid Build Coastguard Worker goto error;
8036*7c568831SAndroid Build Coastguard Worker }
8037*7c568831SAndroid Build Coastguard Worker }
8038*7c568831SAndroid Build Coastguard Worker
8039*7c568831SAndroid Build Coastguard Worker target = xmlBufCreate(50);
8040*7c568831SAndroid Build Coastguard Worker if (target == NULL) {
8041*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
8042*7c568831SAndroid Build Coastguard Worker goto error;
8043*7c568831SAndroid Build Coastguard Worker }
8044*7c568831SAndroid Build Coastguard Worker
8045*7c568831SAndroid Build Coastguard Worker max = xmlUTF8Strlen(to->stringval);
8046*7c568831SAndroid Build Coastguard Worker for (cptr = str->stringval; (ch=*cptr); ) {
8047*7c568831SAndroid Build Coastguard Worker offset = xmlUTF8Strloc(from->stringval, cptr);
8048*7c568831SAndroid Build Coastguard Worker if (offset >= 0) {
8049*7c568831SAndroid Build Coastguard Worker if (offset < max) {
8050*7c568831SAndroid Build Coastguard Worker point = xmlUTF8Strpos(to->stringval, offset);
8051*7c568831SAndroid Build Coastguard Worker if (point)
8052*7c568831SAndroid Build Coastguard Worker xmlBufAdd(target, point, xmlUTF8Strsize(point, 1));
8053*7c568831SAndroid Build Coastguard Worker }
8054*7c568831SAndroid Build Coastguard Worker } else
8055*7c568831SAndroid Build Coastguard Worker xmlBufAdd(target, cptr, xmlUTF8Strsize(cptr, 1));
8056*7c568831SAndroid Build Coastguard Worker
8057*7c568831SAndroid Build Coastguard Worker /* Step to next character in input */
8058*7c568831SAndroid Build Coastguard Worker cptr++;
8059*7c568831SAndroid Build Coastguard Worker if ( ch & 0x80 ) {
8060*7c568831SAndroid Build Coastguard Worker /* if not simple ascii, verify proper format */
8061*7c568831SAndroid Build Coastguard Worker if ( (ch & 0xc0) != 0xc0 ) {
8062*7c568831SAndroid Build Coastguard Worker xmlXPathErr(ctxt, XPATH_INVALID_CHAR_ERROR);
8063*7c568831SAndroid Build Coastguard Worker break;
8064*7c568831SAndroid Build Coastguard Worker }
8065*7c568831SAndroid Build Coastguard Worker /* then skip over remaining bytes for this char */
8066*7c568831SAndroid Build Coastguard Worker while ( (ch <<= 1) & 0x80 )
8067*7c568831SAndroid Build Coastguard Worker if ( (*cptr++ & 0xc0) != 0x80 ) {
8068*7c568831SAndroid Build Coastguard Worker xmlXPathErr(ctxt, XPATH_INVALID_CHAR_ERROR);
8069*7c568831SAndroid Build Coastguard Worker break;
8070*7c568831SAndroid Build Coastguard Worker }
8071*7c568831SAndroid Build Coastguard Worker if (ch & 0x80) /* must have had error encountered */
8072*7c568831SAndroid Build Coastguard Worker break;
8073*7c568831SAndroid Build Coastguard Worker }
8074*7c568831SAndroid Build Coastguard Worker }
8075*7c568831SAndroid Build Coastguard Worker
8076*7c568831SAndroid Build Coastguard Worker content = xmlBufDetach(target);
8077*7c568831SAndroid Build Coastguard Worker if (content == NULL)
8078*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
8079*7c568831SAndroid Build Coastguard Worker else
8080*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheWrapString(ctxt, content));
8081*7c568831SAndroid Build Coastguard Worker xmlBufFree(target);
8082*7c568831SAndroid Build Coastguard Worker error:
8083*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, str);
8084*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, from);
8085*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, to);
8086*7c568831SAndroid Build Coastguard Worker }
8087*7c568831SAndroid Build Coastguard Worker
8088*7c568831SAndroid Build Coastguard Worker /**
8089*7c568831SAndroid Build Coastguard Worker * xmlXPathBooleanFunction:
8090*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8091*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
8092*7c568831SAndroid Build Coastguard Worker *
8093*7c568831SAndroid Build Coastguard Worker * Implement the boolean() XPath function
8094*7c568831SAndroid Build Coastguard Worker * boolean boolean(object)
8095*7c568831SAndroid Build Coastguard Worker * The boolean function converts its argument to a boolean as follows:
8096*7c568831SAndroid Build Coastguard Worker * - a number is true if and only if it is neither positive or
8097*7c568831SAndroid Build Coastguard Worker * negative zero nor NaN
8098*7c568831SAndroid Build Coastguard Worker * - a node-set is true if and only if it is non-empty
8099*7c568831SAndroid Build Coastguard Worker * - a string is true if and only if its length is non-zero
8100*7c568831SAndroid Build Coastguard Worker */
8101*7c568831SAndroid Build Coastguard Worker void
xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt,int nargs)8102*7c568831SAndroid Build Coastguard Worker xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8103*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr cur;
8104*7c568831SAndroid Build Coastguard Worker
8105*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(1);
8106*7c568831SAndroid Build Coastguard Worker cur = valuePop(ctxt);
8107*7c568831SAndroid Build Coastguard Worker if (cur == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
8108*7c568831SAndroid Build Coastguard Worker if (cur->type != XPATH_BOOLEAN) {
8109*7c568831SAndroid Build Coastguard Worker int boolval = xmlXPathCastToBoolean(cur);
8110*7c568831SAndroid Build Coastguard Worker
8111*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, cur);
8112*7c568831SAndroid Build Coastguard Worker cur = xmlXPathCacheNewBoolean(ctxt, boolval);
8113*7c568831SAndroid Build Coastguard Worker }
8114*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, cur);
8115*7c568831SAndroid Build Coastguard Worker }
8116*7c568831SAndroid Build Coastguard Worker
8117*7c568831SAndroid Build Coastguard Worker /**
8118*7c568831SAndroid Build Coastguard Worker * xmlXPathNotFunction:
8119*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8120*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
8121*7c568831SAndroid Build Coastguard Worker *
8122*7c568831SAndroid Build Coastguard Worker * Implement the not() XPath function
8123*7c568831SAndroid Build Coastguard Worker * boolean not(boolean)
8124*7c568831SAndroid Build Coastguard Worker * The not function returns true if its argument is false,
8125*7c568831SAndroid Build Coastguard Worker * and false otherwise.
8126*7c568831SAndroid Build Coastguard Worker */
8127*7c568831SAndroid Build Coastguard Worker void
xmlXPathNotFunction(xmlXPathParserContextPtr ctxt,int nargs)8128*7c568831SAndroid Build Coastguard Worker xmlXPathNotFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8129*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(1);
8130*7c568831SAndroid Build Coastguard Worker CAST_TO_BOOLEAN;
8131*7c568831SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_BOOLEAN);
8132*7c568831SAndroid Build Coastguard Worker ctxt->value->boolval = ! ctxt->value->boolval;
8133*7c568831SAndroid Build Coastguard Worker }
8134*7c568831SAndroid Build Coastguard Worker
8135*7c568831SAndroid Build Coastguard Worker /**
8136*7c568831SAndroid Build Coastguard Worker * xmlXPathTrueFunction:
8137*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8138*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
8139*7c568831SAndroid Build Coastguard Worker *
8140*7c568831SAndroid Build Coastguard Worker * Implement the true() XPath function
8141*7c568831SAndroid Build Coastguard Worker * boolean true()
8142*7c568831SAndroid Build Coastguard Worker */
8143*7c568831SAndroid Build Coastguard Worker void
xmlXPathTrueFunction(xmlXPathParserContextPtr ctxt,int nargs)8144*7c568831SAndroid Build Coastguard Worker xmlXPathTrueFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8145*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(0);
8146*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 1));
8147*7c568831SAndroid Build Coastguard Worker }
8148*7c568831SAndroid Build Coastguard Worker
8149*7c568831SAndroid Build Coastguard Worker /**
8150*7c568831SAndroid Build Coastguard Worker * xmlXPathFalseFunction:
8151*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8152*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
8153*7c568831SAndroid Build Coastguard Worker *
8154*7c568831SAndroid Build Coastguard Worker * Implement the false() XPath function
8155*7c568831SAndroid Build Coastguard Worker * boolean false()
8156*7c568831SAndroid Build Coastguard Worker */
8157*7c568831SAndroid Build Coastguard Worker void
xmlXPathFalseFunction(xmlXPathParserContextPtr ctxt,int nargs)8158*7c568831SAndroid Build Coastguard Worker xmlXPathFalseFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8159*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(0);
8160*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 0));
8161*7c568831SAndroid Build Coastguard Worker }
8162*7c568831SAndroid Build Coastguard Worker
8163*7c568831SAndroid Build Coastguard Worker /**
8164*7c568831SAndroid Build Coastguard Worker * xmlXPathLangFunction:
8165*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8166*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
8167*7c568831SAndroid Build Coastguard Worker *
8168*7c568831SAndroid Build Coastguard Worker * Implement the lang() XPath function
8169*7c568831SAndroid Build Coastguard Worker * boolean lang(string)
8170*7c568831SAndroid Build Coastguard Worker * The lang function returns true or false depending on whether the
8171*7c568831SAndroid Build Coastguard Worker * language of the context node as specified by xml:lang attributes
8172*7c568831SAndroid Build Coastguard Worker * is the same as or is a sublanguage of the language specified by
8173*7c568831SAndroid Build Coastguard Worker * the argument string. The language of the context node is determined
8174*7c568831SAndroid Build Coastguard Worker * by the value of the xml:lang attribute on the context node, or, if
8175*7c568831SAndroid Build Coastguard Worker * the context node has no xml:lang attribute, by the value of the
8176*7c568831SAndroid Build Coastguard Worker * xml:lang attribute on the nearest ancestor of the context node that
8177*7c568831SAndroid Build Coastguard Worker * has an xml:lang attribute. If there is no such attribute, then lang
8178*7c568831SAndroid Build Coastguard Worker * returns false. If there is such an attribute, then lang returns
8179*7c568831SAndroid Build Coastguard Worker * true if the attribute value is equal to the argument ignoring case,
8180*7c568831SAndroid Build Coastguard Worker * or if there is some suffix starting with - such that the attribute
8181*7c568831SAndroid Build Coastguard Worker * value is equal to the argument ignoring that suffix of the attribute
8182*7c568831SAndroid Build Coastguard Worker * value and ignoring case.
8183*7c568831SAndroid Build Coastguard Worker */
8184*7c568831SAndroid Build Coastguard Worker void
xmlXPathLangFunction(xmlXPathParserContextPtr ctxt,int nargs)8185*7c568831SAndroid Build Coastguard Worker xmlXPathLangFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8186*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr val;
8187*7c568831SAndroid Build Coastguard Worker xmlNodePtr cur;
8188*7c568831SAndroid Build Coastguard Worker xmlChar *theLang;
8189*7c568831SAndroid Build Coastguard Worker const xmlChar *lang;
8190*7c568831SAndroid Build Coastguard Worker int ret = 0;
8191*7c568831SAndroid Build Coastguard Worker int i;
8192*7c568831SAndroid Build Coastguard Worker
8193*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(1);
8194*7c568831SAndroid Build Coastguard Worker CAST_TO_STRING;
8195*7c568831SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_STRING);
8196*7c568831SAndroid Build Coastguard Worker val = valuePop(ctxt);
8197*7c568831SAndroid Build Coastguard Worker lang = val->stringval;
8198*7c568831SAndroid Build Coastguard Worker cur = ctxt->context->node;
8199*7c568831SAndroid Build Coastguard Worker while (cur != NULL) {
8200*7c568831SAndroid Build Coastguard Worker if (xmlNodeGetAttrValue(cur, BAD_CAST "lang", XML_XML_NAMESPACE,
8201*7c568831SAndroid Build Coastguard Worker &theLang) < 0)
8202*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
8203*7c568831SAndroid Build Coastguard Worker if (theLang != NULL)
8204*7c568831SAndroid Build Coastguard Worker break;
8205*7c568831SAndroid Build Coastguard Worker cur = cur->parent;
8206*7c568831SAndroid Build Coastguard Worker }
8207*7c568831SAndroid Build Coastguard Worker if ((theLang != NULL) && (lang != NULL)) {
8208*7c568831SAndroid Build Coastguard Worker for (i = 0;lang[i] != 0;i++)
8209*7c568831SAndroid Build Coastguard Worker if (toupper(lang[i]) != toupper(theLang[i]))
8210*7c568831SAndroid Build Coastguard Worker goto not_equal;
8211*7c568831SAndroid Build Coastguard Worker if ((theLang[i] == 0) || (theLang[i] == '-'))
8212*7c568831SAndroid Build Coastguard Worker ret = 1;
8213*7c568831SAndroid Build Coastguard Worker }
8214*7c568831SAndroid Build Coastguard Worker not_equal:
8215*7c568831SAndroid Build Coastguard Worker if (theLang != NULL)
8216*7c568831SAndroid Build Coastguard Worker xmlFree((void *)theLang);
8217*7c568831SAndroid Build Coastguard Worker
8218*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, val);
8219*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, ret));
8220*7c568831SAndroid Build Coastguard Worker }
8221*7c568831SAndroid Build Coastguard Worker
8222*7c568831SAndroid Build Coastguard Worker /**
8223*7c568831SAndroid Build Coastguard Worker * xmlXPathNumberFunction:
8224*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8225*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
8226*7c568831SAndroid Build Coastguard Worker *
8227*7c568831SAndroid Build Coastguard Worker * Implement the number() XPath function
8228*7c568831SAndroid Build Coastguard Worker * number number(object?)
8229*7c568831SAndroid Build Coastguard Worker */
8230*7c568831SAndroid Build Coastguard Worker void
xmlXPathNumberFunction(xmlXPathParserContextPtr ctxt,int nargs)8231*7c568831SAndroid Build Coastguard Worker xmlXPathNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8232*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr cur;
8233*7c568831SAndroid Build Coastguard Worker double res;
8234*7c568831SAndroid Build Coastguard Worker
8235*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL) return;
8236*7c568831SAndroid Build Coastguard Worker if (nargs == 0) {
8237*7c568831SAndroid Build Coastguard Worker if (ctxt->context->node == NULL) {
8238*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, 0.0));
8239*7c568831SAndroid Build Coastguard Worker } else {
8240*7c568831SAndroid Build Coastguard Worker xmlChar* content = xmlNodeGetContent(ctxt->context->node);
8241*7c568831SAndroid Build Coastguard Worker if (content == NULL)
8242*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
8243*7c568831SAndroid Build Coastguard Worker
8244*7c568831SAndroid Build Coastguard Worker res = xmlXPathStringEvalNumber(content);
8245*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, res));
8246*7c568831SAndroid Build Coastguard Worker xmlFree(content);
8247*7c568831SAndroid Build Coastguard Worker }
8248*7c568831SAndroid Build Coastguard Worker return;
8249*7c568831SAndroid Build Coastguard Worker }
8250*7c568831SAndroid Build Coastguard Worker
8251*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(1);
8252*7c568831SAndroid Build Coastguard Worker cur = valuePop(ctxt);
8253*7c568831SAndroid Build Coastguard Worker if (cur->type != XPATH_NUMBER) {
8254*7c568831SAndroid Build Coastguard Worker double floatval;
8255*7c568831SAndroid Build Coastguard Worker
8256*7c568831SAndroid Build Coastguard Worker floatval = xmlXPathCastToNumberInternal(ctxt, cur);
8257*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, cur);
8258*7c568831SAndroid Build Coastguard Worker cur = xmlXPathCacheNewFloat(ctxt, floatval);
8259*7c568831SAndroid Build Coastguard Worker }
8260*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, cur);
8261*7c568831SAndroid Build Coastguard Worker }
8262*7c568831SAndroid Build Coastguard Worker
8263*7c568831SAndroid Build Coastguard Worker /**
8264*7c568831SAndroid Build Coastguard Worker * xmlXPathSumFunction:
8265*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8266*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
8267*7c568831SAndroid Build Coastguard Worker *
8268*7c568831SAndroid Build Coastguard Worker * Implement the sum() XPath function
8269*7c568831SAndroid Build Coastguard Worker * number sum(node-set)
8270*7c568831SAndroid Build Coastguard Worker * The sum function returns the sum of the values of the nodes in
8271*7c568831SAndroid Build Coastguard Worker * the argument node-set.
8272*7c568831SAndroid Build Coastguard Worker */
8273*7c568831SAndroid Build Coastguard Worker void
xmlXPathSumFunction(xmlXPathParserContextPtr ctxt,int nargs)8274*7c568831SAndroid Build Coastguard Worker xmlXPathSumFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8275*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr cur;
8276*7c568831SAndroid Build Coastguard Worker int i;
8277*7c568831SAndroid Build Coastguard Worker double res = 0.0;
8278*7c568831SAndroid Build Coastguard Worker
8279*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(1);
8280*7c568831SAndroid Build Coastguard Worker if ((ctxt->value == NULL) ||
8281*7c568831SAndroid Build Coastguard Worker ((ctxt->value->type != XPATH_NODESET) &&
8282*7c568831SAndroid Build Coastguard Worker (ctxt->value->type != XPATH_XSLT_TREE)))
8283*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_TYPE);
8284*7c568831SAndroid Build Coastguard Worker cur = valuePop(ctxt);
8285*7c568831SAndroid Build Coastguard Worker
8286*7c568831SAndroid Build Coastguard Worker if ((cur->nodesetval != NULL) && (cur->nodesetval->nodeNr != 0)) {
8287*7c568831SAndroid Build Coastguard Worker for (i = 0; i < cur->nodesetval->nodeNr; i++) {
8288*7c568831SAndroid Build Coastguard Worker res += xmlXPathNodeToNumberInternal(ctxt,
8289*7c568831SAndroid Build Coastguard Worker cur->nodesetval->nodeTab[i]);
8290*7c568831SAndroid Build Coastguard Worker }
8291*7c568831SAndroid Build Coastguard Worker }
8292*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, res));
8293*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, cur);
8294*7c568831SAndroid Build Coastguard Worker }
8295*7c568831SAndroid Build Coastguard Worker
8296*7c568831SAndroid Build Coastguard Worker /**
8297*7c568831SAndroid Build Coastguard Worker * xmlXPathFloorFunction:
8298*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8299*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
8300*7c568831SAndroid Build Coastguard Worker *
8301*7c568831SAndroid Build Coastguard Worker * Implement the floor() XPath function
8302*7c568831SAndroid Build Coastguard Worker * number floor(number)
8303*7c568831SAndroid Build Coastguard Worker * The floor function returns the largest (closest to positive infinity)
8304*7c568831SAndroid Build Coastguard Worker * number that is not greater than the argument and that is an integer.
8305*7c568831SAndroid Build Coastguard Worker */
8306*7c568831SAndroid Build Coastguard Worker void
xmlXPathFloorFunction(xmlXPathParserContextPtr ctxt,int nargs)8307*7c568831SAndroid Build Coastguard Worker xmlXPathFloorFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8308*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(1);
8309*7c568831SAndroid Build Coastguard Worker CAST_TO_NUMBER;
8310*7c568831SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_NUMBER);
8311*7c568831SAndroid Build Coastguard Worker
8312*7c568831SAndroid Build Coastguard Worker ctxt->value->floatval = floor(ctxt->value->floatval);
8313*7c568831SAndroid Build Coastguard Worker }
8314*7c568831SAndroid Build Coastguard Worker
8315*7c568831SAndroid Build Coastguard Worker /**
8316*7c568831SAndroid Build Coastguard Worker * xmlXPathCeilingFunction:
8317*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8318*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
8319*7c568831SAndroid Build Coastguard Worker *
8320*7c568831SAndroid Build Coastguard Worker * Implement the ceiling() XPath function
8321*7c568831SAndroid Build Coastguard Worker * number ceiling(number)
8322*7c568831SAndroid Build Coastguard Worker * The ceiling function returns the smallest (closest to negative infinity)
8323*7c568831SAndroid Build Coastguard Worker * number that is not less than the argument and that is an integer.
8324*7c568831SAndroid Build Coastguard Worker */
8325*7c568831SAndroid Build Coastguard Worker void
xmlXPathCeilingFunction(xmlXPathParserContextPtr ctxt,int nargs)8326*7c568831SAndroid Build Coastguard Worker xmlXPathCeilingFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8327*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(1);
8328*7c568831SAndroid Build Coastguard Worker CAST_TO_NUMBER;
8329*7c568831SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_NUMBER);
8330*7c568831SAndroid Build Coastguard Worker
8331*7c568831SAndroid Build Coastguard Worker #ifdef _AIX
8332*7c568831SAndroid Build Coastguard Worker /* Work around buggy ceil() function on AIX */
8333*7c568831SAndroid Build Coastguard Worker ctxt->value->floatval = copysign(ceil(ctxt->value->floatval), ctxt->value->floatval);
8334*7c568831SAndroid Build Coastguard Worker #else
8335*7c568831SAndroid Build Coastguard Worker ctxt->value->floatval = ceil(ctxt->value->floatval);
8336*7c568831SAndroid Build Coastguard Worker #endif
8337*7c568831SAndroid Build Coastguard Worker }
8338*7c568831SAndroid Build Coastguard Worker
8339*7c568831SAndroid Build Coastguard Worker /**
8340*7c568831SAndroid Build Coastguard Worker * xmlXPathRoundFunction:
8341*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8342*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
8343*7c568831SAndroid Build Coastguard Worker *
8344*7c568831SAndroid Build Coastguard Worker * Implement the round() XPath function
8345*7c568831SAndroid Build Coastguard Worker * number round(number)
8346*7c568831SAndroid Build Coastguard Worker * The round function returns the number that is closest to the
8347*7c568831SAndroid Build Coastguard Worker * argument and that is an integer. If there are two such numbers,
8348*7c568831SAndroid Build Coastguard Worker * then the one that is closest to positive infinity is returned.
8349*7c568831SAndroid Build Coastguard Worker */
8350*7c568831SAndroid Build Coastguard Worker void
xmlXPathRoundFunction(xmlXPathParserContextPtr ctxt,int nargs)8351*7c568831SAndroid Build Coastguard Worker xmlXPathRoundFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8352*7c568831SAndroid Build Coastguard Worker double f;
8353*7c568831SAndroid Build Coastguard Worker
8354*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(1);
8355*7c568831SAndroid Build Coastguard Worker CAST_TO_NUMBER;
8356*7c568831SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_NUMBER);
8357*7c568831SAndroid Build Coastguard Worker
8358*7c568831SAndroid Build Coastguard Worker f = ctxt->value->floatval;
8359*7c568831SAndroid Build Coastguard Worker
8360*7c568831SAndroid Build Coastguard Worker if ((f >= -0.5) && (f < 0.5)) {
8361*7c568831SAndroid Build Coastguard Worker /* Handles negative zero. */
8362*7c568831SAndroid Build Coastguard Worker ctxt->value->floatval *= 0.0;
8363*7c568831SAndroid Build Coastguard Worker }
8364*7c568831SAndroid Build Coastguard Worker else {
8365*7c568831SAndroid Build Coastguard Worker double rounded = floor(f);
8366*7c568831SAndroid Build Coastguard Worker if (f - rounded >= 0.5)
8367*7c568831SAndroid Build Coastguard Worker rounded += 1.0;
8368*7c568831SAndroid Build Coastguard Worker ctxt->value->floatval = rounded;
8369*7c568831SAndroid Build Coastguard Worker }
8370*7c568831SAndroid Build Coastguard Worker }
8371*7c568831SAndroid Build Coastguard Worker
8372*7c568831SAndroid Build Coastguard Worker /************************************************************************
8373*7c568831SAndroid Build Coastguard Worker * *
8374*7c568831SAndroid Build Coastguard Worker * The Parser *
8375*7c568831SAndroid Build Coastguard Worker * *
8376*7c568831SAndroid Build Coastguard Worker ************************************************************************/
8377*7c568831SAndroid Build Coastguard Worker
8378*7c568831SAndroid Build Coastguard Worker /*
8379*7c568831SAndroid Build Coastguard Worker * a few forward declarations since we use a recursive call based
8380*7c568831SAndroid Build Coastguard Worker * implementation.
8381*7c568831SAndroid Build Coastguard Worker */
8382*7c568831SAndroid Build Coastguard Worker static void xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt, int sort);
8383*7c568831SAndroid Build Coastguard Worker static void xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter);
8384*7c568831SAndroid Build Coastguard Worker static void xmlXPathCompLocationPath(xmlXPathParserContextPtr ctxt);
8385*7c568831SAndroid Build Coastguard Worker static void xmlXPathCompRelativeLocationPath(xmlXPathParserContextPtr ctxt);
8386*7c568831SAndroid Build Coastguard Worker static xmlChar * xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt,
8387*7c568831SAndroid Build Coastguard Worker int qualified);
8388*7c568831SAndroid Build Coastguard Worker
8389*7c568831SAndroid Build Coastguard Worker /**
8390*7c568831SAndroid Build Coastguard Worker * xmlXPathCurrentChar:
8391*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath parser context
8392*7c568831SAndroid Build Coastguard Worker * @cur: pointer to the beginning of the char
8393*7c568831SAndroid Build Coastguard Worker * @len: pointer to the length of the char read
8394*7c568831SAndroid Build Coastguard Worker *
8395*7c568831SAndroid Build Coastguard Worker * The current char value, if using UTF-8 this may actually span multiple
8396*7c568831SAndroid Build Coastguard Worker * bytes in the input buffer.
8397*7c568831SAndroid Build Coastguard Worker *
8398*7c568831SAndroid Build Coastguard Worker * Returns the current char value and its length
8399*7c568831SAndroid Build Coastguard Worker */
8400*7c568831SAndroid Build Coastguard Worker
8401*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCurrentChar(xmlXPathParserContextPtr ctxt,int * len)8402*7c568831SAndroid Build Coastguard Worker xmlXPathCurrentChar(xmlXPathParserContextPtr ctxt, int *len) {
8403*7c568831SAndroid Build Coastguard Worker unsigned char c;
8404*7c568831SAndroid Build Coastguard Worker unsigned int val;
8405*7c568831SAndroid Build Coastguard Worker const xmlChar *cur;
8406*7c568831SAndroid Build Coastguard Worker
8407*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
8408*7c568831SAndroid Build Coastguard Worker return(0);
8409*7c568831SAndroid Build Coastguard Worker cur = ctxt->cur;
8410*7c568831SAndroid Build Coastguard Worker
8411*7c568831SAndroid Build Coastguard Worker /*
8412*7c568831SAndroid Build Coastguard Worker * We are supposed to handle UTF8, check it's valid
8413*7c568831SAndroid Build Coastguard Worker * From rfc2044: encoding of the Unicode values on UTF-8:
8414*7c568831SAndroid Build Coastguard Worker *
8415*7c568831SAndroid Build Coastguard Worker * UCS-4 range (hex.) UTF-8 octet sequence (binary)
8416*7c568831SAndroid Build Coastguard Worker * 0000 0000-0000 007F 0xxxxxxx
8417*7c568831SAndroid Build Coastguard Worker * 0000 0080-0000 07FF 110xxxxx 10xxxxxx
8418*7c568831SAndroid Build Coastguard Worker * 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
8419*7c568831SAndroid Build Coastguard Worker *
8420*7c568831SAndroid Build Coastguard Worker * Check for the 0x110000 limit too
8421*7c568831SAndroid Build Coastguard Worker */
8422*7c568831SAndroid Build Coastguard Worker c = *cur;
8423*7c568831SAndroid Build Coastguard Worker if (c & 0x80) {
8424*7c568831SAndroid Build Coastguard Worker if ((cur[1] & 0xc0) != 0x80)
8425*7c568831SAndroid Build Coastguard Worker goto encoding_error;
8426*7c568831SAndroid Build Coastguard Worker if ((c & 0xe0) == 0xe0) {
8427*7c568831SAndroid Build Coastguard Worker
8428*7c568831SAndroid Build Coastguard Worker if ((cur[2] & 0xc0) != 0x80)
8429*7c568831SAndroid Build Coastguard Worker goto encoding_error;
8430*7c568831SAndroid Build Coastguard Worker if ((c & 0xf0) == 0xf0) {
8431*7c568831SAndroid Build Coastguard Worker if (((c & 0xf8) != 0xf0) ||
8432*7c568831SAndroid Build Coastguard Worker ((cur[3] & 0xc0) != 0x80))
8433*7c568831SAndroid Build Coastguard Worker goto encoding_error;
8434*7c568831SAndroid Build Coastguard Worker /* 4-byte code */
8435*7c568831SAndroid Build Coastguard Worker *len = 4;
8436*7c568831SAndroid Build Coastguard Worker val = (cur[0] & 0x7) << 18;
8437*7c568831SAndroid Build Coastguard Worker val |= (cur[1] & 0x3f) << 12;
8438*7c568831SAndroid Build Coastguard Worker val |= (cur[2] & 0x3f) << 6;
8439*7c568831SAndroid Build Coastguard Worker val |= cur[3] & 0x3f;
8440*7c568831SAndroid Build Coastguard Worker } else {
8441*7c568831SAndroid Build Coastguard Worker /* 3-byte code */
8442*7c568831SAndroid Build Coastguard Worker *len = 3;
8443*7c568831SAndroid Build Coastguard Worker val = (cur[0] & 0xf) << 12;
8444*7c568831SAndroid Build Coastguard Worker val |= (cur[1] & 0x3f) << 6;
8445*7c568831SAndroid Build Coastguard Worker val |= cur[2] & 0x3f;
8446*7c568831SAndroid Build Coastguard Worker }
8447*7c568831SAndroid Build Coastguard Worker } else {
8448*7c568831SAndroid Build Coastguard Worker /* 2-byte code */
8449*7c568831SAndroid Build Coastguard Worker *len = 2;
8450*7c568831SAndroid Build Coastguard Worker val = (cur[0] & 0x1f) << 6;
8451*7c568831SAndroid Build Coastguard Worker val |= cur[1] & 0x3f;
8452*7c568831SAndroid Build Coastguard Worker }
8453*7c568831SAndroid Build Coastguard Worker if (!IS_CHAR(val)) {
8454*7c568831SAndroid Build Coastguard Worker XP_ERROR0(XPATH_INVALID_CHAR_ERROR);
8455*7c568831SAndroid Build Coastguard Worker }
8456*7c568831SAndroid Build Coastguard Worker return(val);
8457*7c568831SAndroid Build Coastguard Worker } else {
8458*7c568831SAndroid Build Coastguard Worker /* 1-byte code */
8459*7c568831SAndroid Build Coastguard Worker *len = 1;
8460*7c568831SAndroid Build Coastguard Worker return(*cur);
8461*7c568831SAndroid Build Coastguard Worker }
8462*7c568831SAndroid Build Coastguard Worker encoding_error:
8463*7c568831SAndroid Build Coastguard Worker /*
8464*7c568831SAndroid Build Coastguard Worker * If we detect an UTF8 error that probably means that the
8465*7c568831SAndroid Build Coastguard Worker * input encoding didn't get properly advertised in the
8466*7c568831SAndroid Build Coastguard Worker * declaration header. Report the error and switch the encoding
8467*7c568831SAndroid Build Coastguard Worker * to ISO-Latin-1 (if you don't like this policy, just declare the
8468*7c568831SAndroid Build Coastguard Worker * encoding !)
8469*7c568831SAndroid Build Coastguard Worker */
8470*7c568831SAndroid Build Coastguard Worker *len = 0;
8471*7c568831SAndroid Build Coastguard Worker XP_ERROR0(XPATH_ENCODING_ERROR);
8472*7c568831SAndroid Build Coastguard Worker }
8473*7c568831SAndroid Build Coastguard Worker
8474*7c568831SAndroid Build Coastguard Worker /**
8475*7c568831SAndroid Build Coastguard Worker * xmlXPathParseNCName:
8476*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8477*7c568831SAndroid Build Coastguard Worker *
8478*7c568831SAndroid Build Coastguard Worker * parse an XML namespace non qualified name.
8479*7c568831SAndroid Build Coastguard Worker *
8480*7c568831SAndroid Build Coastguard Worker * [NS 3] NCName ::= (Letter | '_') (NCNameChar)*
8481*7c568831SAndroid Build Coastguard Worker *
8482*7c568831SAndroid Build Coastguard Worker * [NS 4] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
8483*7c568831SAndroid Build Coastguard Worker * CombiningChar | Extender
8484*7c568831SAndroid Build Coastguard Worker *
8485*7c568831SAndroid Build Coastguard Worker * Returns the namespace name or NULL
8486*7c568831SAndroid Build Coastguard Worker */
8487*7c568831SAndroid Build Coastguard Worker
8488*7c568831SAndroid Build Coastguard Worker xmlChar *
xmlXPathParseNCName(xmlXPathParserContextPtr ctxt)8489*7c568831SAndroid Build Coastguard Worker xmlXPathParseNCName(xmlXPathParserContextPtr ctxt) {
8490*7c568831SAndroid Build Coastguard Worker const xmlChar *in;
8491*7c568831SAndroid Build Coastguard Worker xmlChar *ret;
8492*7c568831SAndroid Build Coastguard Worker int count = 0;
8493*7c568831SAndroid Build Coastguard Worker
8494*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->cur == NULL)) return(NULL);
8495*7c568831SAndroid Build Coastguard Worker /*
8496*7c568831SAndroid Build Coastguard Worker * Accelerator for simple ASCII names
8497*7c568831SAndroid Build Coastguard Worker */
8498*7c568831SAndroid Build Coastguard Worker in = ctxt->cur;
8499*7c568831SAndroid Build Coastguard Worker if (((*in >= 0x61) && (*in <= 0x7A)) ||
8500*7c568831SAndroid Build Coastguard Worker ((*in >= 0x41) && (*in <= 0x5A)) ||
8501*7c568831SAndroid Build Coastguard Worker (*in == '_')) {
8502*7c568831SAndroid Build Coastguard Worker in++;
8503*7c568831SAndroid Build Coastguard Worker while (((*in >= 0x61) && (*in <= 0x7A)) ||
8504*7c568831SAndroid Build Coastguard Worker ((*in >= 0x41) && (*in <= 0x5A)) ||
8505*7c568831SAndroid Build Coastguard Worker ((*in >= 0x30) && (*in <= 0x39)) ||
8506*7c568831SAndroid Build Coastguard Worker (*in == '_') || (*in == '.') ||
8507*7c568831SAndroid Build Coastguard Worker (*in == '-'))
8508*7c568831SAndroid Build Coastguard Worker in++;
8509*7c568831SAndroid Build Coastguard Worker if ((*in == ' ') || (*in == '>') || (*in == '/') ||
8510*7c568831SAndroid Build Coastguard Worker (*in == '[') || (*in == ']') || (*in == ':') ||
8511*7c568831SAndroid Build Coastguard Worker (*in == '@') || (*in == '*')) {
8512*7c568831SAndroid Build Coastguard Worker count = in - ctxt->cur;
8513*7c568831SAndroid Build Coastguard Worker if (count == 0)
8514*7c568831SAndroid Build Coastguard Worker return(NULL);
8515*7c568831SAndroid Build Coastguard Worker ret = xmlStrndup(ctxt->cur, count);
8516*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
8517*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
8518*7c568831SAndroid Build Coastguard Worker ctxt->cur = in;
8519*7c568831SAndroid Build Coastguard Worker return(ret);
8520*7c568831SAndroid Build Coastguard Worker }
8521*7c568831SAndroid Build Coastguard Worker }
8522*7c568831SAndroid Build Coastguard Worker return(xmlXPathParseNameComplex(ctxt, 0));
8523*7c568831SAndroid Build Coastguard Worker }
8524*7c568831SAndroid Build Coastguard Worker
8525*7c568831SAndroid Build Coastguard Worker
8526*7c568831SAndroid Build Coastguard Worker /**
8527*7c568831SAndroid Build Coastguard Worker * xmlXPathParseQName:
8528*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8529*7c568831SAndroid Build Coastguard Worker * @prefix: a xmlChar **
8530*7c568831SAndroid Build Coastguard Worker *
8531*7c568831SAndroid Build Coastguard Worker * parse an XML qualified name
8532*7c568831SAndroid Build Coastguard Worker *
8533*7c568831SAndroid Build Coastguard Worker * [NS 5] QName ::= (Prefix ':')? LocalPart
8534*7c568831SAndroid Build Coastguard Worker *
8535*7c568831SAndroid Build Coastguard Worker * [NS 6] Prefix ::= NCName
8536*7c568831SAndroid Build Coastguard Worker *
8537*7c568831SAndroid Build Coastguard Worker * [NS 7] LocalPart ::= NCName
8538*7c568831SAndroid Build Coastguard Worker *
8539*7c568831SAndroid Build Coastguard Worker * Returns the function returns the local part, and prefix is updated
8540*7c568831SAndroid Build Coastguard Worker * to get the Prefix if any.
8541*7c568831SAndroid Build Coastguard Worker */
8542*7c568831SAndroid Build Coastguard Worker
8543*7c568831SAndroid Build Coastguard Worker static xmlChar *
xmlXPathParseQName(xmlXPathParserContextPtr ctxt,xmlChar ** prefix)8544*7c568831SAndroid Build Coastguard Worker xmlXPathParseQName(xmlXPathParserContextPtr ctxt, xmlChar **prefix) {
8545*7c568831SAndroid Build Coastguard Worker xmlChar *ret = NULL;
8546*7c568831SAndroid Build Coastguard Worker
8547*7c568831SAndroid Build Coastguard Worker *prefix = NULL;
8548*7c568831SAndroid Build Coastguard Worker ret = xmlXPathParseNCName(ctxt);
8549*7c568831SAndroid Build Coastguard Worker if (ret && CUR == ':') {
8550*7c568831SAndroid Build Coastguard Worker *prefix = ret;
8551*7c568831SAndroid Build Coastguard Worker NEXT;
8552*7c568831SAndroid Build Coastguard Worker ret = xmlXPathParseNCName(ctxt);
8553*7c568831SAndroid Build Coastguard Worker }
8554*7c568831SAndroid Build Coastguard Worker return(ret);
8555*7c568831SAndroid Build Coastguard Worker }
8556*7c568831SAndroid Build Coastguard Worker
8557*7c568831SAndroid Build Coastguard Worker /**
8558*7c568831SAndroid Build Coastguard Worker * xmlXPathParseName:
8559*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8560*7c568831SAndroid Build Coastguard Worker *
8561*7c568831SAndroid Build Coastguard Worker * parse an XML name
8562*7c568831SAndroid Build Coastguard Worker *
8563*7c568831SAndroid Build Coastguard Worker * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
8564*7c568831SAndroid Build Coastguard Worker * CombiningChar | Extender
8565*7c568831SAndroid Build Coastguard Worker *
8566*7c568831SAndroid Build Coastguard Worker * [5] Name ::= (Letter | '_' | ':') (NameChar)*
8567*7c568831SAndroid Build Coastguard Worker *
8568*7c568831SAndroid Build Coastguard Worker * Returns the namespace name or NULL
8569*7c568831SAndroid Build Coastguard Worker */
8570*7c568831SAndroid Build Coastguard Worker
8571*7c568831SAndroid Build Coastguard Worker xmlChar *
xmlXPathParseName(xmlXPathParserContextPtr ctxt)8572*7c568831SAndroid Build Coastguard Worker xmlXPathParseName(xmlXPathParserContextPtr ctxt) {
8573*7c568831SAndroid Build Coastguard Worker const xmlChar *in;
8574*7c568831SAndroid Build Coastguard Worker xmlChar *ret;
8575*7c568831SAndroid Build Coastguard Worker size_t count = 0;
8576*7c568831SAndroid Build Coastguard Worker
8577*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->cur == NULL)) return(NULL);
8578*7c568831SAndroid Build Coastguard Worker /*
8579*7c568831SAndroid Build Coastguard Worker * Accelerator for simple ASCII names
8580*7c568831SAndroid Build Coastguard Worker */
8581*7c568831SAndroid Build Coastguard Worker in = ctxt->cur;
8582*7c568831SAndroid Build Coastguard Worker if (((*in >= 0x61) && (*in <= 0x7A)) ||
8583*7c568831SAndroid Build Coastguard Worker ((*in >= 0x41) && (*in <= 0x5A)) ||
8584*7c568831SAndroid Build Coastguard Worker (*in == '_') || (*in == ':')) {
8585*7c568831SAndroid Build Coastguard Worker in++;
8586*7c568831SAndroid Build Coastguard Worker while (((*in >= 0x61) && (*in <= 0x7A)) ||
8587*7c568831SAndroid Build Coastguard Worker ((*in >= 0x41) && (*in <= 0x5A)) ||
8588*7c568831SAndroid Build Coastguard Worker ((*in >= 0x30) && (*in <= 0x39)) ||
8589*7c568831SAndroid Build Coastguard Worker (*in == '_') || (*in == '-') ||
8590*7c568831SAndroid Build Coastguard Worker (*in == ':') || (*in == '.'))
8591*7c568831SAndroid Build Coastguard Worker in++;
8592*7c568831SAndroid Build Coastguard Worker if ((*in > 0) && (*in < 0x80)) {
8593*7c568831SAndroid Build Coastguard Worker count = in - ctxt->cur;
8594*7c568831SAndroid Build Coastguard Worker if (count > XML_MAX_NAME_LENGTH) {
8595*7c568831SAndroid Build Coastguard Worker ctxt->cur = in;
8596*7c568831SAndroid Build Coastguard Worker XP_ERRORNULL(XPATH_EXPR_ERROR);
8597*7c568831SAndroid Build Coastguard Worker }
8598*7c568831SAndroid Build Coastguard Worker ret = xmlStrndup(ctxt->cur, count);
8599*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
8600*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
8601*7c568831SAndroid Build Coastguard Worker ctxt->cur = in;
8602*7c568831SAndroid Build Coastguard Worker return(ret);
8603*7c568831SAndroid Build Coastguard Worker }
8604*7c568831SAndroid Build Coastguard Worker }
8605*7c568831SAndroid Build Coastguard Worker return(xmlXPathParseNameComplex(ctxt, 1));
8606*7c568831SAndroid Build Coastguard Worker }
8607*7c568831SAndroid Build Coastguard Worker
8608*7c568831SAndroid Build Coastguard Worker static xmlChar *
xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt,int qualified)8609*7c568831SAndroid Build Coastguard Worker xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) {
8610*7c568831SAndroid Build Coastguard Worker xmlChar *ret;
8611*7c568831SAndroid Build Coastguard Worker xmlChar buf[XML_MAX_NAMELEN + 5];
8612*7c568831SAndroid Build Coastguard Worker int len = 0, l;
8613*7c568831SAndroid Build Coastguard Worker int c;
8614*7c568831SAndroid Build Coastguard Worker
8615*7c568831SAndroid Build Coastguard Worker /*
8616*7c568831SAndroid Build Coastguard Worker * Handler for more complex cases
8617*7c568831SAndroid Build Coastguard Worker */
8618*7c568831SAndroid Build Coastguard Worker c = CUR_CHAR(l);
8619*7c568831SAndroid Build Coastguard Worker if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
8620*7c568831SAndroid Build Coastguard Worker (c == '[') || (c == ']') || (c == '@') || /* accelerators */
8621*7c568831SAndroid Build Coastguard Worker (c == '*') || /* accelerators */
8622*7c568831SAndroid Build Coastguard Worker (!IS_LETTER(c) && (c != '_') &&
8623*7c568831SAndroid Build Coastguard Worker ((!qualified) || (c != ':')))) {
8624*7c568831SAndroid Build Coastguard Worker return(NULL);
8625*7c568831SAndroid Build Coastguard Worker }
8626*7c568831SAndroid Build Coastguard Worker
8627*7c568831SAndroid Build Coastguard Worker while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
8628*7c568831SAndroid Build Coastguard Worker ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
8629*7c568831SAndroid Build Coastguard Worker (c == '.') || (c == '-') ||
8630*7c568831SAndroid Build Coastguard Worker (c == '_') || ((qualified) && (c == ':')) ||
8631*7c568831SAndroid Build Coastguard Worker (IS_COMBINING(c)) ||
8632*7c568831SAndroid Build Coastguard Worker (IS_EXTENDER(c)))) {
8633*7c568831SAndroid Build Coastguard Worker COPY_BUF(buf,len,c);
8634*7c568831SAndroid Build Coastguard Worker NEXTL(l);
8635*7c568831SAndroid Build Coastguard Worker c = CUR_CHAR(l);
8636*7c568831SAndroid Build Coastguard Worker if (len >= XML_MAX_NAMELEN) {
8637*7c568831SAndroid Build Coastguard Worker /*
8638*7c568831SAndroid Build Coastguard Worker * Okay someone managed to make a huge name, so he's ready to pay
8639*7c568831SAndroid Build Coastguard Worker * for the processing speed.
8640*7c568831SAndroid Build Coastguard Worker */
8641*7c568831SAndroid Build Coastguard Worker xmlChar *buffer;
8642*7c568831SAndroid Build Coastguard Worker int max = len * 2;
8643*7c568831SAndroid Build Coastguard Worker
8644*7c568831SAndroid Build Coastguard Worker if (len > XML_MAX_NAME_LENGTH) {
8645*7c568831SAndroid Build Coastguard Worker XP_ERRORNULL(XPATH_EXPR_ERROR);
8646*7c568831SAndroid Build Coastguard Worker }
8647*7c568831SAndroid Build Coastguard Worker buffer = xmlMalloc(max);
8648*7c568831SAndroid Build Coastguard Worker if (buffer == NULL) {
8649*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
8650*7c568831SAndroid Build Coastguard Worker return(NULL);
8651*7c568831SAndroid Build Coastguard Worker }
8652*7c568831SAndroid Build Coastguard Worker memcpy(buffer, buf, len);
8653*7c568831SAndroid Build Coastguard Worker while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigname.xml */
8654*7c568831SAndroid Build Coastguard Worker (c == '.') || (c == '-') ||
8655*7c568831SAndroid Build Coastguard Worker (c == '_') || ((qualified) && (c == ':')) ||
8656*7c568831SAndroid Build Coastguard Worker (IS_COMBINING(c)) ||
8657*7c568831SAndroid Build Coastguard Worker (IS_EXTENDER(c))) {
8658*7c568831SAndroid Build Coastguard Worker if (len + 10 > max) {
8659*7c568831SAndroid Build Coastguard Worker xmlChar *tmp;
8660*7c568831SAndroid Build Coastguard Worker if (max > XML_MAX_NAME_LENGTH) {
8661*7c568831SAndroid Build Coastguard Worker xmlFree(buffer);
8662*7c568831SAndroid Build Coastguard Worker XP_ERRORNULL(XPATH_EXPR_ERROR);
8663*7c568831SAndroid Build Coastguard Worker }
8664*7c568831SAndroid Build Coastguard Worker max *= 2;
8665*7c568831SAndroid Build Coastguard Worker tmp = (xmlChar *) xmlRealloc(buffer, max);
8666*7c568831SAndroid Build Coastguard Worker if (tmp == NULL) {
8667*7c568831SAndroid Build Coastguard Worker xmlFree(buffer);
8668*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
8669*7c568831SAndroid Build Coastguard Worker return(NULL);
8670*7c568831SAndroid Build Coastguard Worker }
8671*7c568831SAndroid Build Coastguard Worker buffer = tmp;
8672*7c568831SAndroid Build Coastguard Worker }
8673*7c568831SAndroid Build Coastguard Worker COPY_BUF(buffer,len,c);
8674*7c568831SAndroid Build Coastguard Worker NEXTL(l);
8675*7c568831SAndroid Build Coastguard Worker c = CUR_CHAR(l);
8676*7c568831SAndroid Build Coastguard Worker }
8677*7c568831SAndroid Build Coastguard Worker buffer[len] = 0;
8678*7c568831SAndroid Build Coastguard Worker return(buffer);
8679*7c568831SAndroid Build Coastguard Worker }
8680*7c568831SAndroid Build Coastguard Worker }
8681*7c568831SAndroid Build Coastguard Worker if (len == 0)
8682*7c568831SAndroid Build Coastguard Worker return(NULL);
8683*7c568831SAndroid Build Coastguard Worker ret = xmlStrndup(buf, len);
8684*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
8685*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
8686*7c568831SAndroid Build Coastguard Worker return(ret);
8687*7c568831SAndroid Build Coastguard Worker }
8688*7c568831SAndroid Build Coastguard Worker
8689*7c568831SAndroid Build Coastguard Worker #define MAX_FRAC 20
8690*7c568831SAndroid Build Coastguard Worker
8691*7c568831SAndroid Build Coastguard Worker /**
8692*7c568831SAndroid Build Coastguard Worker * xmlXPathStringEvalNumber:
8693*7c568831SAndroid Build Coastguard Worker * @str: A string to scan
8694*7c568831SAndroid Build Coastguard Worker *
8695*7c568831SAndroid Build Coastguard Worker * [30a] Float ::= Number ('e' Digits?)?
8696*7c568831SAndroid Build Coastguard Worker *
8697*7c568831SAndroid Build Coastguard Worker * [30] Number ::= Digits ('.' Digits?)?
8698*7c568831SAndroid Build Coastguard Worker * | '.' Digits
8699*7c568831SAndroid Build Coastguard Worker * [31] Digits ::= [0-9]+
8700*7c568831SAndroid Build Coastguard Worker *
8701*7c568831SAndroid Build Coastguard Worker * Compile a Number in the string
8702*7c568831SAndroid Build Coastguard Worker * In complement of the Number expression, this function also handles
8703*7c568831SAndroid Build Coastguard Worker * negative values : '-' Number.
8704*7c568831SAndroid Build Coastguard Worker *
8705*7c568831SAndroid Build Coastguard Worker * Returns the double value.
8706*7c568831SAndroid Build Coastguard Worker */
8707*7c568831SAndroid Build Coastguard Worker double
xmlXPathStringEvalNumber(const xmlChar * str)8708*7c568831SAndroid Build Coastguard Worker xmlXPathStringEvalNumber(const xmlChar *str) {
8709*7c568831SAndroid Build Coastguard Worker const xmlChar *cur = str;
8710*7c568831SAndroid Build Coastguard Worker double ret;
8711*7c568831SAndroid Build Coastguard Worker int ok = 0;
8712*7c568831SAndroid Build Coastguard Worker int isneg = 0;
8713*7c568831SAndroid Build Coastguard Worker int exponent = 0;
8714*7c568831SAndroid Build Coastguard Worker int is_exponent_negative = 0;
8715*7c568831SAndroid Build Coastguard Worker #ifdef __GNUC__
8716*7c568831SAndroid Build Coastguard Worker unsigned long tmp = 0;
8717*7c568831SAndroid Build Coastguard Worker double temp;
8718*7c568831SAndroid Build Coastguard Worker #endif
8719*7c568831SAndroid Build Coastguard Worker if (cur == NULL) return(0);
8720*7c568831SAndroid Build Coastguard Worker while (IS_BLANK_CH(*cur)) cur++;
8721*7c568831SAndroid Build Coastguard Worker if (*cur == '-') {
8722*7c568831SAndroid Build Coastguard Worker isneg = 1;
8723*7c568831SAndroid Build Coastguard Worker cur++;
8724*7c568831SAndroid Build Coastguard Worker }
8725*7c568831SAndroid Build Coastguard Worker if ((*cur != '.') && ((*cur < '0') || (*cur > '9'))) {
8726*7c568831SAndroid Build Coastguard Worker return(xmlXPathNAN);
8727*7c568831SAndroid Build Coastguard Worker }
8728*7c568831SAndroid Build Coastguard Worker
8729*7c568831SAndroid Build Coastguard Worker #ifdef __GNUC__
8730*7c568831SAndroid Build Coastguard Worker /*
8731*7c568831SAndroid Build Coastguard Worker * tmp/temp is a workaround against a gcc compiler bug
8732*7c568831SAndroid Build Coastguard Worker * http://veillard.com/gcc.bug
8733*7c568831SAndroid Build Coastguard Worker */
8734*7c568831SAndroid Build Coastguard Worker ret = 0;
8735*7c568831SAndroid Build Coastguard Worker while ((*cur >= '0') && (*cur <= '9')) {
8736*7c568831SAndroid Build Coastguard Worker ret = ret * 10;
8737*7c568831SAndroid Build Coastguard Worker tmp = (*cur - '0');
8738*7c568831SAndroid Build Coastguard Worker ok = 1;
8739*7c568831SAndroid Build Coastguard Worker cur++;
8740*7c568831SAndroid Build Coastguard Worker temp = (double) tmp;
8741*7c568831SAndroid Build Coastguard Worker ret = ret + temp;
8742*7c568831SAndroid Build Coastguard Worker }
8743*7c568831SAndroid Build Coastguard Worker #else
8744*7c568831SAndroid Build Coastguard Worker ret = 0;
8745*7c568831SAndroid Build Coastguard Worker while ((*cur >= '0') && (*cur <= '9')) {
8746*7c568831SAndroid Build Coastguard Worker ret = ret * 10 + (*cur - '0');
8747*7c568831SAndroid Build Coastguard Worker ok = 1;
8748*7c568831SAndroid Build Coastguard Worker cur++;
8749*7c568831SAndroid Build Coastguard Worker }
8750*7c568831SAndroid Build Coastguard Worker #endif
8751*7c568831SAndroid Build Coastguard Worker
8752*7c568831SAndroid Build Coastguard Worker if (*cur == '.') {
8753*7c568831SAndroid Build Coastguard Worker int v, frac = 0, max;
8754*7c568831SAndroid Build Coastguard Worker double fraction = 0;
8755*7c568831SAndroid Build Coastguard Worker
8756*7c568831SAndroid Build Coastguard Worker cur++;
8757*7c568831SAndroid Build Coastguard Worker if (((*cur < '0') || (*cur > '9')) && (!ok)) {
8758*7c568831SAndroid Build Coastguard Worker return(xmlXPathNAN);
8759*7c568831SAndroid Build Coastguard Worker }
8760*7c568831SAndroid Build Coastguard Worker while (*cur == '0') {
8761*7c568831SAndroid Build Coastguard Worker frac = frac + 1;
8762*7c568831SAndroid Build Coastguard Worker cur++;
8763*7c568831SAndroid Build Coastguard Worker }
8764*7c568831SAndroid Build Coastguard Worker max = frac + MAX_FRAC;
8765*7c568831SAndroid Build Coastguard Worker while (((*cur >= '0') && (*cur <= '9')) && (frac < max)) {
8766*7c568831SAndroid Build Coastguard Worker v = (*cur - '0');
8767*7c568831SAndroid Build Coastguard Worker fraction = fraction * 10 + v;
8768*7c568831SAndroid Build Coastguard Worker frac = frac + 1;
8769*7c568831SAndroid Build Coastguard Worker cur++;
8770*7c568831SAndroid Build Coastguard Worker }
8771*7c568831SAndroid Build Coastguard Worker fraction /= pow(10.0, frac);
8772*7c568831SAndroid Build Coastguard Worker ret = ret + fraction;
8773*7c568831SAndroid Build Coastguard Worker while ((*cur >= '0') && (*cur <= '9'))
8774*7c568831SAndroid Build Coastguard Worker cur++;
8775*7c568831SAndroid Build Coastguard Worker }
8776*7c568831SAndroid Build Coastguard Worker if ((*cur == 'e') || (*cur == 'E')) {
8777*7c568831SAndroid Build Coastguard Worker cur++;
8778*7c568831SAndroid Build Coastguard Worker if (*cur == '-') {
8779*7c568831SAndroid Build Coastguard Worker is_exponent_negative = 1;
8780*7c568831SAndroid Build Coastguard Worker cur++;
8781*7c568831SAndroid Build Coastguard Worker } else if (*cur == '+') {
8782*7c568831SAndroid Build Coastguard Worker cur++;
8783*7c568831SAndroid Build Coastguard Worker }
8784*7c568831SAndroid Build Coastguard Worker while ((*cur >= '0') && (*cur <= '9')) {
8785*7c568831SAndroid Build Coastguard Worker if (exponent < 1000000)
8786*7c568831SAndroid Build Coastguard Worker exponent = exponent * 10 + (*cur - '0');
8787*7c568831SAndroid Build Coastguard Worker cur++;
8788*7c568831SAndroid Build Coastguard Worker }
8789*7c568831SAndroid Build Coastguard Worker }
8790*7c568831SAndroid Build Coastguard Worker while (IS_BLANK_CH(*cur)) cur++;
8791*7c568831SAndroid Build Coastguard Worker if (*cur != 0) return(xmlXPathNAN);
8792*7c568831SAndroid Build Coastguard Worker if (isneg) ret = -ret;
8793*7c568831SAndroid Build Coastguard Worker if (is_exponent_negative) exponent = -exponent;
8794*7c568831SAndroid Build Coastguard Worker ret *= pow(10.0, (double)exponent);
8795*7c568831SAndroid Build Coastguard Worker return(ret);
8796*7c568831SAndroid Build Coastguard Worker }
8797*7c568831SAndroid Build Coastguard Worker
8798*7c568831SAndroid Build Coastguard Worker /**
8799*7c568831SAndroid Build Coastguard Worker * xmlXPathCompNumber:
8800*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8801*7c568831SAndroid Build Coastguard Worker *
8802*7c568831SAndroid Build Coastguard Worker * [30] Number ::= Digits ('.' Digits?)?
8803*7c568831SAndroid Build Coastguard Worker * | '.' Digits
8804*7c568831SAndroid Build Coastguard Worker * [31] Digits ::= [0-9]+
8805*7c568831SAndroid Build Coastguard Worker *
8806*7c568831SAndroid Build Coastguard Worker * Compile a Number, then push it on the stack
8807*7c568831SAndroid Build Coastguard Worker *
8808*7c568831SAndroid Build Coastguard Worker */
8809*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompNumber(xmlXPathParserContextPtr ctxt)8810*7c568831SAndroid Build Coastguard Worker xmlXPathCompNumber(xmlXPathParserContextPtr ctxt)
8811*7c568831SAndroid Build Coastguard Worker {
8812*7c568831SAndroid Build Coastguard Worker double ret = 0.0;
8813*7c568831SAndroid Build Coastguard Worker int ok = 0;
8814*7c568831SAndroid Build Coastguard Worker int exponent = 0;
8815*7c568831SAndroid Build Coastguard Worker int is_exponent_negative = 0;
8816*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr num;
8817*7c568831SAndroid Build Coastguard Worker #ifdef __GNUC__
8818*7c568831SAndroid Build Coastguard Worker unsigned long tmp = 0;
8819*7c568831SAndroid Build Coastguard Worker double temp;
8820*7c568831SAndroid Build Coastguard Worker #endif
8821*7c568831SAndroid Build Coastguard Worker
8822*7c568831SAndroid Build Coastguard Worker CHECK_ERROR;
8823*7c568831SAndroid Build Coastguard Worker if ((CUR != '.') && ((CUR < '0') || (CUR > '9'))) {
8824*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_NUMBER_ERROR);
8825*7c568831SAndroid Build Coastguard Worker }
8826*7c568831SAndroid Build Coastguard Worker #ifdef __GNUC__
8827*7c568831SAndroid Build Coastguard Worker /*
8828*7c568831SAndroid Build Coastguard Worker * tmp/temp is a workaround against a gcc compiler bug
8829*7c568831SAndroid Build Coastguard Worker * http://veillard.com/gcc.bug
8830*7c568831SAndroid Build Coastguard Worker */
8831*7c568831SAndroid Build Coastguard Worker ret = 0;
8832*7c568831SAndroid Build Coastguard Worker while ((CUR >= '0') && (CUR <= '9')) {
8833*7c568831SAndroid Build Coastguard Worker ret = ret * 10;
8834*7c568831SAndroid Build Coastguard Worker tmp = (CUR - '0');
8835*7c568831SAndroid Build Coastguard Worker ok = 1;
8836*7c568831SAndroid Build Coastguard Worker NEXT;
8837*7c568831SAndroid Build Coastguard Worker temp = (double) tmp;
8838*7c568831SAndroid Build Coastguard Worker ret = ret + temp;
8839*7c568831SAndroid Build Coastguard Worker }
8840*7c568831SAndroid Build Coastguard Worker #else
8841*7c568831SAndroid Build Coastguard Worker ret = 0;
8842*7c568831SAndroid Build Coastguard Worker while ((CUR >= '0') && (CUR <= '9')) {
8843*7c568831SAndroid Build Coastguard Worker ret = ret * 10 + (CUR - '0');
8844*7c568831SAndroid Build Coastguard Worker ok = 1;
8845*7c568831SAndroid Build Coastguard Worker NEXT;
8846*7c568831SAndroid Build Coastguard Worker }
8847*7c568831SAndroid Build Coastguard Worker #endif
8848*7c568831SAndroid Build Coastguard Worker if (CUR == '.') {
8849*7c568831SAndroid Build Coastguard Worker int v, frac = 0, max;
8850*7c568831SAndroid Build Coastguard Worker double fraction = 0;
8851*7c568831SAndroid Build Coastguard Worker
8852*7c568831SAndroid Build Coastguard Worker NEXT;
8853*7c568831SAndroid Build Coastguard Worker if (((CUR < '0') || (CUR > '9')) && (!ok)) {
8854*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_NUMBER_ERROR);
8855*7c568831SAndroid Build Coastguard Worker }
8856*7c568831SAndroid Build Coastguard Worker while (CUR == '0') {
8857*7c568831SAndroid Build Coastguard Worker frac = frac + 1;
8858*7c568831SAndroid Build Coastguard Worker NEXT;
8859*7c568831SAndroid Build Coastguard Worker }
8860*7c568831SAndroid Build Coastguard Worker max = frac + MAX_FRAC;
8861*7c568831SAndroid Build Coastguard Worker while ((CUR >= '0') && (CUR <= '9') && (frac < max)) {
8862*7c568831SAndroid Build Coastguard Worker v = (CUR - '0');
8863*7c568831SAndroid Build Coastguard Worker fraction = fraction * 10 + v;
8864*7c568831SAndroid Build Coastguard Worker frac = frac + 1;
8865*7c568831SAndroid Build Coastguard Worker NEXT;
8866*7c568831SAndroid Build Coastguard Worker }
8867*7c568831SAndroid Build Coastguard Worker fraction /= pow(10.0, frac);
8868*7c568831SAndroid Build Coastguard Worker ret = ret + fraction;
8869*7c568831SAndroid Build Coastguard Worker while ((CUR >= '0') && (CUR <= '9'))
8870*7c568831SAndroid Build Coastguard Worker NEXT;
8871*7c568831SAndroid Build Coastguard Worker }
8872*7c568831SAndroid Build Coastguard Worker if ((CUR == 'e') || (CUR == 'E')) {
8873*7c568831SAndroid Build Coastguard Worker NEXT;
8874*7c568831SAndroid Build Coastguard Worker if (CUR == '-') {
8875*7c568831SAndroid Build Coastguard Worker is_exponent_negative = 1;
8876*7c568831SAndroid Build Coastguard Worker NEXT;
8877*7c568831SAndroid Build Coastguard Worker } else if (CUR == '+') {
8878*7c568831SAndroid Build Coastguard Worker NEXT;
8879*7c568831SAndroid Build Coastguard Worker }
8880*7c568831SAndroid Build Coastguard Worker while ((CUR >= '0') && (CUR <= '9')) {
8881*7c568831SAndroid Build Coastguard Worker if (exponent < 1000000)
8882*7c568831SAndroid Build Coastguard Worker exponent = exponent * 10 + (CUR - '0');
8883*7c568831SAndroid Build Coastguard Worker NEXT;
8884*7c568831SAndroid Build Coastguard Worker }
8885*7c568831SAndroid Build Coastguard Worker if (is_exponent_negative)
8886*7c568831SAndroid Build Coastguard Worker exponent = -exponent;
8887*7c568831SAndroid Build Coastguard Worker ret *= pow(10.0, (double) exponent);
8888*7c568831SAndroid Build Coastguard Worker }
8889*7c568831SAndroid Build Coastguard Worker num = xmlXPathCacheNewFloat(ctxt, ret);
8890*7c568831SAndroid Build Coastguard Worker if (num == NULL) {
8891*7c568831SAndroid Build Coastguard Worker ctxt->error = XPATH_MEMORY_ERROR;
8892*7c568831SAndroid Build Coastguard Worker } else if (PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_NUMBER, 0, 0, num,
8893*7c568831SAndroid Build Coastguard Worker NULL) == -1) {
8894*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, num);
8895*7c568831SAndroid Build Coastguard Worker }
8896*7c568831SAndroid Build Coastguard Worker }
8897*7c568831SAndroid Build Coastguard Worker
8898*7c568831SAndroid Build Coastguard Worker /**
8899*7c568831SAndroid Build Coastguard Worker * xmlXPathParseLiteral:
8900*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8901*7c568831SAndroid Build Coastguard Worker *
8902*7c568831SAndroid Build Coastguard Worker * Parse a Literal
8903*7c568831SAndroid Build Coastguard Worker *
8904*7c568831SAndroid Build Coastguard Worker * [29] Literal ::= '"' [^"]* '"'
8905*7c568831SAndroid Build Coastguard Worker * | "'" [^']* "'"
8906*7c568831SAndroid Build Coastguard Worker *
8907*7c568831SAndroid Build Coastguard Worker * Returns the value found or NULL in case of error
8908*7c568831SAndroid Build Coastguard Worker */
8909*7c568831SAndroid Build Coastguard Worker static xmlChar *
xmlXPathParseLiteral(xmlXPathParserContextPtr ctxt)8910*7c568831SAndroid Build Coastguard Worker xmlXPathParseLiteral(xmlXPathParserContextPtr ctxt) {
8911*7c568831SAndroid Build Coastguard Worker const xmlChar *q;
8912*7c568831SAndroid Build Coastguard Worker xmlChar *ret = NULL;
8913*7c568831SAndroid Build Coastguard Worker int quote;
8914*7c568831SAndroid Build Coastguard Worker
8915*7c568831SAndroid Build Coastguard Worker if (CUR == '"') {
8916*7c568831SAndroid Build Coastguard Worker quote = '"';
8917*7c568831SAndroid Build Coastguard Worker } else if (CUR == '\'') {
8918*7c568831SAndroid Build Coastguard Worker quote = '\'';
8919*7c568831SAndroid Build Coastguard Worker } else {
8920*7c568831SAndroid Build Coastguard Worker XP_ERRORNULL(XPATH_START_LITERAL_ERROR);
8921*7c568831SAndroid Build Coastguard Worker }
8922*7c568831SAndroid Build Coastguard Worker
8923*7c568831SAndroid Build Coastguard Worker NEXT;
8924*7c568831SAndroid Build Coastguard Worker q = CUR_PTR;
8925*7c568831SAndroid Build Coastguard Worker while (CUR != quote) {
8926*7c568831SAndroid Build Coastguard Worker int ch;
8927*7c568831SAndroid Build Coastguard Worker int len = 4;
8928*7c568831SAndroid Build Coastguard Worker
8929*7c568831SAndroid Build Coastguard Worker if (CUR == 0)
8930*7c568831SAndroid Build Coastguard Worker XP_ERRORNULL(XPATH_UNFINISHED_LITERAL_ERROR);
8931*7c568831SAndroid Build Coastguard Worker ch = xmlGetUTF8Char(CUR_PTR, &len);
8932*7c568831SAndroid Build Coastguard Worker if ((ch < 0) || (IS_CHAR(ch) == 0))
8933*7c568831SAndroid Build Coastguard Worker XP_ERRORNULL(XPATH_INVALID_CHAR_ERROR);
8934*7c568831SAndroid Build Coastguard Worker CUR_PTR += len;
8935*7c568831SAndroid Build Coastguard Worker }
8936*7c568831SAndroid Build Coastguard Worker ret = xmlStrndup(q, CUR_PTR - q);
8937*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
8938*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
8939*7c568831SAndroid Build Coastguard Worker NEXT;
8940*7c568831SAndroid Build Coastguard Worker return(ret);
8941*7c568831SAndroid Build Coastguard Worker }
8942*7c568831SAndroid Build Coastguard Worker
8943*7c568831SAndroid Build Coastguard Worker /**
8944*7c568831SAndroid Build Coastguard Worker * xmlXPathCompLiteral:
8945*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8946*7c568831SAndroid Build Coastguard Worker *
8947*7c568831SAndroid Build Coastguard Worker * Parse a Literal and push it on the stack.
8948*7c568831SAndroid Build Coastguard Worker *
8949*7c568831SAndroid Build Coastguard Worker * [29] Literal ::= '"' [^"]* '"'
8950*7c568831SAndroid Build Coastguard Worker * | "'" [^']* "'"
8951*7c568831SAndroid Build Coastguard Worker *
8952*7c568831SAndroid Build Coastguard Worker * TODO: xmlXPathCompLiteral memory allocation could be improved.
8953*7c568831SAndroid Build Coastguard Worker */
8954*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompLiteral(xmlXPathParserContextPtr ctxt)8955*7c568831SAndroid Build Coastguard Worker xmlXPathCompLiteral(xmlXPathParserContextPtr ctxt) {
8956*7c568831SAndroid Build Coastguard Worker xmlChar *ret = NULL;
8957*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr lit;
8958*7c568831SAndroid Build Coastguard Worker
8959*7c568831SAndroid Build Coastguard Worker ret = xmlXPathParseLiteral(ctxt);
8960*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
8961*7c568831SAndroid Build Coastguard Worker return;
8962*7c568831SAndroid Build Coastguard Worker lit = xmlXPathCacheNewString(ctxt, ret);
8963*7c568831SAndroid Build Coastguard Worker if (lit == NULL) {
8964*7c568831SAndroid Build Coastguard Worker ctxt->error = XPATH_MEMORY_ERROR;
8965*7c568831SAndroid Build Coastguard Worker } else if (PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_STRING, 0, 0, lit,
8966*7c568831SAndroid Build Coastguard Worker NULL) == -1) {
8967*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, lit);
8968*7c568831SAndroid Build Coastguard Worker }
8969*7c568831SAndroid Build Coastguard Worker xmlFree(ret);
8970*7c568831SAndroid Build Coastguard Worker }
8971*7c568831SAndroid Build Coastguard Worker
8972*7c568831SAndroid Build Coastguard Worker /**
8973*7c568831SAndroid Build Coastguard Worker * xmlXPathCompVariableReference:
8974*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8975*7c568831SAndroid Build Coastguard Worker *
8976*7c568831SAndroid Build Coastguard Worker * Parse a VariableReference, evaluate it and push it on the stack.
8977*7c568831SAndroid Build Coastguard Worker *
8978*7c568831SAndroid Build Coastguard Worker * The variable bindings consist of a mapping from variable names
8979*7c568831SAndroid Build Coastguard Worker * to variable values. The value of a variable is an object, which can be
8980*7c568831SAndroid Build Coastguard Worker * of any of the types that are possible for the value of an expression,
8981*7c568831SAndroid Build Coastguard Worker * and may also be of additional types not specified here.
8982*7c568831SAndroid Build Coastguard Worker *
8983*7c568831SAndroid Build Coastguard Worker * Early evaluation is possible since:
8984*7c568831SAndroid Build Coastguard Worker * The variable bindings [...] used to evaluate a subexpression are
8985*7c568831SAndroid Build Coastguard Worker * always the same as those used to evaluate the containing expression.
8986*7c568831SAndroid Build Coastguard Worker *
8987*7c568831SAndroid Build Coastguard Worker * [36] VariableReference ::= '$' QName
8988*7c568831SAndroid Build Coastguard Worker */
8989*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompVariableReference(xmlXPathParserContextPtr ctxt)8990*7c568831SAndroid Build Coastguard Worker xmlXPathCompVariableReference(xmlXPathParserContextPtr ctxt) {
8991*7c568831SAndroid Build Coastguard Worker xmlChar *name;
8992*7c568831SAndroid Build Coastguard Worker xmlChar *prefix;
8993*7c568831SAndroid Build Coastguard Worker
8994*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
8995*7c568831SAndroid Build Coastguard Worker if (CUR != '$') {
8996*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_VARIABLE_REF_ERROR);
8997*7c568831SAndroid Build Coastguard Worker }
8998*7c568831SAndroid Build Coastguard Worker NEXT;
8999*7c568831SAndroid Build Coastguard Worker name = xmlXPathParseQName(ctxt, &prefix);
9000*7c568831SAndroid Build Coastguard Worker if (name == NULL) {
9001*7c568831SAndroid Build Coastguard Worker xmlFree(prefix);
9002*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_VARIABLE_REF_ERROR);
9003*7c568831SAndroid Build Coastguard Worker }
9004*7c568831SAndroid Build Coastguard Worker ctxt->comp->last = -1;
9005*7c568831SAndroid Build Coastguard Worker if (PUSH_LONG_EXPR(XPATH_OP_VARIABLE, 0, 0, 0, name, prefix) == -1) {
9006*7c568831SAndroid Build Coastguard Worker xmlFree(prefix);
9007*7c568831SAndroid Build Coastguard Worker xmlFree(name);
9008*7c568831SAndroid Build Coastguard Worker }
9009*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9010*7c568831SAndroid Build Coastguard Worker if ((ctxt->context != NULL) && (ctxt->context->flags & XML_XPATH_NOVAR)) {
9011*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_FORBID_VARIABLE_ERROR);
9012*7c568831SAndroid Build Coastguard Worker }
9013*7c568831SAndroid Build Coastguard Worker }
9014*7c568831SAndroid Build Coastguard Worker
9015*7c568831SAndroid Build Coastguard Worker /**
9016*7c568831SAndroid Build Coastguard Worker * xmlXPathIsNodeType:
9017*7c568831SAndroid Build Coastguard Worker * @name: a name string
9018*7c568831SAndroid Build Coastguard Worker *
9019*7c568831SAndroid Build Coastguard Worker * Is the name given a NodeType one.
9020*7c568831SAndroid Build Coastguard Worker *
9021*7c568831SAndroid Build Coastguard Worker * [38] NodeType ::= 'comment'
9022*7c568831SAndroid Build Coastguard Worker * | 'text'
9023*7c568831SAndroid Build Coastguard Worker * | 'processing-instruction'
9024*7c568831SAndroid Build Coastguard Worker * | 'node'
9025*7c568831SAndroid Build Coastguard Worker *
9026*7c568831SAndroid Build Coastguard Worker * Returns 1 if true 0 otherwise
9027*7c568831SAndroid Build Coastguard Worker */
9028*7c568831SAndroid Build Coastguard Worker int
xmlXPathIsNodeType(const xmlChar * name)9029*7c568831SAndroid Build Coastguard Worker xmlXPathIsNodeType(const xmlChar *name) {
9030*7c568831SAndroid Build Coastguard Worker if (name == NULL)
9031*7c568831SAndroid Build Coastguard Worker return(0);
9032*7c568831SAndroid Build Coastguard Worker
9033*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "node"))
9034*7c568831SAndroid Build Coastguard Worker return(1);
9035*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "text"))
9036*7c568831SAndroid Build Coastguard Worker return(1);
9037*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "comment"))
9038*7c568831SAndroid Build Coastguard Worker return(1);
9039*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "processing-instruction"))
9040*7c568831SAndroid Build Coastguard Worker return(1);
9041*7c568831SAndroid Build Coastguard Worker return(0);
9042*7c568831SAndroid Build Coastguard Worker }
9043*7c568831SAndroid Build Coastguard Worker
9044*7c568831SAndroid Build Coastguard Worker /**
9045*7c568831SAndroid Build Coastguard Worker * xmlXPathCompFunctionCall:
9046*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9047*7c568831SAndroid Build Coastguard Worker *
9048*7c568831SAndroid Build Coastguard Worker * [16] FunctionCall ::= FunctionName '(' ( Argument ( ',' Argument)*)? ')'
9049*7c568831SAndroid Build Coastguard Worker * [17] Argument ::= Expr
9050*7c568831SAndroid Build Coastguard Worker *
9051*7c568831SAndroid Build Coastguard Worker * Compile a function call, the evaluation of all arguments are
9052*7c568831SAndroid Build Coastguard Worker * pushed on the stack
9053*7c568831SAndroid Build Coastguard Worker */
9054*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompFunctionCall(xmlXPathParserContextPtr ctxt)9055*7c568831SAndroid Build Coastguard Worker xmlXPathCompFunctionCall(xmlXPathParserContextPtr ctxt) {
9056*7c568831SAndroid Build Coastguard Worker xmlChar *name;
9057*7c568831SAndroid Build Coastguard Worker xmlChar *prefix;
9058*7c568831SAndroid Build Coastguard Worker int nbargs = 0;
9059*7c568831SAndroid Build Coastguard Worker int sort = 1;
9060*7c568831SAndroid Build Coastguard Worker
9061*7c568831SAndroid Build Coastguard Worker name = xmlXPathParseQName(ctxt, &prefix);
9062*7c568831SAndroid Build Coastguard Worker if (name == NULL) {
9063*7c568831SAndroid Build Coastguard Worker xmlFree(prefix);
9064*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_EXPR_ERROR);
9065*7c568831SAndroid Build Coastguard Worker }
9066*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9067*7c568831SAndroid Build Coastguard Worker
9068*7c568831SAndroid Build Coastguard Worker if (CUR != '(') {
9069*7c568831SAndroid Build Coastguard Worker xmlFree(name);
9070*7c568831SAndroid Build Coastguard Worker xmlFree(prefix);
9071*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_EXPR_ERROR);
9072*7c568831SAndroid Build Coastguard Worker }
9073*7c568831SAndroid Build Coastguard Worker NEXT;
9074*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9075*7c568831SAndroid Build Coastguard Worker
9076*7c568831SAndroid Build Coastguard Worker /*
9077*7c568831SAndroid Build Coastguard Worker * Optimization for count(): we don't need the node-set to be sorted.
9078*7c568831SAndroid Build Coastguard Worker */
9079*7c568831SAndroid Build Coastguard Worker if ((prefix == NULL) && (name[0] == 'c') &&
9080*7c568831SAndroid Build Coastguard Worker xmlStrEqual(name, BAD_CAST "count"))
9081*7c568831SAndroid Build Coastguard Worker {
9082*7c568831SAndroid Build Coastguard Worker sort = 0;
9083*7c568831SAndroid Build Coastguard Worker }
9084*7c568831SAndroid Build Coastguard Worker ctxt->comp->last = -1;
9085*7c568831SAndroid Build Coastguard Worker if (CUR != ')') {
9086*7c568831SAndroid Build Coastguard Worker while (CUR != 0) {
9087*7c568831SAndroid Build Coastguard Worker int op1 = ctxt->comp->last;
9088*7c568831SAndroid Build Coastguard Worker ctxt->comp->last = -1;
9089*7c568831SAndroid Build Coastguard Worker xmlXPathCompileExpr(ctxt, sort);
9090*7c568831SAndroid Build Coastguard Worker if (ctxt->error != XPATH_EXPRESSION_OK) {
9091*7c568831SAndroid Build Coastguard Worker xmlFree(name);
9092*7c568831SAndroid Build Coastguard Worker xmlFree(prefix);
9093*7c568831SAndroid Build Coastguard Worker return;
9094*7c568831SAndroid Build Coastguard Worker }
9095*7c568831SAndroid Build Coastguard Worker PUSH_BINARY_EXPR(XPATH_OP_ARG, op1, ctxt->comp->last, 0, 0);
9096*7c568831SAndroid Build Coastguard Worker nbargs++;
9097*7c568831SAndroid Build Coastguard Worker if (CUR == ')') break;
9098*7c568831SAndroid Build Coastguard Worker if (CUR != ',') {
9099*7c568831SAndroid Build Coastguard Worker xmlFree(name);
9100*7c568831SAndroid Build Coastguard Worker xmlFree(prefix);
9101*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_EXPR_ERROR);
9102*7c568831SAndroid Build Coastguard Worker }
9103*7c568831SAndroid Build Coastguard Worker NEXT;
9104*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9105*7c568831SAndroid Build Coastguard Worker }
9106*7c568831SAndroid Build Coastguard Worker }
9107*7c568831SAndroid Build Coastguard Worker if (PUSH_LONG_EXPR(XPATH_OP_FUNCTION, nbargs, 0, 0, name, prefix) == -1) {
9108*7c568831SAndroid Build Coastguard Worker xmlFree(prefix);
9109*7c568831SAndroid Build Coastguard Worker xmlFree(name);
9110*7c568831SAndroid Build Coastguard Worker }
9111*7c568831SAndroid Build Coastguard Worker NEXT;
9112*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9113*7c568831SAndroid Build Coastguard Worker }
9114*7c568831SAndroid Build Coastguard Worker
9115*7c568831SAndroid Build Coastguard Worker /**
9116*7c568831SAndroid Build Coastguard Worker * xmlXPathCompPrimaryExpr:
9117*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9118*7c568831SAndroid Build Coastguard Worker *
9119*7c568831SAndroid Build Coastguard Worker * [15] PrimaryExpr ::= VariableReference
9120*7c568831SAndroid Build Coastguard Worker * | '(' Expr ')'
9121*7c568831SAndroid Build Coastguard Worker * | Literal
9122*7c568831SAndroid Build Coastguard Worker * | Number
9123*7c568831SAndroid Build Coastguard Worker * | FunctionCall
9124*7c568831SAndroid Build Coastguard Worker *
9125*7c568831SAndroid Build Coastguard Worker * Compile a primary expression.
9126*7c568831SAndroid Build Coastguard Worker */
9127*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompPrimaryExpr(xmlXPathParserContextPtr ctxt)9128*7c568831SAndroid Build Coastguard Worker xmlXPathCompPrimaryExpr(xmlXPathParserContextPtr ctxt) {
9129*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9130*7c568831SAndroid Build Coastguard Worker if (CUR == '$') xmlXPathCompVariableReference(ctxt);
9131*7c568831SAndroid Build Coastguard Worker else if (CUR == '(') {
9132*7c568831SAndroid Build Coastguard Worker NEXT;
9133*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9134*7c568831SAndroid Build Coastguard Worker xmlXPathCompileExpr(ctxt, 1);
9135*7c568831SAndroid Build Coastguard Worker CHECK_ERROR;
9136*7c568831SAndroid Build Coastguard Worker if (CUR != ')') {
9137*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_EXPR_ERROR);
9138*7c568831SAndroid Build Coastguard Worker }
9139*7c568831SAndroid Build Coastguard Worker NEXT;
9140*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9141*7c568831SAndroid Build Coastguard Worker } else if (IS_ASCII_DIGIT(CUR) || (CUR == '.' && IS_ASCII_DIGIT(NXT(1)))) {
9142*7c568831SAndroid Build Coastguard Worker xmlXPathCompNumber(ctxt);
9143*7c568831SAndroid Build Coastguard Worker } else if ((CUR == '\'') || (CUR == '"')) {
9144*7c568831SAndroid Build Coastguard Worker xmlXPathCompLiteral(ctxt);
9145*7c568831SAndroid Build Coastguard Worker } else {
9146*7c568831SAndroid Build Coastguard Worker xmlXPathCompFunctionCall(ctxt);
9147*7c568831SAndroid Build Coastguard Worker }
9148*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9149*7c568831SAndroid Build Coastguard Worker }
9150*7c568831SAndroid Build Coastguard Worker
9151*7c568831SAndroid Build Coastguard Worker /**
9152*7c568831SAndroid Build Coastguard Worker * xmlXPathCompFilterExpr:
9153*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9154*7c568831SAndroid Build Coastguard Worker *
9155*7c568831SAndroid Build Coastguard Worker * [20] FilterExpr ::= PrimaryExpr
9156*7c568831SAndroid Build Coastguard Worker * | FilterExpr Predicate
9157*7c568831SAndroid Build Coastguard Worker *
9158*7c568831SAndroid Build Coastguard Worker * Compile a filter expression.
9159*7c568831SAndroid Build Coastguard Worker * Square brackets are used to filter expressions in the same way that
9160*7c568831SAndroid Build Coastguard Worker * they are used in location paths. It is an error if the expression to
9161*7c568831SAndroid Build Coastguard Worker * be filtered does not evaluate to a node-set. The context node list
9162*7c568831SAndroid Build Coastguard Worker * used for evaluating the expression in square brackets is the node-set
9163*7c568831SAndroid Build Coastguard Worker * to be filtered listed in document order.
9164*7c568831SAndroid Build Coastguard Worker */
9165*7c568831SAndroid Build Coastguard Worker
9166*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompFilterExpr(xmlXPathParserContextPtr ctxt)9167*7c568831SAndroid Build Coastguard Worker xmlXPathCompFilterExpr(xmlXPathParserContextPtr ctxt) {
9168*7c568831SAndroid Build Coastguard Worker xmlXPathCompPrimaryExpr(ctxt);
9169*7c568831SAndroid Build Coastguard Worker CHECK_ERROR;
9170*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9171*7c568831SAndroid Build Coastguard Worker
9172*7c568831SAndroid Build Coastguard Worker while (CUR == '[') {
9173*7c568831SAndroid Build Coastguard Worker xmlXPathCompPredicate(ctxt, 1);
9174*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9175*7c568831SAndroid Build Coastguard Worker }
9176*7c568831SAndroid Build Coastguard Worker
9177*7c568831SAndroid Build Coastguard Worker
9178*7c568831SAndroid Build Coastguard Worker }
9179*7c568831SAndroid Build Coastguard Worker
9180*7c568831SAndroid Build Coastguard Worker /**
9181*7c568831SAndroid Build Coastguard Worker * xmlXPathScanName:
9182*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9183*7c568831SAndroid Build Coastguard Worker *
9184*7c568831SAndroid Build Coastguard Worker * Trickery: parse an XML name but without consuming the input flow
9185*7c568831SAndroid Build Coastguard Worker * Needed to avoid insanity in the parser state.
9186*7c568831SAndroid Build Coastguard Worker *
9187*7c568831SAndroid Build Coastguard Worker * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
9188*7c568831SAndroid Build Coastguard Worker * CombiningChar | Extender
9189*7c568831SAndroid Build Coastguard Worker *
9190*7c568831SAndroid Build Coastguard Worker * [5] Name ::= (Letter | '_' | ':') (NameChar)*
9191*7c568831SAndroid Build Coastguard Worker *
9192*7c568831SAndroid Build Coastguard Worker * [6] Names ::= Name (S Name)*
9193*7c568831SAndroid Build Coastguard Worker *
9194*7c568831SAndroid Build Coastguard Worker * Returns the Name parsed or NULL
9195*7c568831SAndroid Build Coastguard Worker */
9196*7c568831SAndroid Build Coastguard Worker
9197*7c568831SAndroid Build Coastguard Worker static xmlChar *
xmlXPathScanName(xmlXPathParserContextPtr ctxt)9198*7c568831SAndroid Build Coastguard Worker xmlXPathScanName(xmlXPathParserContextPtr ctxt) {
9199*7c568831SAndroid Build Coastguard Worker int l;
9200*7c568831SAndroid Build Coastguard Worker int c;
9201*7c568831SAndroid Build Coastguard Worker const xmlChar *cur;
9202*7c568831SAndroid Build Coastguard Worker xmlChar *ret;
9203*7c568831SAndroid Build Coastguard Worker
9204*7c568831SAndroid Build Coastguard Worker cur = ctxt->cur;
9205*7c568831SAndroid Build Coastguard Worker
9206*7c568831SAndroid Build Coastguard Worker c = CUR_CHAR(l);
9207*7c568831SAndroid Build Coastguard Worker if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
9208*7c568831SAndroid Build Coastguard Worker (!IS_LETTER(c) && (c != '_') &&
9209*7c568831SAndroid Build Coastguard Worker (c != ':'))) {
9210*7c568831SAndroid Build Coastguard Worker return(NULL);
9211*7c568831SAndroid Build Coastguard Worker }
9212*7c568831SAndroid Build Coastguard Worker
9213*7c568831SAndroid Build Coastguard Worker while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
9214*7c568831SAndroid Build Coastguard Worker ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
9215*7c568831SAndroid Build Coastguard Worker (c == '.') || (c == '-') ||
9216*7c568831SAndroid Build Coastguard Worker (c == '_') || (c == ':') ||
9217*7c568831SAndroid Build Coastguard Worker (IS_COMBINING(c)) ||
9218*7c568831SAndroid Build Coastguard Worker (IS_EXTENDER(c)))) {
9219*7c568831SAndroid Build Coastguard Worker NEXTL(l);
9220*7c568831SAndroid Build Coastguard Worker c = CUR_CHAR(l);
9221*7c568831SAndroid Build Coastguard Worker }
9222*7c568831SAndroid Build Coastguard Worker ret = xmlStrndup(cur, ctxt->cur - cur);
9223*7c568831SAndroid Build Coastguard Worker if (ret == NULL)
9224*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
9225*7c568831SAndroid Build Coastguard Worker ctxt->cur = cur;
9226*7c568831SAndroid Build Coastguard Worker return(ret);
9227*7c568831SAndroid Build Coastguard Worker }
9228*7c568831SAndroid Build Coastguard Worker
9229*7c568831SAndroid Build Coastguard Worker /**
9230*7c568831SAndroid Build Coastguard Worker * xmlXPathCompPathExpr:
9231*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9232*7c568831SAndroid Build Coastguard Worker *
9233*7c568831SAndroid Build Coastguard Worker * [19] PathExpr ::= LocationPath
9234*7c568831SAndroid Build Coastguard Worker * | FilterExpr
9235*7c568831SAndroid Build Coastguard Worker * | FilterExpr '/' RelativeLocationPath
9236*7c568831SAndroid Build Coastguard Worker * | FilterExpr '//' RelativeLocationPath
9237*7c568831SAndroid Build Coastguard Worker *
9238*7c568831SAndroid Build Coastguard Worker * Compile a path expression.
9239*7c568831SAndroid Build Coastguard Worker * The / operator and // operators combine an arbitrary expression
9240*7c568831SAndroid Build Coastguard Worker * and a relative location path. It is an error if the expression
9241*7c568831SAndroid Build Coastguard Worker * does not evaluate to a node-set.
9242*7c568831SAndroid Build Coastguard Worker * The / operator does composition in the same way as when / is
9243*7c568831SAndroid Build Coastguard Worker * used in a location path. As in location paths, // is short for
9244*7c568831SAndroid Build Coastguard Worker * /descendant-or-self::node()/.
9245*7c568831SAndroid Build Coastguard Worker */
9246*7c568831SAndroid Build Coastguard Worker
9247*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt)9248*7c568831SAndroid Build Coastguard Worker xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) {
9249*7c568831SAndroid Build Coastguard Worker int lc = 1; /* Should we branch to LocationPath ? */
9250*7c568831SAndroid Build Coastguard Worker xmlChar *name = NULL; /* we may have to preparse a name to find out */
9251*7c568831SAndroid Build Coastguard Worker
9252*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9253*7c568831SAndroid Build Coastguard Worker if ((CUR == '$') || (CUR == '(') ||
9254*7c568831SAndroid Build Coastguard Worker (IS_ASCII_DIGIT(CUR)) ||
9255*7c568831SAndroid Build Coastguard Worker (CUR == '\'') || (CUR == '"') ||
9256*7c568831SAndroid Build Coastguard Worker (CUR == '.' && IS_ASCII_DIGIT(NXT(1)))) {
9257*7c568831SAndroid Build Coastguard Worker lc = 0;
9258*7c568831SAndroid Build Coastguard Worker } else if (CUR == '*') {
9259*7c568831SAndroid Build Coastguard Worker /* relative or absolute location path */
9260*7c568831SAndroid Build Coastguard Worker lc = 1;
9261*7c568831SAndroid Build Coastguard Worker } else if (CUR == '/') {
9262*7c568831SAndroid Build Coastguard Worker /* relative or absolute location path */
9263*7c568831SAndroid Build Coastguard Worker lc = 1;
9264*7c568831SAndroid Build Coastguard Worker } else if (CUR == '@') {
9265*7c568831SAndroid Build Coastguard Worker /* relative abbreviated attribute location path */
9266*7c568831SAndroid Build Coastguard Worker lc = 1;
9267*7c568831SAndroid Build Coastguard Worker } else if (CUR == '.') {
9268*7c568831SAndroid Build Coastguard Worker /* relative abbreviated attribute location path */
9269*7c568831SAndroid Build Coastguard Worker lc = 1;
9270*7c568831SAndroid Build Coastguard Worker } else {
9271*7c568831SAndroid Build Coastguard Worker /*
9272*7c568831SAndroid Build Coastguard Worker * Problem is finding if we have a name here whether it's:
9273*7c568831SAndroid Build Coastguard Worker * - a nodetype
9274*7c568831SAndroid Build Coastguard Worker * - a function call in which case it's followed by '('
9275*7c568831SAndroid Build Coastguard Worker * - an axis in which case it's followed by ':'
9276*7c568831SAndroid Build Coastguard Worker * - a element name
9277*7c568831SAndroid Build Coastguard Worker * We do an a priori analysis here rather than having to
9278*7c568831SAndroid Build Coastguard Worker * maintain parsed token content through the recursive function
9279*7c568831SAndroid Build Coastguard Worker * calls. This looks uglier but makes the code easier to
9280*7c568831SAndroid Build Coastguard Worker * read/write/debug.
9281*7c568831SAndroid Build Coastguard Worker */
9282*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9283*7c568831SAndroid Build Coastguard Worker name = xmlXPathScanName(ctxt);
9284*7c568831SAndroid Build Coastguard Worker if ((name != NULL) && (xmlStrstr(name, (xmlChar *) "::") != NULL)) {
9285*7c568831SAndroid Build Coastguard Worker lc = 1;
9286*7c568831SAndroid Build Coastguard Worker xmlFree(name);
9287*7c568831SAndroid Build Coastguard Worker } else if (name != NULL) {
9288*7c568831SAndroid Build Coastguard Worker int len =xmlStrlen(name);
9289*7c568831SAndroid Build Coastguard Worker
9290*7c568831SAndroid Build Coastguard Worker
9291*7c568831SAndroid Build Coastguard Worker while (NXT(len) != 0) {
9292*7c568831SAndroid Build Coastguard Worker if (NXT(len) == '/') {
9293*7c568831SAndroid Build Coastguard Worker /* element name */
9294*7c568831SAndroid Build Coastguard Worker lc = 1;
9295*7c568831SAndroid Build Coastguard Worker break;
9296*7c568831SAndroid Build Coastguard Worker } else if (IS_BLANK_CH(NXT(len))) {
9297*7c568831SAndroid Build Coastguard Worker /* ignore blanks */
9298*7c568831SAndroid Build Coastguard Worker ;
9299*7c568831SAndroid Build Coastguard Worker } else if (NXT(len) == ':') {
9300*7c568831SAndroid Build Coastguard Worker lc = 1;
9301*7c568831SAndroid Build Coastguard Worker break;
9302*7c568831SAndroid Build Coastguard Worker } else if ((NXT(len) == '(')) {
9303*7c568831SAndroid Build Coastguard Worker /* Node Type or Function */
9304*7c568831SAndroid Build Coastguard Worker if (xmlXPathIsNodeType(name)) {
9305*7c568831SAndroid Build Coastguard Worker lc = 1;
9306*7c568831SAndroid Build Coastguard Worker } else {
9307*7c568831SAndroid Build Coastguard Worker lc = 0;
9308*7c568831SAndroid Build Coastguard Worker }
9309*7c568831SAndroid Build Coastguard Worker break;
9310*7c568831SAndroid Build Coastguard Worker } else if ((NXT(len) == '[')) {
9311*7c568831SAndroid Build Coastguard Worker /* element name */
9312*7c568831SAndroid Build Coastguard Worker lc = 1;
9313*7c568831SAndroid Build Coastguard Worker break;
9314*7c568831SAndroid Build Coastguard Worker } else if ((NXT(len) == '<') || (NXT(len) == '>') ||
9315*7c568831SAndroid Build Coastguard Worker (NXT(len) == '=')) {
9316*7c568831SAndroid Build Coastguard Worker lc = 1;
9317*7c568831SAndroid Build Coastguard Worker break;
9318*7c568831SAndroid Build Coastguard Worker } else {
9319*7c568831SAndroid Build Coastguard Worker lc = 1;
9320*7c568831SAndroid Build Coastguard Worker break;
9321*7c568831SAndroid Build Coastguard Worker }
9322*7c568831SAndroid Build Coastguard Worker len++;
9323*7c568831SAndroid Build Coastguard Worker }
9324*7c568831SAndroid Build Coastguard Worker if (NXT(len) == 0) {
9325*7c568831SAndroid Build Coastguard Worker /* element name */
9326*7c568831SAndroid Build Coastguard Worker lc = 1;
9327*7c568831SAndroid Build Coastguard Worker }
9328*7c568831SAndroid Build Coastguard Worker xmlFree(name);
9329*7c568831SAndroid Build Coastguard Worker } else {
9330*7c568831SAndroid Build Coastguard Worker /* make sure all cases are covered explicitly */
9331*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_EXPR_ERROR);
9332*7c568831SAndroid Build Coastguard Worker }
9333*7c568831SAndroid Build Coastguard Worker }
9334*7c568831SAndroid Build Coastguard Worker
9335*7c568831SAndroid Build Coastguard Worker if (lc) {
9336*7c568831SAndroid Build Coastguard Worker if (CUR == '/') {
9337*7c568831SAndroid Build Coastguard Worker PUSH_LEAVE_EXPR(XPATH_OP_ROOT, 0, 0);
9338*7c568831SAndroid Build Coastguard Worker } else {
9339*7c568831SAndroid Build Coastguard Worker PUSH_LEAVE_EXPR(XPATH_OP_NODE, 0, 0);
9340*7c568831SAndroid Build Coastguard Worker }
9341*7c568831SAndroid Build Coastguard Worker xmlXPathCompLocationPath(ctxt);
9342*7c568831SAndroid Build Coastguard Worker } else {
9343*7c568831SAndroid Build Coastguard Worker xmlXPathCompFilterExpr(ctxt);
9344*7c568831SAndroid Build Coastguard Worker CHECK_ERROR;
9345*7c568831SAndroid Build Coastguard Worker if ((CUR == '/') && (NXT(1) == '/')) {
9346*7c568831SAndroid Build Coastguard Worker SKIP(2);
9347*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9348*7c568831SAndroid Build Coastguard Worker
9349*7c568831SAndroid Build Coastguard Worker PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
9350*7c568831SAndroid Build Coastguard Worker NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
9351*7c568831SAndroid Build Coastguard Worker
9352*7c568831SAndroid Build Coastguard Worker xmlXPathCompRelativeLocationPath(ctxt);
9353*7c568831SAndroid Build Coastguard Worker } else if (CUR == '/') {
9354*7c568831SAndroid Build Coastguard Worker xmlXPathCompRelativeLocationPath(ctxt);
9355*7c568831SAndroid Build Coastguard Worker }
9356*7c568831SAndroid Build Coastguard Worker }
9357*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9358*7c568831SAndroid Build Coastguard Worker }
9359*7c568831SAndroid Build Coastguard Worker
9360*7c568831SAndroid Build Coastguard Worker /**
9361*7c568831SAndroid Build Coastguard Worker * xmlXPathCompUnionExpr:
9362*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9363*7c568831SAndroid Build Coastguard Worker *
9364*7c568831SAndroid Build Coastguard Worker * [18] UnionExpr ::= PathExpr
9365*7c568831SAndroid Build Coastguard Worker * | UnionExpr '|' PathExpr
9366*7c568831SAndroid Build Coastguard Worker *
9367*7c568831SAndroid Build Coastguard Worker * Compile an union expression.
9368*7c568831SAndroid Build Coastguard Worker */
9369*7c568831SAndroid Build Coastguard Worker
9370*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompUnionExpr(xmlXPathParserContextPtr ctxt)9371*7c568831SAndroid Build Coastguard Worker xmlXPathCompUnionExpr(xmlXPathParserContextPtr ctxt) {
9372*7c568831SAndroid Build Coastguard Worker xmlXPathCompPathExpr(ctxt);
9373*7c568831SAndroid Build Coastguard Worker CHECK_ERROR;
9374*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9375*7c568831SAndroid Build Coastguard Worker while (CUR == '|') {
9376*7c568831SAndroid Build Coastguard Worker int op1 = ctxt->comp->last;
9377*7c568831SAndroid Build Coastguard Worker PUSH_LEAVE_EXPR(XPATH_OP_NODE, 0, 0);
9378*7c568831SAndroid Build Coastguard Worker
9379*7c568831SAndroid Build Coastguard Worker NEXT;
9380*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9381*7c568831SAndroid Build Coastguard Worker xmlXPathCompPathExpr(ctxt);
9382*7c568831SAndroid Build Coastguard Worker
9383*7c568831SAndroid Build Coastguard Worker PUSH_BINARY_EXPR(XPATH_OP_UNION, op1, ctxt->comp->last, 0, 0);
9384*7c568831SAndroid Build Coastguard Worker
9385*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9386*7c568831SAndroid Build Coastguard Worker }
9387*7c568831SAndroid Build Coastguard Worker }
9388*7c568831SAndroid Build Coastguard Worker
9389*7c568831SAndroid Build Coastguard Worker /**
9390*7c568831SAndroid Build Coastguard Worker * xmlXPathCompUnaryExpr:
9391*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9392*7c568831SAndroid Build Coastguard Worker *
9393*7c568831SAndroid Build Coastguard Worker * [27] UnaryExpr ::= UnionExpr
9394*7c568831SAndroid Build Coastguard Worker * | '-' UnaryExpr
9395*7c568831SAndroid Build Coastguard Worker *
9396*7c568831SAndroid Build Coastguard Worker * Compile an unary expression.
9397*7c568831SAndroid Build Coastguard Worker */
9398*7c568831SAndroid Build Coastguard Worker
9399*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompUnaryExpr(xmlXPathParserContextPtr ctxt)9400*7c568831SAndroid Build Coastguard Worker xmlXPathCompUnaryExpr(xmlXPathParserContextPtr ctxt) {
9401*7c568831SAndroid Build Coastguard Worker int minus = 0;
9402*7c568831SAndroid Build Coastguard Worker int found = 0;
9403*7c568831SAndroid Build Coastguard Worker
9404*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9405*7c568831SAndroid Build Coastguard Worker while (CUR == '-') {
9406*7c568831SAndroid Build Coastguard Worker minus = 1 - minus;
9407*7c568831SAndroid Build Coastguard Worker found = 1;
9408*7c568831SAndroid Build Coastguard Worker NEXT;
9409*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9410*7c568831SAndroid Build Coastguard Worker }
9411*7c568831SAndroid Build Coastguard Worker
9412*7c568831SAndroid Build Coastguard Worker xmlXPathCompUnionExpr(ctxt);
9413*7c568831SAndroid Build Coastguard Worker CHECK_ERROR;
9414*7c568831SAndroid Build Coastguard Worker if (found) {
9415*7c568831SAndroid Build Coastguard Worker if (minus)
9416*7c568831SAndroid Build Coastguard Worker PUSH_UNARY_EXPR(XPATH_OP_PLUS, ctxt->comp->last, 2, 0);
9417*7c568831SAndroid Build Coastguard Worker else
9418*7c568831SAndroid Build Coastguard Worker PUSH_UNARY_EXPR(XPATH_OP_PLUS, ctxt->comp->last, 3, 0);
9419*7c568831SAndroid Build Coastguard Worker }
9420*7c568831SAndroid Build Coastguard Worker }
9421*7c568831SAndroid Build Coastguard Worker
9422*7c568831SAndroid Build Coastguard Worker /**
9423*7c568831SAndroid Build Coastguard Worker * xmlXPathCompMultiplicativeExpr:
9424*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9425*7c568831SAndroid Build Coastguard Worker *
9426*7c568831SAndroid Build Coastguard Worker * [26] MultiplicativeExpr ::= UnaryExpr
9427*7c568831SAndroid Build Coastguard Worker * | MultiplicativeExpr MultiplyOperator UnaryExpr
9428*7c568831SAndroid Build Coastguard Worker * | MultiplicativeExpr 'div' UnaryExpr
9429*7c568831SAndroid Build Coastguard Worker * | MultiplicativeExpr 'mod' UnaryExpr
9430*7c568831SAndroid Build Coastguard Worker * [34] MultiplyOperator ::= '*'
9431*7c568831SAndroid Build Coastguard Worker *
9432*7c568831SAndroid Build Coastguard Worker * Compile an Additive expression.
9433*7c568831SAndroid Build Coastguard Worker */
9434*7c568831SAndroid Build Coastguard Worker
9435*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompMultiplicativeExpr(xmlXPathParserContextPtr ctxt)9436*7c568831SAndroid Build Coastguard Worker xmlXPathCompMultiplicativeExpr(xmlXPathParserContextPtr ctxt) {
9437*7c568831SAndroid Build Coastguard Worker xmlXPathCompUnaryExpr(ctxt);
9438*7c568831SAndroid Build Coastguard Worker CHECK_ERROR;
9439*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9440*7c568831SAndroid Build Coastguard Worker while ((CUR == '*') ||
9441*7c568831SAndroid Build Coastguard Worker ((CUR == 'd') && (NXT(1) == 'i') && (NXT(2) == 'v')) ||
9442*7c568831SAndroid Build Coastguard Worker ((CUR == 'm') && (NXT(1) == 'o') && (NXT(2) == 'd'))) {
9443*7c568831SAndroid Build Coastguard Worker int op = -1;
9444*7c568831SAndroid Build Coastguard Worker int op1 = ctxt->comp->last;
9445*7c568831SAndroid Build Coastguard Worker
9446*7c568831SAndroid Build Coastguard Worker if (CUR == '*') {
9447*7c568831SAndroid Build Coastguard Worker op = 0;
9448*7c568831SAndroid Build Coastguard Worker NEXT;
9449*7c568831SAndroid Build Coastguard Worker } else if (CUR == 'd') {
9450*7c568831SAndroid Build Coastguard Worker op = 1;
9451*7c568831SAndroid Build Coastguard Worker SKIP(3);
9452*7c568831SAndroid Build Coastguard Worker } else if (CUR == 'm') {
9453*7c568831SAndroid Build Coastguard Worker op = 2;
9454*7c568831SAndroid Build Coastguard Worker SKIP(3);
9455*7c568831SAndroid Build Coastguard Worker }
9456*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9457*7c568831SAndroid Build Coastguard Worker xmlXPathCompUnaryExpr(ctxt);
9458*7c568831SAndroid Build Coastguard Worker CHECK_ERROR;
9459*7c568831SAndroid Build Coastguard Worker PUSH_BINARY_EXPR(XPATH_OP_MULT, op1, ctxt->comp->last, op, 0);
9460*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9461*7c568831SAndroid Build Coastguard Worker }
9462*7c568831SAndroid Build Coastguard Worker }
9463*7c568831SAndroid Build Coastguard Worker
9464*7c568831SAndroid Build Coastguard Worker /**
9465*7c568831SAndroid Build Coastguard Worker * xmlXPathCompAdditiveExpr:
9466*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9467*7c568831SAndroid Build Coastguard Worker *
9468*7c568831SAndroid Build Coastguard Worker * [25] AdditiveExpr ::= MultiplicativeExpr
9469*7c568831SAndroid Build Coastguard Worker * | AdditiveExpr '+' MultiplicativeExpr
9470*7c568831SAndroid Build Coastguard Worker * | AdditiveExpr '-' MultiplicativeExpr
9471*7c568831SAndroid Build Coastguard Worker *
9472*7c568831SAndroid Build Coastguard Worker * Compile an Additive expression.
9473*7c568831SAndroid Build Coastguard Worker */
9474*7c568831SAndroid Build Coastguard Worker
9475*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompAdditiveExpr(xmlXPathParserContextPtr ctxt)9476*7c568831SAndroid Build Coastguard Worker xmlXPathCompAdditiveExpr(xmlXPathParserContextPtr ctxt) {
9477*7c568831SAndroid Build Coastguard Worker
9478*7c568831SAndroid Build Coastguard Worker xmlXPathCompMultiplicativeExpr(ctxt);
9479*7c568831SAndroid Build Coastguard Worker CHECK_ERROR;
9480*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9481*7c568831SAndroid Build Coastguard Worker while ((CUR == '+') || (CUR == '-')) {
9482*7c568831SAndroid Build Coastguard Worker int plus;
9483*7c568831SAndroid Build Coastguard Worker int op1 = ctxt->comp->last;
9484*7c568831SAndroid Build Coastguard Worker
9485*7c568831SAndroid Build Coastguard Worker if (CUR == '+') plus = 1;
9486*7c568831SAndroid Build Coastguard Worker else plus = 0;
9487*7c568831SAndroid Build Coastguard Worker NEXT;
9488*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9489*7c568831SAndroid Build Coastguard Worker xmlXPathCompMultiplicativeExpr(ctxt);
9490*7c568831SAndroid Build Coastguard Worker CHECK_ERROR;
9491*7c568831SAndroid Build Coastguard Worker PUSH_BINARY_EXPR(XPATH_OP_PLUS, op1, ctxt->comp->last, plus, 0);
9492*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9493*7c568831SAndroid Build Coastguard Worker }
9494*7c568831SAndroid Build Coastguard Worker }
9495*7c568831SAndroid Build Coastguard Worker
9496*7c568831SAndroid Build Coastguard Worker /**
9497*7c568831SAndroid Build Coastguard Worker * xmlXPathCompRelationalExpr:
9498*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9499*7c568831SAndroid Build Coastguard Worker *
9500*7c568831SAndroid Build Coastguard Worker * [24] RelationalExpr ::= AdditiveExpr
9501*7c568831SAndroid Build Coastguard Worker * | RelationalExpr '<' AdditiveExpr
9502*7c568831SAndroid Build Coastguard Worker * | RelationalExpr '>' AdditiveExpr
9503*7c568831SAndroid Build Coastguard Worker * | RelationalExpr '<=' AdditiveExpr
9504*7c568831SAndroid Build Coastguard Worker * | RelationalExpr '>=' AdditiveExpr
9505*7c568831SAndroid Build Coastguard Worker *
9506*7c568831SAndroid Build Coastguard Worker * A <= B > C is allowed ? Answer from James, yes with
9507*7c568831SAndroid Build Coastguard Worker * (AdditiveExpr <= AdditiveExpr) > AdditiveExpr
9508*7c568831SAndroid Build Coastguard Worker * which is basically what got implemented.
9509*7c568831SAndroid Build Coastguard Worker *
9510*7c568831SAndroid Build Coastguard Worker * Compile a Relational expression, then push the result
9511*7c568831SAndroid Build Coastguard Worker * on the stack
9512*7c568831SAndroid Build Coastguard Worker */
9513*7c568831SAndroid Build Coastguard Worker
9514*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompRelationalExpr(xmlXPathParserContextPtr ctxt)9515*7c568831SAndroid Build Coastguard Worker xmlXPathCompRelationalExpr(xmlXPathParserContextPtr ctxt) {
9516*7c568831SAndroid Build Coastguard Worker xmlXPathCompAdditiveExpr(ctxt);
9517*7c568831SAndroid Build Coastguard Worker CHECK_ERROR;
9518*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9519*7c568831SAndroid Build Coastguard Worker while ((CUR == '<') || (CUR == '>')) {
9520*7c568831SAndroid Build Coastguard Worker int inf, strict;
9521*7c568831SAndroid Build Coastguard Worker int op1 = ctxt->comp->last;
9522*7c568831SAndroid Build Coastguard Worker
9523*7c568831SAndroid Build Coastguard Worker if (CUR == '<') inf = 1;
9524*7c568831SAndroid Build Coastguard Worker else inf = 0;
9525*7c568831SAndroid Build Coastguard Worker if (NXT(1) == '=') strict = 0;
9526*7c568831SAndroid Build Coastguard Worker else strict = 1;
9527*7c568831SAndroid Build Coastguard Worker NEXT;
9528*7c568831SAndroid Build Coastguard Worker if (!strict) NEXT;
9529*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9530*7c568831SAndroid Build Coastguard Worker xmlXPathCompAdditiveExpr(ctxt);
9531*7c568831SAndroid Build Coastguard Worker CHECK_ERROR;
9532*7c568831SAndroid Build Coastguard Worker PUSH_BINARY_EXPR(XPATH_OP_CMP, op1, ctxt->comp->last, inf, strict);
9533*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9534*7c568831SAndroid Build Coastguard Worker }
9535*7c568831SAndroid Build Coastguard Worker }
9536*7c568831SAndroid Build Coastguard Worker
9537*7c568831SAndroid Build Coastguard Worker /**
9538*7c568831SAndroid Build Coastguard Worker * xmlXPathCompEqualityExpr:
9539*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9540*7c568831SAndroid Build Coastguard Worker *
9541*7c568831SAndroid Build Coastguard Worker * [23] EqualityExpr ::= RelationalExpr
9542*7c568831SAndroid Build Coastguard Worker * | EqualityExpr '=' RelationalExpr
9543*7c568831SAndroid Build Coastguard Worker * | EqualityExpr '!=' RelationalExpr
9544*7c568831SAndroid Build Coastguard Worker *
9545*7c568831SAndroid Build Coastguard Worker * A != B != C is allowed ? Answer from James, yes with
9546*7c568831SAndroid Build Coastguard Worker * (RelationalExpr = RelationalExpr) = RelationalExpr
9547*7c568831SAndroid Build Coastguard Worker * (RelationalExpr != RelationalExpr) != RelationalExpr
9548*7c568831SAndroid Build Coastguard Worker * which is basically what got implemented.
9549*7c568831SAndroid Build Coastguard Worker *
9550*7c568831SAndroid Build Coastguard Worker * Compile an Equality expression.
9551*7c568831SAndroid Build Coastguard Worker *
9552*7c568831SAndroid Build Coastguard Worker */
9553*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompEqualityExpr(xmlXPathParserContextPtr ctxt)9554*7c568831SAndroid Build Coastguard Worker xmlXPathCompEqualityExpr(xmlXPathParserContextPtr ctxt) {
9555*7c568831SAndroid Build Coastguard Worker xmlXPathCompRelationalExpr(ctxt);
9556*7c568831SAndroid Build Coastguard Worker CHECK_ERROR;
9557*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9558*7c568831SAndroid Build Coastguard Worker while ((CUR == '=') || ((CUR == '!') && (NXT(1) == '='))) {
9559*7c568831SAndroid Build Coastguard Worker int eq;
9560*7c568831SAndroid Build Coastguard Worker int op1 = ctxt->comp->last;
9561*7c568831SAndroid Build Coastguard Worker
9562*7c568831SAndroid Build Coastguard Worker if (CUR == '=') eq = 1;
9563*7c568831SAndroid Build Coastguard Worker else eq = 0;
9564*7c568831SAndroid Build Coastguard Worker NEXT;
9565*7c568831SAndroid Build Coastguard Worker if (!eq) NEXT;
9566*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9567*7c568831SAndroid Build Coastguard Worker xmlXPathCompRelationalExpr(ctxt);
9568*7c568831SAndroid Build Coastguard Worker CHECK_ERROR;
9569*7c568831SAndroid Build Coastguard Worker PUSH_BINARY_EXPR(XPATH_OP_EQUAL, op1, ctxt->comp->last, eq, 0);
9570*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9571*7c568831SAndroid Build Coastguard Worker }
9572*7c568831SAndroid Build Coastguard Worker }
9573*7c568831SAndroid Build Coastguard Worker
9574*7c568831SAndroid Build Coastguard Worker /**
9575*7c568831SAndroid Build Coastguard Worker * xmlXPathCompAndExpr:
9576*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9577*7c568831SAndroid Build Coastguard Worker *
9578*7c568831SAndroid Build Coastguard Worker * [22] AndExpr ::= EqualityExpr
9579*7c568831SAndroid Build Coastguard Worker * | AndExpr 'and' EqualityExpr
9580*7c568831SAndroid Build Coastguard Worker *
9581*7c568831SAndroid Build Coastguard Worker * Compile an AND expression.
9582*7c568831SAndroid Build Coastguard Worker *
9583*7c568831SAndroid Build Coastguard Worker */
9584*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompAndExpr(xmlXPathParserContextPtr ctxt)9585*7c568831SAndroid Build Coastguard Worker xmlXPathCompAndExpr(xmlXPathParserContextPtr ctxt) {
9586*7c568831SAndroid Build Coastguard Worker xmlXPathCompEqualityExpr(ctxt);
9587*7c568831SAndroid Build Coastguard Worker CHECK_ERROR;
9588*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9589*7c568831SAndroid Build Coastguard Worker while ((CUR == 'a') && (NXT(1) == 'n') && (NXT(2) == 'd')) {
9590*7c568831SAndroid Build Coastguard Worker int op1 = ctxt->comp->last;
9591*7c568831SAndroid Build Coastguard Worker SKIP(3);
9592*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9593*7c568831SAndroid Build Coastguard Worker xmlXPathCompEqualityExpr(ctxt);
9594*7c568831SAndroid Build Coastguard Worker CHECK_ERROR;
9595*7c568831SAndroid Build Coastguard Worker PUSH_BINARY_EXPR(XPATH_OP_AND, op1, ctxt->comp->last, 0, 0);
9596*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9597*7c568831SAndroid Build Coastguard Worker }
9598*7c568831SAndroid Build Coastguard Worker }
9599*7c568831SAndroid Build Coastguard Worker
9600*7c568831SAndroid Build Coastguard Worker /**
9601*7c568831SAndroid Build Coastguard Worker * xmlXPathCompileExpr:
9602*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9603*7c568831SAndroid Build Coastguard Worker *
9604*7c568831SAndroid Build Coastguard Worker * [14] Expr ::= OrExpr
9605*7c568831SAndroid Build Coastguard Worker * [21] OrExpr ::= AndExpr
9606*7c568831SAndroid Build Coastguard Worker * | OrExpr 'or' AndExpr
9607*7c568831SAndroid Build Coastguard Worker *
9608*7c568831SAndroid Build Coastguard Worker * Parse and compile an expression
9609*7c568831SAndroid Build Coastguard Worker */
9610*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt,int sort)9611*7c568831SAndroid Build Coastguard Worker xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt, int sort) {
9612*7c568831SAndroid Build Coastguard Worker xmlXPathContextPtr xpctxt = ctxt->context;
9613*7c568831SAndroid Build Coastguard Worker
9614*7c568831SAndroid Build Coastguard Worker if (xpctxt != NULL) {
9615*7c568831SAndroid Build Coastguard Worker if (xpctxt->depth >= XPATH_MAX_RECURSION_DEPTH)
9616*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_RECURSION_LIMIT_EXCEEDED);
9617*7c568831SAndroid Build Coastguard Worker /*
9618*7c568831SAndroid Build Coastguard Worker * Parsing a single '(' pushes about 10 functions on the call stack
9619*7c568831SAndroid Build Coastguard Worker * before recursing!
9620*7c568831SAndroid Build Coastguard Worker */
9621*7c568831SAndroid Build Coastguard Worker xpctxt->depth += 10;
9622*7c568831SAndroid Build Coastguard Worker }
9623*7c568831SAndroid Build Coastguard Worker
9624*7c568831SAndroid Build Coastguard Worker xmlXPathCompAndExpr(ctxt);
9625*7c568831SAndroid Build Coastguard Worker CHECK_ERROR;
9626*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9627*7c568831SAndroid Build Coastguard Worker while ((CUR == 'o') && (NXT(1) == 'r')) {
9628*7c568831SAndroid Build Coastguard Worker int op1 = ctxt->comp->last;
9629*7c568831SAndroid Build Coastguard Worker SKIP(2);
9630*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9631*7c568831SAndroid Build Coastguard Worker xmlXPathCompAndExpr(ctxt);
9632*7c568831SAndroid Build Coastguard Worker CHECK_ERROR;
9633*7c568831SAndroid Build Coastguard Worker PUSH_BINARY_EXPR(XPATH_OP_OR, op1, ctxt->comp->last, 0, 0);
9634*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9635*7c568831SAndroid Build Coastguard Worker }
9636*7c568831SAndroid Build Coastguard Worker if ((sort) && (ctxt->comp->steps[ctxt->comp->last].op != XPATH_OP_VALUE)) {
9637*7c568831SAndroid Build Coastguard Worker /* more ops could be optimized too */
9638*7c568831SAndroid Build Coastguard Worker /*
9639*7c568831SAndroid Build Coastguard Worker * This is the main place to eliminate sorting for
9640*7c568831SAndroid Build Coastguard Worker * operations which don't require a sorted node-set.
9641*7c568831SAndroid Build Coastguard Worker * E.g. count().
9642*7c568831SAndroid Build Coastguard Worker */
9643*7c568831SAndroid Build Coastguard Worker PUSH_UNARY_EXPR(XPATH_OP_SORT, ctxt->comp->last , 0, 0);
9644*7c568831SAndroid Build Coastguard Worker }
9645*7c568831SAndroid Build Coastguard Worker
9646*7c568831SAndroid Build Coastguard Worker if (xpctxt != NULL)
9647*7c568831SAndroid Build Coastguard Worker xpctxt->depth -= 10;
9648*7c568831SAndroid Build Coastguard Worker }
9649*7c568831SAndroid Build Coastguard Worker
9650*7c568831SAndroid Build Coastguard Worker /**
9651*7c568831SAndroid Build Coastguard Worker * xmlXPathCompPredicate:
9652*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9653*7c568831SAndroid Build Coastguard Worker * @filter: act as a filter
9654*7c568831SAndroid Build Coastguard Worker *
9655*7c568831SAndroid Build Coastguard Worker * [8] Predicate ::= '[' PredicateExpr ']'
9656*7c568831SAndroid Build Coastguard Worker * [9] PredicateExpr ::= Expr
9657*7c568831SAndroid Build Coastguard Worker *
9658*7c568831SAndroid Build Coastguard Worker * Compile a predicate expression
9659*7c568831SAndroid Build Coastguard Worker */
9660*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt,int filter)9661*7c568831SAndroid Build Coastguard Worker xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter) {
9662*7c568831SAndroid Build Coastguard Worker int op1 = ctxt->comp->last;
9663*7c568831SAndroid Build Coastguard Worker
9664*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9665*7c568831SAndroid Build Coastguard Worker if (CUR != '[') {
9666*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
9667*7c568831SAndroid Build Coastguard Worker }
9668*7c568831SAndroid Build Coastguard Worker NEXT;
9669*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9670*7c568831SAndroid Build Coastguard Worker
9671*7c568831SAndroid Build Coastguard Worker ctxt->comp->last = -1;
9672*7c568831SAndroid Build Coastguard Worker /*
9673*7c568831SAndroid Build Coastguard Worker * This call to xmlXPathCompileExpr() will deactivate sorting
9674*7c568831SAndroid Build Coastguard Worker * of the predicate result.
9675*7c568831SAndroid Build Coastguard Worker * TODO: Sorting is still activated for filters, since I'm not
9676*7c568831SAndroid Build Coastguard Worker * sure if needed. Normally sorting should not be needed, since
9677*7c568831SAndroid Build Coastguard Worker * a filter can only diminish the number of items in a sequence,
9678*7c568831SAndroid Build Coastguard Worker * but won't change its order; so if the initial sequence is sorted,
9679*7c568831SAndroid Build Coastguard Worker * subsequent sorting is not needed.
9680*7c568831SAndroid Build Coastguard Worker */
9681*7c568831SAndroid Build Coastguard Worker if (! filter)
9682*7c568831SAndroid Build Coastguard Worker xmlXPathCompileExpr(ctxt, 0);
9683*7c568831SAndroid Build Coastguard Worker else
9684*7c568831SAndroid Build Coastguard Worker xmlXPathCompileExpr(ctxt, 1);
9685*7c568831SAndroid Build Coastguard Worker CHECK_ERROR;
9686*7c568831SAndroid Build Coastguard Worker
9687*7c568831SAndroid Build Coastguard Worker if (CUR != ']') {
9688*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
9689*7c568831SAndroid Build Coastguard Worker }
9690*7c568831SAndroid Build Coastguard Worker
9691*7c568831SAndroid Build Coastguard Worker if (filter)
9692*7c568831SAndroid Build Coastguard Worker PUSH_BINARY_EXPR(XPATH_OP_FILTER, op1, ctxt->comp->last, 0, 0);
9693*7c568831SAndroid Build Coastguard Worker else
9694*7c568831SAndroid Build Coastguard Worker PUSH_BINARY_EXPR(XPATH_OP_PREDICATE, op1, ctxt->comp->last, 0, 0);
9695*7c568831SAndroid Build Coastguard Worker
9696*7c568831SAndroid Build Coastguard Worker NEXT;
9697*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9698*7c568831SAndroid Build Coastguard Worker }
9699*7c568831SAndroid Build Coastguard Worker
9700*7c568831SAndroid Build Coastguard Worker /**
9701*7c568831SAndroid Build Coastguard Worker * xmlXPathCompNodeTest:
9702*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9703*7c568831SAndroid Build Coastguard Worker * @test: pointer to a xmlXPathTestVal
9704*7c568831SAndroid Build Coastguard Worker * @type: pointer to a xmlXPathTypeVal
9705*7c568831SAndroid Build Coastguard Worker * @prefix: placeholder for a possible name prefix
9706*7c568831SAndroid Build Coastguard Worker *
9707*7c568831SAndroid Build Coastguard Worker * [7] NodeTest ::= NameTest
9708*7c568831SAndroid Build Coastguard Worker * | NodeType '(' ')'
9709*7c568831SAndroid Build Coastguard Worker * | 'processing-instruction' '(' Literal ')'
9710*7c568831SAndroid Build Coastguard Worker *
9711*7c568831SAndroid Build Coastguard Worker * [37] NameTest ::= '*'
9712*7c568831SAndroid Build Coastguard Worker * | NCName ':' '*'
9713*7c568831SAndroid Build Coastguard Worker * | QName
9714*7c568831SAndroid Build Coastguard Worker * [38] NodeType ::= 'comment'
9715*7c568831SAndroid Build Coastguard Worker * | 'text'
9716*7c568831SAndroid Build Coastguard Worker * | 'processing-instruction'
9717*7c568831SAndroid Build Coastguard Worker * | 'node'
9718*7c568831SAndroid Build Coastguard Worker *
9719*7c568831SAndroid Build Coastguard Worker * Returns the name found and updates @test, @type and @prefix appropriately
9720*7c568831SAndroid Build Coastguard Worker */
9721*7c568831SAndroid Build Coastguard Worker static xmlChar *
xmlXPathCompNodeTest(xmlXPathParserContextPtr ctxt,xmlXPathTestVal * test,xmlXPathTypeVal * type,xmlChar ** prefix,xmlChar * name)9722*7c568831SAndroid Build Coastguard Worker xmlXPathCompNodeTest(xmlXPathParserContextPtr ctxt, xmlXPathTestVal *test,
9723*7c568831SAndroid Build Coastguard Worker xmlXPathTypeVal *type, xmlChar **prefix,
9724*7c568831SAndroid Build Coastguard Worker xmlChar *name) {
9725*7c568831SAndroid Build Coastguard Worker int blanks;
9726*7c568831SAndroid Build Coastguard Worker
9727*7c568831SAndroid Build Coastguard Worker if ((test == NULL) || (type == NULL) || (prefix == NULL)) {
9728*7c568831SAndroid Build Coastguard Worker return(NULL);
9729*7c568831SAndroid Build Coastguard Worker }
9730*7c568831SAndroid Build Coastguard Worker *type = (xmlXPathTypeVal) 0;
9731*7c568831SAndroid Build Coastguard Worker *test = (xmlXPathTestVal) 0;
9732*7c568831SAndroid Build Coastguard Worker *prefix = NULL;
9733*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9734*7c568831SAndroid Build Coastguard Worker
9735*7c568831SAndroid Build Coastguard Worker if ((name == NULL) && (CUR == '*')) {
9736*7c568831SAndroid Build Coastguard Worker /*
9737*7c568831SAndroid Build Coastguard Worker * All elements
9738*7c568831SAndroid Build Coastguard Worker */
9739*7c568831SAndroid Build Coastguard Worker NEXT;
9740*7c568831SAndroid Build Coastguard Worker *test = NODE_TEST_ALL;
9741*7c568831SAndroid Build Coastguard Worker return(NULL);
9742*7c568831SAndroid Build Coastguard Worker }
9743*7c568831SAndroid Build Coastguard Worker
9744*7c568831SAndroid Build Coastguard Worker if (name == NULL)
9745*7c568831SAndroid Build Coastguard Worker name = xmlXPathParseNCName(ctxt);
9746*7c568831SAndroid Build Coastguard Worker if (name == NULL) {
9747*7c568831SAndroid Build Coastguard Worker XP_ERRORNULL(XPATH_EXPR_ERROR);
9748*7c568831SAndroid Build Coastguard Worker }
9749*7c568831SAndroid Build Coastguard Worker
9750*7c568831SAndroid Build Coastguard Worker blanks = IS_BLANK_CH(CUR);
9751*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9752*7c568831SAndroid Build Coastguard Worker if (CUR == '(') {
9753*7c568831SAndroid Build Coastguard Worker NEXT;
9754*7c568831SAndroid Build Coastguard Worker /*
9755*7c568831SAndroid Build Coastguard Worker * NodeType or PI search
9756*7c568831SAndroid Build Coastguard Worker */
9757*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "comment"))
9758*7c568831SAndroid Build Coastguard Worker *type = NODE_TYPE_COMMENT;
9759*7c568831SAndroid Build Coastguard Worker else if (xmlStrEqual(name, BAD_CAST "node"))
9760*7c568831SAndroid Build Coastguard Worker *type = NODE_TYPE_NODE;
9761*7c568831SAndroid Build Coastguard Worker else if (xmlStrEqual(name, BAD_CAST "processing-instruction"))
9762*7c568831SAndroid Build Coastguard Worker *type = NODE_TYPE_PI;
9763*7c568831SAndroid Build Coastguard Worker else if (xmlStrEqual(name, BAD_CAST "text"))
9764*7c568831SAndroid Build Coastguard Worker *type = NODE_TYPE_TEXT;
9765*7c568831SAndroid Build Coastguard Worker else {
9766*7c568831SAndroid Build Coastguard Worker if (name != NULL)
9767*7c568831SAndroid Build Coastguard Worker xmlFree(name);
9768*7c568831SAndroid Build Coastguard Worker XP_ERRORNULL(XPATH_EXPR_ERROR);
9769*7c568831SAndroid Build Coastguard Worker }
9770*7c568831SAndroid Build Coastguard Worker
9771*7c568831SAndroid Build Coastguard Worker *test = NODE_TEST_TYPE;
9772*7c568831SAndroid Build Coastguard Worker
9773*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9774*7c568831SAndroid Build Coastguard Worker if (*type == NODE_TYPE_PI) {
9775*7c568831SAndroid Build Coastguard Worker /*
9776*7c568831SAndroid Build Coastguard Worker * Specific case: search a PI by name.
9777*7c568831SAndroid Build Coastguard Worker */
9778*7c568831SAndroid Build Coastguard Worker if (name != NULL)
9779*7c568831SAndroid Build Coastguard Worker xmlFree(name);
9780*7c568831SAndroid Build Coastguard Worker name = NULL;
9781*7c568831SAndroid Build Coastguard Worker if (CUR != ')') {
9782*7c568831SAndroid Build Coastguard Worker name = xmlXPathParseLiteral(ctxt);
9783*7c568831SAndroid Build Coastguard Worker *test = NODE_TEST_PI;
9784*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9785*7c568831SAndroid Build Coastguard Worker }
9786*7c568831SAndroid Build Coastguard Worker }
9787*7c568831SAndroid Build Coastguard Worker if (CUR != ')') {
9788*7c568831SAndroid Build Coastguard Worker if (name != NULL)
9789*7c568831SAndroid Build Coastguard Worker xmlFree(name);
9790*7c568831SAndroid Build Coastguard Worker XP_ERRORNULL(XPATH_UNCLOSED_ERROR);
9791*7c568831SAndroid Build Coastguard Worker }
9792*7c568831SAndroid Build Coastguard Worker NEXT;
9793*7c568831SAndroid Build Coastguard Worker return(name);
9794*7c568831SAndroid Build Coastguard Worker }
9795*7c568831SAndroid Build Coastguard Worker *test = NODE_TEST_NAME;
9796*7c568831SAndroid Build Coastguard Worker if ((!blanks) && (CUR == ':')) {
9797*7c568831SAndroid Build Coastguard Worker NEXT;
9798*7c568831SAndroid Build Coastguard Worker
9799*7c568831SAndroid Build Coastguard Worker /*
9800*7c568831SAndroid Build Coastguard Worker * Since currently the parser context don't have a
9801*7c568831SAndroid Build Coastguard Worker * namespace list associated:
9802*7c568831SAndroid Build Coastguard Worker * The namespace name for this prefix can be computed
9803*7c568831SAndroid Build Coastguard Worker * only at evaluation time. The compilation is done
9804*7c568831SAndroid Build Coastguard Worker * outside of any context.
9805*7c568831SAndroid Build Coastguard Worker */
9806*7c568831SAndroid Build Coastguard Worker *prefix = name;
9807*7c568831SAndroid Build Coastguard Worker
9808*7c568831SAndroid Build Coastguard Worker if (CUR == '*') {
9809*7c568831SAndroid Build Coastguard Worker /*
9810*7c568831SAndroid Build Coastguard Worker * All elements
9811*7c568831SAndroid Build Coastguard Worker */
9812*7c568831SAndroid Build Coastguard Worker NEXT;
9813*7c568831SAndroid Build Coastguard Worker *test = NODE_TEST_ALL;
9814*7c568831SAndroid Build Coastguard Worker return(NULL);
9815*7c568831SAndroid Build Coastguard Worker }
9816*7c568831SAndroid Build Coastguard Worker
9817*7c568831SAndroid Build Coastguard Worker name = xmlXPathParseNCName(ctxt);
9818*7c568831SAndroid Build Coastguard Worker if (name == NULL) {
9819*7c568831SAndroid Build Coastguard Worker XP_ERRORNULL(XPATH_EXPR_ERROR);
9820*7c568831SAndroid Build Coastguard Worker }
9821*7c568831SAndroid Build Coastguard Worker }
9822*7c568831SAndroid Build Coastguard Worker return(name);
9823*7c568831SAndroid Build Coastguard Worker }
9824*7c568831SAndroid Build Coastguard Worker
9825*7c568831SAndroid Build Coastguard Worker /**
9826*7c568831SAndroid Build Coastguard Worker * xmlXPathIsAxisName:
9827*7c568831SAndroid Build Coastguard Worker * @name: a preparsed name token
9828*7c568831SAndroid Build Coastguard Worker *
9829*7c568831SAndroid Build Coastguard Worker * [6] AxisName ::= 'ancestor'
9830*7c568831SAndroid Build Coastguard Worker * | 'ancestor-or-self'
9831*7c568831SAndroid Build Coastguard Worker * | 'attribute'
9832*7c568831SAndroid Build Coastguard Worker * | 'child'
9833*7c568831SAndroid Build Coastguard Worker * | 'descendant'
9834*7c568831SAndroid Build Coastguard Worker * | 'descendant-or-self'
9835*7c568831SAndroid Build Coastguard Worker * | 'following'
9836*7c568831SAndroid Build Coastguard Worker * | 'following-sibling'
9837*7c568831SAndroid Build Coastguard Worker * | 'namespace'
9838*7c568831SAndroid Build Coastguard Worker * | 'parent'
9839*7c568831SAndroid Build Coastguard Worker * | 'preceding'
9840*7c568831SAndroid Build Coastguard Worker * | 'preceding-sibling'
9841*7c568831SAndroid Build Coastguard Worker * | 'self'
9842*7c568831SAndroid Build Coastguard Worker *
9843*7c568831SAndroid Build Coastguard Worker * Returns the axis or 0
9844*7c568831SAndroid Build Coastguard Worker */
9845*7c568831SAndroid Build Coastguard Worker static xmlXPathAxisVal
xmlXPathIsAxisName(const xmlChar * name)9846*7c568831SAndroid Build Coastguard Worker xmlXPathIsAxisName(const xmlChar *name) {
9847*7c568831SAndroid Build Coastguard Worker xmlXPathAxisVal ret = (xmlXPathAxisVal) 0;
9848*7c568831SAndroid Build Coastguard Worker switch (name[0]) {
9849*7c568831SAndroid Build Coastguard Worker case 'a':
9850*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "ancestor"))
9851*7c568831SAndroid Build Coastguard Worker ret = AXIS_ANCESTOR;
9852*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "ancestor-or-self"))
9853*7c568831SAndroid Build Coastguard Worker ret = AXIS_ANCESTOR_OR_SELF;
9854*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "attribute"))
9855*7c568831SAndroid Build Coastguard Worker ret = AXIS_ATTRIBUTE;
9856*7c568831SAndroid Build Coastguard Worker break;
9857*7c568831SAndroid Build Coastguard Worker case 'c':
9858*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "child"))
9859*7c568831SAndroid Build Coastguard Worker ret = AXIS_CHILD;
9860*7c568831SAndroid Build Coastguard Worker break;
9861*7c568831SAndroid Build Coastguard Worker case 'd':
9862*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "descendant"))
9863*7c568831SAndroid Build Coastguard Worker ret = AXIS_DESCENDANT;
9864*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "descendant-or-self"))
9865*7c568831SAndroid Build Coastguard Worker ret = AXIS_DESCENDANT_OR_SELF;
9866*7c568831SAndroid Build Coastguard Worker break;
9867*7c568831SAndroid Build Coastguard Worker case 'f':
9868*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "following"))
9869*7c568831SAndroid Build Coastguard Worker ret = AXIS_FOLLOWING;
9870*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "following-sibling"))
9871*7c568831SAndroid Build Coastguard Worker ret = AXIS_FOLLOWING_SIBLING;
9872*7c568831SAndroid Build Coastguard Worker break;
9873*7c568831SAndroid Build Coastguard Worker case 'n':
9874*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "namespace"))
9875*7c568831SAndroid Build Coastguard Worker ret = AXIS_NAMESPACE;
9876*7c568831SAndroid Build Coastguard Worker break;
9877*7c568831SAndroid Build Coastguard Worker case 'p':
9878*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "parent"))
9879*7c568831SAndroid Build Coastguard Worker ret = AXIS_PARENT;
9880*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "preceding"))
9881*7c568831SAndroid Build Coastguard Worker ret = AXIS_PRECEDING;
9882*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "preceding-sibling"))
9883*7c568831SAndroid Build Coastguard Worker ret = AXIS_PRECEDING_SIBLING;
9884*7c568831SAndroid Build Coastguard Worker break;
9885*7c568831SAndroid Build Coastguard Worker case 's':
9886*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "self"))
9887*7c568831SAndroid Build Coastguard Worker ret = AXIS_SELF;
9888*7c568831SAndroid Build Coastguard Worker break;
9889*7c568831SAndroid Build Coastguard Worker }
9890*7c568831SAndroid Build Coastguard Worker return(ret);
9891*7c568831SAndroid Build Coastguard Worker }
9892*7c568831SAndroid Build Coastguard Worker
9893*7c568831SAndroid Build Coastguard Worker /**
9894*7c568831SAndroid Build Coastguard Worker * xmlXPathCompStep:
9895*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9896*7c568831SAndroid Build Coastguard Worker *
9897*7c568831SAndroid Build Coastguard Worker * [4] Step ::= AxisSpecifier NodeTest Predicate*
9898*7c568831SAndroid Build Coastguard Worker * | AbbreviatedStep
9899*7c568831SAndroid Build Coastguard Worker *
9900*7c568831SAndroid Build Coastguard Worker * [12] AbbreviatedStep ::= '.' | '..'
9901*7c568831SAndroid Build Coastguard Worker *
9902*7c568831SAndroid Build Coastguard Worker * [5] AxisSpecifier ::= AxisName '::'
9903*7c568831SAndroid Build Coastguard Worker * | AbbreviatedAxisSpecifier
9904*7c568831SAndroid Build Coastguard Worker *
9905*7c568831SAndroid Build Coastguard Worker * [13] AbbreviatedAxisSpecifier ::= '@'?
9906*7c568831SAndroid Build Coastguard Worker *
9907*7c568831SAndroid Build Coastguard Worker * Modified for XPtr range support as:
9908*7c568831SAndroid Build Coastguard Worker *
9909*7c568831SAndroid Build Coastguard Worker * [4xptr] Step ::= AxisSpecifier NodeTest Predicate*
9910*7c568831SAndroid Build Coastguard Worker * | AbbreviatedStep
9911*7c568831SAndroid Build Coastguard Worker * | 'range-to' '(' Expr ')' Predicate*
9912*7c568831SAndroid Build Coastguard Worker *
9913*7c568831SAndroid Build Coastguard Worker * Compile one step in a Location Path
9914*7c568831SAndroid Build Coastguard Worker * A location step of . is short for self::node(). This is
9915*7c568831SAndroid Build Coastguard Worker * particularly useful in conjunction with //. For example, the
9916*7c568831SAndroid Build Coastguard Worker * location path .//para is short for
9917*7c568831SAndroid Build Coastguard Worker * self::node()/descendant-or-self::node()/child::para
9918*7c568831SAndroid Build Coastguard Worker * and so will select all para descendant elements of the context
9919*7c568831SAndroid Build Coastguard Worker * node.
9920*7c568831SAndroid Build Coastguard Worker * Similarly, a location step of .. is short for parent::node().
9921*7c568831SAndroid Build Coastguard Worker * For example, ../title is short for parent::node()/child::title
9922*7c568831SAndroid Build Coastguard Worker * and so will select the title children of the parent of the context
9923*7c568831SAndroid Build Coastguard Worker * node.
9924*7c568831SAndroid Build Coastguard Worker */
9925*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompStep(xmlXPathParserContextPtr ctxt)9926*7c568831SAndroid Build Coastguard Worker xmlXPathCompStep(xmlXPathParserContextPtr ctxt) {
9927*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9928*7c568831SAndroid Build Coastguard Worker if ((CUR == '.') && (NXT(1) == '.')) {
9929*7c568831SAndroid Build Coastguard Worker SKIP(2);
9930*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9931*7c568831SAndroid Build Coastguard Worker PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_PARENT,
9932*7c568831SAndroid Build Coastguard Worker NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
9933*7c568831SAndroid Build Coastguard Worker } else if (CUR == '.') {
9934*7c568831SAndroid Build Coastguard Worker NEXT;
9935*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9936*7c568831SAndroid Build Coastguard Worker } else {
9937*7c568831SAndroid Build Coastguard Worker xmlChar *name = NULL;
9938*7c568831SAndroid Build Coastguard Worker xmlChar *prefix = NULL;
9939*7c568831SAndroid Build Coastguard Worker xmlXPathTestVal test = (xmlXPathTestVal) 0;
9940*7c568831SAndroid Build Coastguard Worker xmlXPathAxisVal axis = (xmlXPathAxisVal) 0;
9941*7c568831SAndroid Build Coastguard Worker xmlXPathTypeVal type = (xmlXPathTypeVal) 0;
9942*7c568831SAndroid Build Coastguard Worker int op1;
9943*7c568831SAndroid Build Coastguard Worker
9944*7c568831SAndroid Build Coastguard Worker if (CUR == '*') {
9945*7c568831SAndroid Build Coastguard Worker axis = AXIS_CHILD;
9946*7c568831SAndroid Build Coastguard Worker } else {
9947*7c568831SAndroid Build Coastguard Worker if (name == NULL)
9948*7c568831SAndroid Build Coastguard Worker name = xmlXPathParseNCName(ctxt);
9949*7c568831SAndroid Build Coastguard Worker if (name != NULL) {
9950*7c568831SAndroid Build Coastguard Worker axis = xmlXPathIsAxisName(name);
9951*7c568831SAndroid Build Coastguard Worker if (axis != 0) {
9952*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9953*7c568831SAndroid Build Coastguard Worker if ((CUR == ':') && (NXT(1) == ':')) {
9954*7c568831SAndroid Build Coastguard Worker SKIP(2);
9955*7c568831SAndroid Build Coastguard Worker xmlFree(name);
9956*7c568831SAndroid Build Coastguard Worker name = NULL;
9957*7c568831SAndroid Build Coastguard Worker } else {
9958*7c568831SAndroid Build Coastguard Worker /* an element name can conflict with an axis one :-\ */
9959*7c568831SAndroid Build Coastguard Worker axis = AXIS_CHILD;
9960*7c568831SAndroid Build Coastguard Worker }
9961*7c568831SAndroid Build Coastguard Worker } else {
9962*7c568831SAndroid Build Coastguard Worker axis = AXIS_CHILD;
9963*7c568831SAndroid Build Coastguard Worker }
9964*7c568831SAndroid Build Coastguard Worker } else if (CUR == '@') {
9965*7c568831SAndroid Build Coastguard Worker NEXT;
9966*7c568831SAndroid Build Coastguard Worker axis = AXIS_ATTRIBUTE;
9967*7c568831SAndroid Build Coastguard Worker } else {
9968*7c568831SAndroid Build Coastguard Worker axis = AXIS_CHILD;
9969*7c568831SAndroid Build Coastguard Worker }
9970*7c568831SAndroid Build Coastguard Worker }
9971*7c568831SAndroid Build Coastguard Worker
9972*7c568831SAndroid Build Coastguard Worker if (ctxt->error != XPATH_EXPRESSION_OK) {
9973*7c568831SAndroid Build Coastguard Worker xmlFree(name);
9974*7c568831SAndroid Build Coastguard Worker return;
9975*7c568831SAndroid Build Coastguard Worker }
9976*7c568831SAndroid Build Coastguard Worker
9977*7c568831SAndroid Build Coastguard Worker name = xmlXPathCompNodeTest(ctxt, &test, &type, &prefix, name);
9978*7c568831SAndroid Build Coastguard Worker if (test == 0)
9979*7c568831SAndroid Build Coastguard Worker return;
9980*7c568831SAndroid Build Coastguard Worker
9981*7c568831SAndroid Build Coastguard Worker if ((prefix != NULL) && (ctxt->context != NULL) &&
9982*7c568831SAndroid Build Coastguard Worker (ctxt->context->flags & XML_XPATH_CHECKNS)) {
9983*7c568831SAndroid Build Coastguard Worker if (xmlXPathNsLookup(ctxt->context, prefix) == NULL) {
9984*7c568831SAndroid Build Coastguard Worker xmlXPathErr(ctxt, XPATH_UNDEF_PREFIX_ERROR);
9985*7c568831SAndroid Build Coastguard Worker }
9986*7c568831SAndroid Build Coastguard Worker }
9987*7c568831SAndroid Build Coastguard Worker
9988*7c568831SAndroid Build Coastguard Worker op1 = ctxt->comp->last;
9989*7c568831SAndroid Build Coastguard Worker ctxt->comp->last = -1;
9990*7c568831SAndroid Build Coastguard Worker
9991*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
9992*7c568831SAndroid Build Coastguard Worker while (CUR == '[') {
9993*7c568831SAndroid Build Coastguard Worker xmlXPathCompPredicate(ctxt, 0);
9994*7c568831SAndroid Build Coastguard Worker }
9995*7c568831SAndroid Build Coastguard Worker
9996*7c568831SAndroid Build Coastguard Worker if (PUSH_FULL_EXPR(XPATH_OP_COLLECT, op1, ctxt->comp->last, axis,
9997*7c568831SAndroid Build Coastguard Worker test, type, (void *)prefix, (void *)name) == -1) {
9998*7c568831SAndroid Build Coastguard Worker xmlFree(prefix);
9999*7c568831SAndroid Build Coastguard Worker xmlFree(name);
10000*7c568831SAndroid Build Coastguard Worker }
10001*7c568831SAndroid Build Coastguard Worker }
10002*7c568831SAndroid Build Coastguard Worker }
10003*7c568831SAndroid Build Coastguard Worker
10004*7c568831SAndroid Build Coastguard Worker /**
10005*7c568831SAndroid Build Coastguard Worker * xmlXPathCompRelativeLocationPath:
10006*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
10007*7c568831SAndroid Build Coastguard Worker *
10008*7c568831SAndroid Build Coastguard Worker * [3] RelativeLocationPath ::= Step
10009*7c568831SAndroid Build Coastguard Worker * | RelativeLocationPath '/' Step
10010*7c568831SAndroid Build Coastguard Worker * | AbbreviatedRelativeLocationPath
10011*7c568831SAndroid Build Coastguard Worker * [11] AbbreviatedRelativeLocationPath ::= RelativeLocationPath '//' Step
10012*7c568831SAndroid Build Coastguard Worker *
10013*7c568831SAndroid Build Coastguard Worker * Compile a relative location path.
10014*7c568831SAndroid Build Coastguard Worker */
10015*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompRelativeLocationPath(xmlXPathParserContextPtr ctxt)10016*7c568831SAndroid Build Coastguard Worker xmlXPathCompRelativeLocationPath
10017*7c568831SAndroid Build Coastguard Worker (xmlXPathParserContextPtr ctxt) {
10018*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
10019*7c568831SAndroid Build Coastguard Worker if ((CUR == '/') && (NXT(1) == '/')) {
10020*7c568831SAndroid Build Coastguard Worker SKIP(2);
10021*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
10022*7c568831SAndroid Build Coastguard Worker PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
10023*7c568831SAndroid Build Coastguard Worker NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
10024*7c568831SAndroid Build Coastguard Worker } else if (CUR == '/') {
10025*7c568831SAndroid Build Coastguard Worker NEXT;
10026*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
10027*7c568831SAndroid Build Coastguard Worker }
10028*7c568831SAndroid Build Coastguard Worker xmlXPathCompStep(ctxt);
10029*7c568831SAndroid Build Coastguard Worker CHECK_ERROR;
10030*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
10031*7c568831SAndroid Build Coastguard Worker while (CUR == '/') {
10032*7c568831SAndroid Build Coastguard Worker if ((CUR == '/') && (NXT(1) == '/')) {
10033*7c568831SAndroid Build Coastguard Worker SKIP(2);
10034*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
10035*7c568831SAndroid Build Coastguard Worker PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
10036*7c568831SAndroid Build Coastguard Worker NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
10037*7c568831SAndroid Build Coastguard Worker xmlXPathCompStep(ctxt);
10038*7c568831SAndroid Build Coastguard Worker } else if (CUR == '/') {
10039*7c568831SAndroid Build Coastguard Worker NEXT;
10040*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
10041*7c568831SAndroid Build Coastguard Worker xmlXPathCompStep(ctxt);
10042*7c568831SAndroid Build Coastguard Worker }
10043*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
10044*7c568831SAndroid Build Coastguard Worker }
10045*7c568831SAndroid Build Coastguard Worker }
10046*7c568831SAndroid Build Coastguard Worker
10047*7c568831SAndroid Build Coastguard Worker /**
10048*7c568831SAndroid Build Coastguard Worker * xmlXPathCompLocationPath:
10049*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
10050*7c568831SAndroid Build Coastguard Worker *
10051*7c568831SAndroid Build Coastguard Worker * [1] LocationPath ::= RelativeLocationPath
10052*7c568831SAndroid Build Coastguard Worker * | AbsoluteLocationPath
10053*7c568831SAndroid Build Coastguard Worker * [2] AbsoluteLocationPath ::= '/' RelativeLocationPath?
10054*7c568831SAndroid Build Coastguard Worker * | AbbreviatedAbsoluteLocationPath
10055*7c568831SAndroid Build Coastguard Worker * [10] AbbreviatedAbsoluteLocationPath ::=
10056*7c568831SAndroid Build Coastguard Worker * '//' RelativeLocationPath
10057*7c568831SAndroid Build Coastguard Worker *
10058*7c568831SAndroid Build Coastguard Worker * Compile a location path
10059*7c568831SAndroid Build Coastguard Worker *
10060*7c568831SAndroid Build Coastguard Worker * // is short for /descendant-or-self::node()/. For example,
10061*7c568831SAndroid Build Coastguard Worker * //para is short for /descendant-or-self::node()/child::para and
10062*7c568831SAndroid Build Coastguard Worker * so will select any para element in the document (even a para element
10063*7c568831SAndroid Build Coastguard Worker * that is a document element will be selected by //para since the
10064*7c568831SAndroid Build Coastguard Worker * document element node is a child of the root node); div//para is
10065*7c568831SAndroid Build Coastguard Worker * short for div/descendant-or-self::node()/child::para and so will
10066*7c568831SAndroid Build Coastguard Worker * select all para descendants of div children.
10067*7c568831SAndroid Build Coastguard Worker */
10068*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompLocationPath(xmlXPathParserContextPtr ctxt)10069*7c568831SAndroid Build Coastguard Worker xmlXPathCompLocationPath(xmlXPathParserContextPtr ctxt) {
10070*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
10071*7c568831SAndroid Build Coastguard Worker if (CUR != '/') {
10072*7c568831SAndroid Build Coastguard Worker xmlXPathCompRelativeLocationPath(ctxt);
10073*7c568831SAndroid Build Coastguard Worker } else {
10074*7c568831SAndroid Build Coastguard Worker while (CUR == '/') {
10075*7c568831SAndroid Build Coastguard Worker if ((CUR == '/') && (NXT(1) == '/')) {
10076*7c568831SAndroid Build Coastguard Worker SKIP(2);
10077*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
10078*7c568831SAndroid Build Coastguard Worker PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
10079*7c568831SAndroid Build Coastguard Worker NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
10080*7c568831SAndroid Build Coastguard Worker xmlXPathCompRelativeLocationPath(ctxt);
10081*7c568831SAndroid Build Coastguard Worker } else if (CUR == '/') {
10082*7c568831SAndroid Build Coastguard Worker NEXT;
10083*7c568831SAndroid Build Coastguard Worker SKIP_BLANKS;
10084*7c568831SAndroid Build Coastguard Worker if ((CUR != 0 ) &&
10085*7c568831SAndroid Build Coastguard Worker ((IS_ASCII_LETTER(CUR)) || (CUR == '_') || (CUR == '.') ||
10086*7c568831SAndroid Build Coastguard Worker (CUR == '@') || (CUR == '*')))
10087*7c568831SAndroid Build Coastguard Worker xmlXPathCompRelativeLocationPath(ctxt);
10088*7c568831SAndroid Build Coastguard Worker }
10089*7c568831SAndroid Build Coastguard Worker CHECK_ERROR;
10090*7c568831SAndroid Build Coastguard Worker }
10091*7c568831SAndroid Build Coastguard Worker }
10092*7c568831SAndroid Build Coastguard Worker }
10093*7c568831SAndroid Build Coastguard Worker
10094*7c568831SAndroid Build Coastguard Worker /************************************************************************
10095*7c568831SAndroid Build Coastguard Worker * *
10096*7c568831SAndroid Build Coastguard Worker * XPath precompiled expression evaluation *
10097*7c568831SAndroid Build Coastguard Worker * *
10098*7c568831SAndroid Build Coastguard Worker ************************************************************************/
10099*7c568831SAndroid Build Coastguard Worker
10100*7c568831SAndroid Build Coastguard Worker static int
10101*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op);
10102*7c568831SAndroid Build Coastguard Worker
10103*7c568831SAndroid Build Coastguard Worker /**
10104*7c568831SAndroid Build Coastguard Worker * xmlXPathNodeSetFilter:
10105*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
10106*7c568831SAndroid Build Coastguard Worker * @set: the node set to filter
10107*7c568831SAndroid Build Coastguard Worker * @filterOpIndex: the index of the predicate/filter op
10108*7c568831SAndroid Build Coastguard Worker * @minPos: minimum position in the filtered set (1-based)
10109*7c568831SAndroid Build Coastguard Worker * @maxPos: maximum position in the filtered set (1-based)
10110*7c568831SAndroid Build Coastguard Worker * @hasNsNodes: true if the node set may contain namespace nodes
10111*7c568831SAndroid Build Coastguard Worker *
10112*7c568831SAndroid Build Coastguard Worker * Filter a node set, keeping only nodes for which the predicate expression
10113*7c568831SAndroid Build Coastguard Worker * matches. Afterwards, keep only nodes between minPos and maxPos in the
10114*7c568831SAndroid Build Coastguard Worker * filtered result.
10115*7c568831SAndroid Build Coastguard Worker */
10116*7c568831SAndroid Build Coastguard Worker static void
xmlXPathNodeSetFilter(xmlXPathParserContextPtr ctxt,xmlNodeSetPtr set,int filterOpIndex,int minPos,int maxPos,int hasNsNodes)10117*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetFilter(xmlXPathParserContextPtr ctxt,
10118*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr set,
10119*7c568831SAndroid Build Coastguard Worker int filterOpIndex,
10120*7c568831SAndroid Build Coastguard Worker int minPos, int maxPos,
10121*7c568831SAndroid Build Coastguard Worker int hasNsNodes)
10122*7c568831SAndroid Build Coastguard Worker {
10123*7c568831SAndroid Build Coastguard Worker xmlXPathContextPtr xpctxt;
10124*7c568831SAndroid Build Coastguard Worker xmlNodePtr oldnode;
10125*7c568831SAndroid Build Coastguard Worker xmlDocPtr olddoc;
10126*7c568831SAndroid Build Coastguard Worker xmlXPathStepOpPtr filterOp;
10127*7c568831SAndroid Build Coastguard Worker int oldcs, oldpp;
10128*7c568831SAndroid Build Coastguard Worker int i, j, pos;
10129*7c568831SAndroid Build Coastguard Worker
10130*7c568831SAndroid Build Coastguard Worker if ((set == NULL) || (set->nodeNr == 0))
10131*7c568831SAndroid Build Coastguard Worker return;
10132*7c568831SAndroid Build Coastguard Worker
10133*7c568831SAndroid Build Coastguard Worker /*
10134*7c568831SAndroid Build Coastguard Worker * Check if the node set contains a sufficient number of nodes for
10135*7c568831SAndroid Build Coastguard Worker * the requested range.
10136*7c568831SAndroid Build Coastguard Worker */
10137*7c568831SAndroid Build Coastguard Worker if (set->nodeNr < minPos) {
10138*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetClear(set, hasNsNodes);
10139*7c568831SAndroid Build Coastguard Worker return;
10140*7c568831SAndroid Build Coastguard Worker }
10141*7c568831SAndroid Build Coastguard Worker
10142*7c568831SAndroid Build Coastguard Worker xpctxt = ctxt->context;
10143*7c568831SAndroid Build Coastguard Worker oldnode = xpctxt->node;
10144*7c568831SAndroid Build Coastguard Worker olddoc = xpctxt->doc;
10145*7c568831SAndroid Build Coastguard Worker oldcs = xpctxt->contextSize;
10146*7c568831SAndroid Build Coastguard Worker oldpp = xpctxt->proximityPosition;
10147*7c568831SAndroid Build Coastguard Worker filterOp = &ctxt->comp->steps[filterOpIndex];
10148*7c568831SAndroid Build Coastguard Worker
10149*7c568831SAndroid Build Coastguard Worker xpctxt->contextSize = set->nodeNr;
10150*7c568831SAndroid Build Coastguard Worker
10151*7c568831SAndroid Build Coastguard Worker for (i = 0, j = 0, pos = 1; i < set->nodeNr; i++) {
10152*7c568831SAndroid Build Coastguard Worker xmlNodePtr node = set->nodeTab[i];
10153*7c568831SAndroid Build Coastguard Worker int res;
10154*7c568831SAndroid Build Coastguard Worker
10155*7c568831SAndroid Build Coastguard Worker xpctxt->node = node;
10156*7c568831SAndroid Build Coastguard Worker xpctxt->proximityPosition = i + 1;
10157*7c568831SAndroid Build Coastguard Worker
10158*7c568831SAndroid Build Coastguard Worker /*
10159*7c568831SAndroid Build Coastguard Worker * Also set the xpath document in case things like
10160*7c568831SAndroid Build Coastguard Worker * key() are evaluated in the predicate.
10161*7c568831SAndroid Build Coastguard Worker *
10162*7c568831SAndroid Build Coastguard Worker * TODO: Get real doc for namespace nodes.
10163*7c568831SAndroid Build Coastguard Worker */
10164*7c568831SAndroid Build Coastguard Worker if ((node->type != XML_NAMESPACE_DECL) &&
10165*7c568831SAndroid Build Coastguard Worker (node->doc != NULL))
10166*7c568831SAndroid Build Coastguard Worker xpctxt->doc = node->doc;
10167*7c568831SAndroid Build Coastguard Worker
10168*7c568831SAndroid Build Coastguard Worker res = xmlXPathCompOpEvalToBoolean(ctxt, filterOp, 1);
10169*7c568831SAndroid Build Coastguard Worker
10170*7c568831SAndroid Build Coastguard Worker if (ctxt->error != XPATH_EXPRESSION_OK)
10171*7c568831SAndroid Build Coastguard Worker break;
10172*7c568831SAndroid Build Coastguard Worker if (res < 0) {
10173*7c568831SAndroid Build Coastguard Worker /* Shouldn't happen */
10174*7c568831SAndroid Build Coastguard Worker xmlXPathErr(ctxt, XPATH_EXPR_ERROR);
10175*7c568831SAndroid Build Coastguard Worker break;
10176*7c568831SAndroid Build Coastguard Worker }
10177*7c568831SAndroid Build Coastguard Worker
10178*7c568831SAndroid Build Coastguard Worker if ((res != 0) && ((pos >= minPos) && (pos <= maxPos))) {
10179*7c568831SAndroid Build Coastguard Worker if (i != j) {
10180*7c568831SAndroid Build Coastguard Worker set->nodeTab[j] = node;
10181*7c568831SAndroid Build Coastguard Worker set->nodeTab[i] = NULL;
10182*7c568831SAndroid Build Coastguard Worker }
10183*7c568831SAndroid Build Coastguard Worker
10184*7c568831SAndroid Build Coastguard Worker j += 1;
10185*7c568831SAndroid Build Coastguard Worker } else {
10186*7c568831SAndroid Build Coastguard Worker /* Remove the entry from the initial node set. */
10187*7c568831SAndroid Build Coastguard Worker set->nodeTab[i] = NULL;
10188*7c568831SAndroid Build Coastguard Worker if (node->type == XML_NAMESPACE_DECL)
10189*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetFreeNs((xmlNsPtr) node);
10190*7c568831SAndroid Build Coastguard Worker }
10191*7c568831SAndroid Build Coastguard Worker
10192*7c568831SAndroid Build Coastguard Worker if (res != 0) {
10193*7c568831SAndroid Build Coastguard Worker if (pos == maxPos) {
10194*7c568831SAndroid Build Coastguard Worker i += 1;
10195*7c568831SAndroid Build Coastguard Worker break;
10196*7c568831SAndroid Build Coastguard Worker }
10197*7c568831SAndroid Build Coastguard Worker
10198*7c568831SAndroid Build Coastguard Worker pos += 1;
10199*7c568831SAndroid Build Coastguard Worker }
10200*7c568831SAndroid Build Coastguard Worker }
10201*7c568831SAndroid Build Coastguard Worker
10202*7c568831SAndroid Build Coastguard Worker /* Free remaining nodes. */
10203*7c568831SAndroid Build Coastguard Worker if (hasNsNodes) {
10204*7c568831SAndroid Build Coastguard Worker for (; i < set->nodeNr; i++) {
10205*7c568831SAndroid Build Coastguard Worker xmlNodePtr node = set->nodeTab[i];
10206*7c568831SAndroid Build Coastguard Worker if ((node != NULL) && (node->type == XML_NAMESPACE_DECL))
10207*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetFreeNs((xmlNsPtr) node);
10208*7c568831SAndroid Build Coastguard Worker }
10209*7c568831SAndroid Build Coastguard Worker }
10210*7c568831SAndroid Build Coastguard Worker
10211*7c568831SAndroid Build Coastguard Worker set->nodeNr = j;
10212*7c568831SAndroid Build Coastguard Worker
10213*7c568831SAndroid Build Coastguard Worker /* If too many elements were removed, shrink table to preserve memory. */
10214*7c568831SAndroid Build Coastguard Worker if ((set->nodeMax > XML_NODESET_DEFAULT) &&
10215*7c568831SAndroid Build Coastguard Worker (set->nodeNr < set->nodeMax / 2)) {
10216*7c568831SAndroid Build Coastguard Worker xmlNodePtr *tmp;
10217*7c568831SAndroid Build Coastguard Worker int nodeMax = set->nodeNr;
10218*7c568831SAndroid Build Coastguard Worker
10219*7c568831SAndroid Build Coastguard Worker if (nodeMax < XML_NODESET_DEFAULT)
10220*7c568831SAndroid Build Coastguard Worker nodeMax = XML_NODESET_DEFAULT;
10221*7c568831SAndroid Build Coastguard Worker tmp = (xmlNodePtr *) xmlRealloc(set->nodeTab,
10222*7c568831SAndroid Build Coastguard Worker nodeMax * sizeof(xmlNodePtr));
10223*7c568831SAndroid Build Coastguard Worker if (tmp == NULL) {
10224*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
10225*7c568831SAndroid Build Coastguard Worker } else {
10226*7c568831SAndroid Build Coastguard Worker set->nodeTab = tmp;
10227*7c568831SAndroid Build Coastguard Worker set->nodeMax = nodeMax;
10228*7c568831SAndroid Build Coastguard Worker }
10229*7c568831SAndroid Build Coastguard Worker }
10230*7c568831SAndroid Build Coastguard Worker
10231*7c568831SAndroid Build Coastguard Worker xpctxt->node = oldnode;
10232*7c568831SAndroid Build Coastguard Worker xpctxt->doc = olddoc;
10233*7c568831SAndroid Build Coastguard Worker xpctxt->contextSize = oldcs;
10234*7c568831SAndroid Build Coastguard Worker xpctxt->proximityPosition = oldpp;
10235*7c568831SAndroid Build Coastguard Worker }
10236*7c568831SAndroid Build Coastguard Worker
10237*7c568831SAndroid Build Coastguard Worker /**
10238*7c568831SAndroid Build Coastguard Worker * xmlXPathCompOpEvalPredicate:
10239*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
10240*7c568831SAndroid Build Coastguard Worker * @op: the predicate op
10241*7c568831SAndroid Build Coastguard Worker * @set: the node set to filter
10242*7c568831SAndroid Build Coastguard Worker * @minPos: minimum position in the filtered set (1-based)
10243*7c568831SAndroid Build Coastguard Worker * @maxPos: maximum position in the filtered set (1-based)
10244*7c568831SAndroid Build Coastguard Worker * @hasNsNodes: true if the node set may contain namespace nodes
10245*7c568831SAndroid Build Coastguard Worker *
10246*7c568831SAndroid Build Coastguard Worker * Filter a node set, keeping only nodes for which the sequence of predicate
10247*7c568831SAndroid Build Coastguard Worker * expressions matches. Afterwards, keep only nodes between minPos and maxPos
10248*7c568831SAndroid Build Coastguard Worker * in the filtered result.
10249*7c568831SAndroid Build Coastguard Worker */
10250*7c568831SAndroid Build Coastguard Worker static void
xmlXPathCompOpEvalPredicate(xmlXPathParserContextPtr ctxt,xmlXPathStepOpPtr op,xmlNodeSetPtr set,int minPos,int maxPos,int hasNsNodes)10251*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalPredicate(xmlXPathParserContextPtr ctxt,
10252*7c568831SAndroid Build Coastguard Worker xmlXPathStepOpPtr op,
10253*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr set,
10254*7c568831SAndroid Build Coastguard Worker int minPos, int maxPos,
10255*7c568831SAndroid Build Coastguard Worker int hasNsNodes)
10256*7c568831SAndroid Build Coastguard Worker {
10257*7c568831SAndroid Build Coastguard Worker if (op->ch1 != -1) {
10258*7c568831SAndroid Build Coastguard Worker xmlXPathCompExprPtr comp = ctxt->comp;
10259*7c568831SAndroid Build Coastguard Worker /*
10260*7c568831SAndroid Build Coastguard Worker * Process inner predicates first.
10261*7c568831SAndroid Build Coastguard Worker */
10262*7c568831SAndroid Build Coastguard Worker if (comp->steps[op->ch1].op != XPATH_OP_PREDICATE) {
10263*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_OPERAND);
10264*7c568831SAndroid Build Coastguard Worker }
10265*7c568831SAndroid Build Coastguard Worker if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH)
10266*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_RECURSION_LIMIT_EXCEEDED);
10267*7c568831SAndroid Build Coastguard Worker ctxt->context->depth += 1;
10268*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalPredicate(ctxt, &comp->steps[op->ch1], set,
10269*7c568831SAndroid Build Coastguard Worker 1, set->nodeNr, hasNsNodes);
10270*7c568831SAndroid Build Coastguard Worker ctxt->context->depth -= 1;
10271*7c568831SAndroid Build Coastguard Worker CHECK_ERROR;
10272*7c568831SAndroid Build Coastguard Worker }
10273*7c568831SAndroid Build Coastguard Worker
10274*7c568831SAndroid Build Coastguard Worker if (op->ch2 != -1)
10275*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetFilter(ctxt, set, op->ch2, minPos, maxPos, hasNsNodes);
10276*7c568831SAndroid Build Coastguard Worker }
10277*7c568831SAndroid Build Coastguard Worker
10278*7c568831SAndroid Build Coastguard Worker static int
xmlXPathIsPositionalPredicate(xmlXPathParserContextPtr ctxt,xmlXPathStepOpPtr op,int * maxPos)10279*7c568831SAndroid Build Coastguard Worker xmlXPathIsPositionalPredicate(xmlXPathParserContextPtr ctxt,
10280*7c568831SAndroid Build Coastguard Worker xmlXPathStepOpPtr op,
10281*7c568831SAndroid Build Coastguard Worker int *maxPos)
10282*7c568831SAndroid Build Coastguard Worker {
10283*7c568831SAndroid Build Coastguard Worker
10284*7c568831SAndroid Build Coastguard Worker xmlXPathStepOpPtr exprOp;
10285*7c568831SAndroid Build Coastguard Worker
10286*7c568831SAndroid Build Coastguard Worker /*
10287*7c568831SAndroid Build Coastguard Worker * BIG NOTE: This is not intended for XPATH_OP_FILTER yet!
10288*7c568831SAndroid Build Coastguard Worker */
10289*7c568831SAndroid Build Coastguard Worker
10290*7c568831SAndroid Build Coastguard Worker /*
10291*7c568831SAndroid Build Coastguard Worker * If not -1, then ch1 will point to:
10292*7c568831SAndroid Build Coastguard Worker * 1) For predicates (XPATH_OP_PREDICATE):
10293*7c568831SAndroid Build Coastguard Worker * - an inner predicate operator
10294*7c568831SAndroid Build Coastguard Worker * 2) For filters (XPATH_OP_FILTER):
10295*7c568831SAndroid Build Coastguard Worker * - an inner filter operator OR
10296*7c568831SAndroid Build Coastguard Worker * - an expression selecting the node set.
10297*7c568831SAndroid Build Coastguard Worker * E.g. "key('a', 'b')" or "(//foo | //bar)".
10298*7c568831SAndroid Build Coastguard Worker */
10299*7c568831SAndroid Build Coastguard Worker if ((op->op != XPATH_OP_PREDICATE) && (op->op != XPATH_OP_FILTER))
10300*7c568831SAndroid Build Coastguard Worker return(0);
10301*7c568831SAndroid Build Coastguard Worker
10302*7c568831SAndroid Build Coastguard Worker if (op->ch2 != -1) {
10303*7c568831SAndroid Build Coastguard Worker exprOp = &ctxt->comp->steps[op->ch2];
10304*7c568831SAndroid Build Coastguard Worker } else
10305*7c568831SAndroid Build Coastguard Worker return(0);
10306*7c568831SAndroid Build Coastguard Worker
10307*7c568831SAndroid Build Coastguard Worker if ((exprOp != NULL) &&
10308*7c568831SAndroid Build Coastguard Worker (exprOp->op == XPATH_OP_VALUE) &&
10309*7c568831SAndroid Build Coastguard Worker (exprOp->value4 != NULL) &&
10310*7c568831SAndroid Build Coastguard Worker (((xmlXPathObjectPtr) exprOp->value4)->type == XPATH_NUMBER))
10311*7c568831SAndroid Build Coastguard Worker {
10312*7c568831SAndroid Build Coastguard Worker double floatval = ((xmlXPathObjectPtr) exprOp->value4)->floatval;
10313*7c568831SAndroid Build Coastguard Worker
10314*7c568831SAndroid Build Coastguard Worker /*
10315*7c568831SAndroid Build Coastguard Worker * We have a "[n]" predicate here.
10316*7c568831SAndroid Build Coastguard Worker * TODO: Unfortunately this simplistic test here is not
10317*7c568831SAndroid Build Coastguard Worker * able to detect a position() predicate in compound
10318*7c568831SAndroid Build Coastguard Worker * expressions like "[@attr = 'a" and position() = 1],
10319*7c568831SAndroid Build Coastguard Worker * and even not the usage of position() in
10320*7c568831SAndroid Build Coastguard Worker * "[position() = 1]"; thus - obviously - a position-range,
10321*7c568831SAndroid Build Coastguard Worker * like it "[position() < 5]", is also not detected.
10322*7c568831SAndroid Build Coastguard Worker * Maybe we could rewrite the AST to ease the optimization.
10323*7c568831SAndroid Build Coastguard Worker */
10324*7c568831SAndroid Build Coastguard Worker
10325*7c568831SAndroid Build Coastguard Worker if ((floatval > INT_MIN) && (floatval < INT_MAX)) {
10326*7c568831SAndroid Build Coastguard Worker *maxPos = (int) floatval;
10327*7c568831SAndroid Build Coastguard Worker if (floatval == (double) *maxPos)
10328*7c568831SAndroid Build Coastguard Worker return(1);
10329*7c568831SAndroid Build Coastguard Worker }
10330*7c568831SAndroid Build Coastguard Worker }
10331*7c568831SAndroid Build Coastguard Worker return(0);
10332*7c568831SAndroid Build Coastguard Worker }
10333*7c568831SAndroid Build Coastguard Worker
10334*7c568831SAndroid Build Coastguard Worker static int
xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,xmlXPathStepOpPtr op,xmlNodePtr * first,xmlNodePtr * last,int toBool)10335*7c568831SAndroid Build Coastguard Worker xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
10336*7c568831SAndroid Build Coastguard Worker xmlXPathStepOpPtr op,
10337*7c568831SAndroid Build Coastguard Worker xmlNodePtr * first, xmlNodePtr * last,
10338*7c568831SAndroid Build Coastguard Worker int toBool)
10339*7c568831SAndroid Build Coastguard Worker {
10340*7c568831SAndroid Build Coastguard Worker
10341*7c568831SAndroid Build Coastguard Worker #define XP_TEST_HIT \
10342*7c568831SAndroid Build Coastguard Worker if (hasAxisRange != 0) { \
10343*7c568831SAndroid Build Coastguard Worker if (++pos == maxPos) { \
10344*7c568831SAndroid Build Coastguard Worker if (addNode(seq, cur) < 0) \
10345*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt); \
10346*7c568831SAndroid Build Coastguard Worker goto axis_range_end; } \
10347*7c568831SAndroid Build Coastguard Worker } else { \
10348*7c568831SAndroid Build Coastguard Worker if (addNode(seq, cur) < 0) \
10349*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt); \
10350*7c568831SAndroid Build Coastguard Worker if (breakOnFirstHit) goto first_hit; }
10351*7c568831SAndroid Build Coastguard Worker
10352*7c568831SAndroid Build Coastguard Worker #define XP_TEST_HIT_NS \
10353*7c568831SAndroid Build Coastguard Worker if (hasAxisRange != 0) { \
10354*7c568831SAndroid Build Coastguard Worker if (++pos == maxPos) { \
10355*7c568831SAndroid Build Coastguard Worker hasNsNodes = 1; \
10356*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur) < 0) \
10357*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt); \
10358*7c568831SAndroid Build Coastguard Worker goto axis_range_end; } \
10359*7c568831SAndroid Build Coastguard Worker } else { \
10360*7c568831SAndroid Build Coastguard Worker hasNsNodes = 1; \
10361*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur) < 0) \
10362*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt); \
10363*7c568831SAndroid Build Coastguard Worker if (breakOnFirstHit) goto first_hit; }
10364*7c568831SAndroid Build Coastguard Worker
10365*7c568831SAndroid Build Coastguard Worker xmlXPathAxisVal axis = (xmlXPathAxisVal) op->value;
10366*7c568831SAndroid Build Coastguard Worker xmlXPathTestVal test = (xmlXPathTestVal) op->value2;
10367*7c568831SAndroid Build Coastguard Worker xmlXPathTypeVal type = (xmlXPathTypeVal) op->value3;
10368*7c568831SAndroid Build Coastguard Worker const xmlChar *prefix = op->value4;
10369*7c568831SAndroid Build Coastguard Worker const xmlChar *name = op->value5;
10370*7c568831SAndroid Build Coastguard Worker const xmlChar *URI = NULL;
10371*7c568831SAndroid Build Coastguard Worker
10372*7c568831SAndroid Build Coastguard Worker int total = 0, hasNsNodes = 0;
10373*7c568831SAndroid Build Coastguard Worker /* The popped object holding the context nodes */
10374*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr obj;
10375*7c568831SAndroid Build Coastguard Worker /* The set of context nodes for the node tests */
10376*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr contextSeq;
10377*7c568831SAndroid Build Coastguard Worker int contextIdx;
10378*7c568831SAndroid Build Coastguard Worker xmlNodePtr contextNode;
10379*7c568831SAndroid Build Coastguard Worker /* The final resulting node set wrt to all context nodes */
10380*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr outSeq;
10381*7c568831SAndroid Build Coastguard Worker /*
10382*7c568831SAndroid Build Coastguard Worker * The temporary resulting node set wrt 1 context node.
10383*7c568831SAndroid Build Coastguard Worker * Used to feed predicate evaluation.
10384*7c568831SAndroid Build Coastguard Worker */
10385*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr seq;
10386*7c568831SAndroid Build Coastguard Worker xmlNodePtr cur;
10387*7c568831SAndroid Build Coastguard Worker /* First predicate operator */
10388*7c568831SAndroid Build Coastguard Worker xmlXPathStepOpPtr predOp;
10389*7c568831SAndroid Build Coastguard Worker int maxPos; /* The requested position() (when a "[n]" predicate) */
10390*7c568831SAndroid Build Coastguard Worker int hasPredicateRange, hasAxisRange, pos;
10391*7c568831SAndroid Build Coastguard Worker int breakOnFirstHit;
10392*7c568831SAndroid Build Coastguard Worker
10393*7c568831SAndroid Build Coastguard Worker xmlXPathTraversalFunction next = NULL;
10394*7c568831SAndroid Build Coastguard Worker int (*addNode) (xmlNodeSetPtr, xmlNodePtr);
10395*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetMergeFunction mergeAndClear;
10396*7c568831SAndroid Build Coastguard Worker xmlNodePtr oldContextNode;
10397*7c568831SAndroid Build Coastguard Worker xmlXPathContextPtr xpctxt = ctxt->context;
10398*7c568831SAndroid Build Coastguard Worker
10399*7c568831SAndroid Build Coastguard Worker
10400*7c568831SAndroid Build Coastguard Worker CHECK_TYPE0(XPATH_NODESET);
10401*7c568831SAndroid Build Coastguard Worker obj = valuePop(ctxt);
10402*7c568831SAndroid Build Coastguard Worker /*
10403*7c568831SAndroid Build Coastguard Worker * Setup namespaces.
10404*7c568831SAndroid Build Coastguard Worker */
10405*7c568831SAndroid Build Coastguard Worker if (prefix != NULL) {
10406*7c568831SAndroid Build Coastguard Worker URI = xmlXPathNsLookup(xpctxt, prefix);
10407*7c568831SAndroid Build Coastguard Worker if (URI == NULL) {
10408*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(xpctxt, obj);
10409*7c568831SAndroid Build Coastguard Worker XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
10410*7c568831SAndroid Build Coastguard Worker }
10411*7c568831SAndroid Build Coastguard Worker }
10412*7c568831SAndroid Build Coastguard Worker /*
10413*7c568831SAndroid Build Coastguard Worker * Setup axis.
10414*7c568831SAndroid Build Coastguard Worker *
10415*7c568831SAndroid Build Coastguard Worker * MAYBE FUTURE TODO: merging optimizations:
10416*7c568831SAndroid Build Coastguard Worker * - If the nodes to be traversed wrt to the initial nodes and
10417*7c568831SAndroid Build Coastguard Worker * the current axis cannot overlap, then we could avoid searching
10418*7c568831SAndroid Build Coastguard Worker * for duplicates during the merge.
10419*7c568831SAndroid Build Coastguard Worker * But the question is how/when to evaluate if they cannot overlap.
10420*7c568831SAndroid Build Coastguard Worker * Example: if we know that for two initial nodes, the one is
10421*7c568831SAndroid Build Coastguard Worker * not in the ancestor-or-self axis of the other, then we could safely
10422*7c568831SAndroid Build Coastguard Worker * avoid a duplicate-aware merge, if the axis to be traversed is e.g.
10423*7c568831SAndroid Build Coastguard Worker * the descendant-or-self axis.
10424*7c568831SAndroid Build Coastguard Worker */
10425*7c568831SAndroid Build Coastguard Worker mergeAndClear = xmlXPathNodeSetMergeAndClear;
10426*7c568831SAndroid Build Coastguard Worker switch (axis) {
10427*7c568831SAndroid Build Coastguard Worker case AXIS_ANCESTOR:
10428*7c568831SAndroid Build Coastguard Worker first = NULL;
10429*7c568831SAndroid Build Coastguard Worker next = xmlXPathNextAncestor;
10430*7c568831SAndroid Build Coastguard Worker break;
10431*7c568831SAndroid Build Coastguard Worker case AXIS_ANCESTOR_OR_SELF:
10432*7c568831SAndroid Build Coastguard Worker first = NULL;
10433*7c568831SAndroid Build Coastguard Worker next = xmlXPathNextAncestorOrSelf;
10434*7c568831SAndroid Build Coastguard Worker break;
10435*7c568831SAndroid Build Coastguard Worker case AXIS_ATTRIBUTE:
10436*7c568831SAndroid Build Coastguard Worker first = NULL;
10437*7c568831SAndroid Build Coastguard Worker last = NULL;
10438*7c568831SAndroid Build Coastguard Worker next = xmlXPathNextAttribute;
10439*7c568831SAndroid Build Coastguard Worker mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls;
10440*7c568831SAndroid Build Coastguard Worker break;
10441*7c568831SAndroid Build Coastguard Worker case AXIS_CHILD:
10442*7c568831SAndroid Build Coastguard Worker last = NULL;
10443*7c568831SAndroid Build Coastguard Worker if (((test == NODE_TEST_NAME) || (test == NODE_TEST_ALL)) &&
10444*7c568831SAndroid Build Coastguard Worker (type == NODE_TYPE_NODE))
10445*7c568831SAndroid Build Coastguard Worker {
10446*7c568831SAndroid Build Coastguard Worker /*
10447*7c568831SAndroid Build Coastguard Worker * Optimization if an element node type is 'element'.
10448*7c568831SAndroid Build Coastguard Worker */
10449*7c568831SAndroid Build Coastguard Worker next = xmlXPathNextChildElement;
10450*7c568831SAndroid Build Coastguard Worker } else
10451*7c568831SAndroid Build Coastguard Worker next = xmlXPathNextChild;
10452*7c568831SAndroid Build Coastguard Worker mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls;
10453*7c568831SAndroid Build Coastguard Worker break;
10454*7c568831SAndroid Build Coastguard Worker case AXIS_DESCENDANT:
10455*7c568831SAndroid Build Coastguard Worker last = NULL;
10456*7c568831SAndroid Build Coastguard Worker next = xmlXPathNextDescendant;
10457*7c568831SAndroid Build Coastguard Worker break;
10458*7c568831SAndroid Build Coastguard Worker case AXIS_DESCENDANT_OR_SELF:
10459*7c568831SAndroid Build Coastguard Worker last = NULL;
10460*7c568831SAndroid Build Coastguard Worker next = xmlXPathNextDescendantOrSelf;
10461*7c568831SAndroid Build Coastguard Worker break;
10462*7c568831SAndroid Build Coastguard Worker case AXIS_FOLLOWING:
10463*7c568831SAndroid Build Coastguard Worker last = NULL;
10464*7c568831SAndroid Build Coastguard Worker next = xmlXPathNextFollowing;
10465*7c568831SAndroid Build Coastguard Worker break;
10466*7c568831SAndroid Build Coastguard Worker case AXIS_FOLLOWING_SIBLING:
10467*7c568831SAndroid Build Coastguard Worker last = NULL;
10468*7c568831SAndroid Build Coastguard Worker next = xmlXPathNextFollowingSibling;
10469*7c568831SAndroid Build Coastguard Worker break;
10470*7c568831SAndroid Build Coastguard Worker case AXIS_NAMESPACE:
10471*7c568831SAndroid Build Coastguard Worker first = NULL;
10472*7c568831SAndroid Build Coastguard Worker last = NULL;
10473*7c568831SAndroid Build Coastguard Worker next = (xmlXPathTraversalFunction) xmlXPathNextNamespace;
10474*7c568831SAndroid Build Coastguard Worker mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls;
10475*7c568831SAndroid Build Coastguard Worker break;
10476*7c568831SAndroid Build Coastguard Worker case AXIS_PARENT:
10477*7c568831SAndroid Build Coastguard Worker first = NULL;
10478*7c568831SAndroid Build Coastguard Worker next = xmlXPathNextParent;
10479*7c568831SAndroid Build Coastguard Worker break;
10480*7c568831SAndroid Build Coastguard Worker case AXIS_PRECEDING:
10481*7c568831SAndroid Build Coastguard Worker first = NULL;
10482*7c568831SAndroid Build Coastguard Worker next = xmlXPathNextPrecedingInternal;
10483*7c568831SAndroid Build Coastguard Worker break;
10484*7c568831SAndroid Build Coastguard Worker case AXIS_PRECEDING_SIBLING:
10485*7c568831SAndroid Build Coastguard Worker first = NULL;
10486*7c568831SAndroid Build Coastguard Worker next = xmlXPathNextPrecedingSibling;
10487*7c568831SAndroid Build Coastguard Worker break;
10488*7c568831SAndroid Build Coastguard Worker case AXIS_SELF:
10489*7c568831SAndroid Build Coastguard Worker first = NULL;
10490*7c568831SAndroid Build Coastguard Worker last = NULL;
10491*7c568831SAndroid Build Coastguard Worker next = xmlXPathNextSelf;
10492*7c568831SAndroid Build Coastguard Worker mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls;
10493*7c568831SAndroid Build Coastguard Worker break;
10494*7c568831SAndroid Build Coastguard Worker }
10495*7c568831SAndroid Build Coastguard Worker
10496*7c568831SAndroid Build Coastguard Worker if (next == NULL) {
10497*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(xpctxt, obj);
10498*7c568831SAndroid Build Coastguard Worker return(0);
10499*7c568831SAndroid Build Coastguard Worker }
10500*7c568831SAndroid Build Coastguard Worker contextSeq = obj->nodesetval;
10501*7c568831SAndroid Build Coastguard Worker if ((contextSeq == NULL) || (contextSeq->nodeNr <= 0)) {
10502*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, obj);
10503*7c568831SAndroid Build Coastguard Worker return(0);
10504*7c568831SAndroid Build Coastguard Worker }
10505*7c568831SAndroid Build Coastguard Worker /*
10506*7c568831SAndroid Build Coastguard Worker * Predicate optimization ---------------------------------------------
10507*7c568831SAndroid Build Coastguard Worker * If this step has a last predicate, which contains a position(),
10508*7c568831SAndroid Build Coastguard Worker * then we'll optimize (although not exactly "position()", but only
10509*7c568831SAndroid Build Coastguard Worker * the short-hand form, i.e., "[n]".
10510*7c568831SAndroid Build Coastguard Worker *
10511*7c568831SAndroid Build Coastguard Worker * Example - expression "/foo[parent::bar][1]":
10512*7c568831SAndroid Build Coastguard Worker *
10513*7c568831SAndroid Build Coastguard Worker * COLLECT 'child' 'name' 'node' foo -- op (we are here)
10514*7c568831SAndroid Build Coastguard Worker * ROOT -- op->ch1
10515*7c568831SAndroid Build Coastguard Worker * PREDICATE -- op->ch2 (predOp)
10516*7c568831SAndroid Build Coastguard Worker * PREDICATE -- predOp->ch1 = [parent::bar]
10517*7c568831SAndroid Build Coastguard Worker * SORT
10518*7c568831SAndroid Build Coastguard Worker * COLLECT 'parent' 'name' 'node' bar
10519*7c568831SAndroid Build Coastguard Worker * NODE
10520*7c568831SAndroid Build Coastguard Worker * ELEM Object is a number : 1 -- predOp->ch2 = [1]
10521*7c568831SAndroid Build Coastguard Worker *
10522*7c568831SAndroid Build Coastguard Worker */
10523*7c568831SAndroid Build Coastguard Worker maxPos = 0;
10524*7c568831SAndroid Build Coastguard Worker predOp = NULL;
10525*7c568831SAndroid Build Coastguard Worker hasPredicateRange = 0;
10526*7c568831SAndroid Build Coastguard Worker hasAxisRange = 0;
10527*7c568831SAndroid Build Coastguard Worker if (op->ch2 != -1) {
10528*7c568831SAndroid Build Coastguard Worker /*
10529*7c568831SAndroid Build Coastguard Worker * There's at least one predicate. 16 == XPATH_OP_PREDICATE
10530*7c568831SAndroid Build Coastguard Worker */
10531*7c568831SAndroid Build Coastguard Worker predOp = &ctxt->comp->steps[op->ch2];
10532*7c568831SAndroid Build Coastguard Worker if (xmlXPathIsPositionalPredicate(ctxt, predOp, &maxPos)) {
10533*7c568831SAndroid Build Coastguard Worker if (predOp->ch1 != -1) {
10534*7c568831SAndroid Build Coastguard Worker /*
10535*7c568831SAndroid Build Coastguard Worker * Use the next inner predicate operator.
10536*7c568831SAndroid Build Coastguard Worker */
10537*7c568831SAndroid Build Coastguard Worker predOp = &ctxt->comp->steps[predOp->ch1];
10538*7c568831SAndroid Build Coastguard Worker hasPredicateRange = 1;
10539*7c568831SAndroid Build Coastguard Worker } else {
10540*7c568831SAndroid Build Coastguard Worker /*
10541*7c568831SAndroid Build Coastguard Worker * There's no other predicate than the [n] predicate.
10542*7c568831SAndroid Build Coastguard Worker */
10543*7c568831SAndroid Build Coastguard Worker predOp = NULL;
10544*7c568831SAndroid Build Coastguard Worker hasAxisRange = 1;
10545*7c568831SAndroid Build Coastguard Worker }
10546*7c568831SAndroid Build Coastguard Worker }
10547*7c568831SAndroid Build Coastguard Worker }
10548*7c568831SAndroid Build Coastguard Worker breakOnFirstHit = ((toBool) && (predOp == NULL)) ? 1 : 0;
10549*7c568831SAndroid Build Coastguard Worker /*
10550*7c568831SAndroid Build Coastguard Worker * Axis traversal -----------------------------------------------------
10551*7c568831SAndroid Build Coastguard Worker */
10552*7c568831SAndroid Build Coastguard Worker /*
10553*7c568831SAndroid Build Coastguard Worker * 2.3 Node Tests
10554*7c568831SAndroid Build Coastguard Worker * - For the attribute axis, the principal node type is attribute.
10555*7c568831SAndroid Build Coastguard Worker * - For the namespace axis, the principal node type is namespace.
10556*7c568831SAndroid Build Coastguard Worker * - For other axes, the principal node type is element.
10557*7c568831SAndroid Build Coastguard Worker *
10558*7c568831SAndroid Build Coastguard Worker * A node test * is true for any node of the
10559*7c568831SAndroid Build Coastguard Worker * principal node type. For example, child::* will
10560*7c568831SAndroid Build Coastguard Worker * select all element children of the context node
10561*7c568831SAndroid Build Coastguard Worker */
10562*7c568831SAndroid Build Coastguard Worker oldContextNode = xpctxt->node;
10563*7c568831SAndroid Build Coastguard Worker addNode = xmlXPathNodeSetAddUnique;
10564*7c568831SAndroid Build Coastguard Worker outSeq = NULL;
10565*7c568831SAndroid Build Coastguard Worker seq = NULL;
10566*7c568831SAndroid Build Coastguard Worker contextNode = NULL;
10567*7c568831SAndroid Build Coastguard Worker contextIdx = 0;
10568*7c568831SAndroid Build Coastguard Worker
10569*7c568831SAndroid Build Coastguard Worker
10570*7c568831SAndroid Build Coastguard Worker while (((contextIdx < contextSeq->nodeNr) || (contextNode != NULL)) &&
10571*7c568831SAndroid Build Coastguard Worker (ctxt->error == XPATH_EXPRESSION_OK)) {
10572*7c568831SAndroid Build Coastguard Worker xpctxt->node = contextSeq->nodeTab[contextIdx++];
10573*7c568831SAndroid Build Coastguard Worker
10574*7c568831SAndroid Build Coastguard Worker if (seq == NULL) {
10575*7c568831SAndroid Build Coastguard Worker seq = xmlXPathNodeSetCreate(NULL);
10576*7c568831SAndroid Build Coastguard Worker if (seq == NULL) {
10577*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
10578*7c568831SAndroid Build Coastguard Worker total = 0;
10579*7c568831SAndroid Build Coastguard Worker goto error;
10580*7c568831SAndroid Build Coastguard Worker }
10581*7c568831SAndroid Build Coastguard Worker }
10582*7c568831SAndroid Build Coastguard Worker /*
10583*7c568831SAndroid Build Coastguard Worker * Traverse the axis and test the nodes.
10584*7c568831SAndroid Build Coastguard Worker */
10585*7c568831SAndroid Build Coastguard Worker pos = 0;
10586*7c568831SAndroid Build Coastguard Worker cur = NULL;
10587*7c568831SAndroid Build Coastguard Worker hasNsNodes = 0;
10588*7c568831SAndroid Build Coastguard Worker do {
10589*7c568831SAndroid Build Coastguard Worker if (OP_LIMIT_EXCEEDED(ctxt, 1))
10590*7c568831SAndroid Build Coastguard Worker goto error;
10591*7c568831SAndroid Build Coastguard Worker
10592*7c568831SAndroid Build Coastguard Worker cur = next(ctxt, cur);
10593*7c568831SAndroid Build Coastguard Worker if (cur == NULL)
10594*7c568831SAndroid Build Coastguard Worker break;
10595*7c568831SAndroid Build Coastguard Worker
10596*7c568831SAndroid Build Coastguard Worker /*
10597*7c568831SAndroid Build Coastguard Worker * QUESTION TODO: What does the "first" and "last" stuff do?
10598*7c568831SAndroid Build Coastguard Worker */
10599*7c568831SAndroid Build Coastguard Worker if ((first != NULL) && (*first != NULL)) {
10600*7c568831SAndroid Build Coastguard Worker if (*first == cur)
10601*7c568831SAndroid Build Coastguard Worker break;
10602*7c568831SAndroid Build Coastguard Worker if (((total % 256) == 0) &&
10603*7c568831SAndroid Build Coastguard Worker #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
10604*7c568831SAndroid Build Coastguard Worker (xmlXPathCmpNodesExt(*first, cur) >= 0))
10605*7c568831SAndroid Build Coastguard Worker #else
10606*7c568831SAndroid Build Coastguard Worker (xmlXPathCmpNodes(*first, cur) >= 0))
10607*7c568831SAndroid Build Coastguard Worker #endif
10608*7c568831SAndroid Build Coastguard Worker {
10609*7c568831SAndroid Build Coastguard Worker break;
10610*7c568831SAndroid Build Coastguard Worker }
10611*7c568831SAndroid Build Coastguard Worker }
10612*7c568831SAndroid Build Coastguard Worker if ((last != NULL) && (*last != NULL)) {
10613*7c568831SAndroid Build Coastguard Worker if (*last == cur)
10614*7c568831SAndroid Build Coastguard Worker break;
10615*7c568831SAndroid Build Coastguard Worker if (((total % 256) == 0) &&
10616*7c568831SAndroid Build Coastguard Worker #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
10617*7c568831SAndroid Build Coastguard Worker (xmlXPathCmpNodesExt(cur, *last) >= 0))
10618*7c568831SAndroid Build Coastguard Worker #else
10619*7c568831SAndroid Build Coastguard Worker (xmlXPathCmpNodes(cur, *last) >= 0))
10620*7c568831SAndroid Build Coastguard Worker #endif
10621*7c568831SAndroid Build Coastguard Worker {
10622*7c568831SAndroid Build Coastguard Worker break;
10623*7c568831SAndroid Build Coastguard Worker }
10624*7c568831SAndroid Build Coastguard Worker }
10625*7c568831SAndroid Build Coastguard Worker
10626*7c568831SAndroid Build Coastguard Worker total++;
10627*7c568831SAndroid Build Coastguard Worker
10628*7c568831SAndroid Build Coastguard Worker switch (test) {
10629*7c568831SAndroid Build Coastguard Worker case NODE_TEST_NONE:
10630*7c568831SAndroid Build Coastguard Worker total = 0;
10631*7c568831SAndroid Build Coastguard Worker goto error;
10632*7c568831SAndroid Build Coastguard Worker case NODE_TEST_TYPE:
10633*7c568831SAndroid Build Coastguard Worker if (type == NODE_TYPE_NODE) {
10634*7c568831SAndroid Build Coastguard Worker switch (cur->type) {
10635*7c568831SAndroid Build Coastguard Worker case XML_DOCUMENT_NODE:
10636*7c568831SAndroid Build Coastguard Worker case XML_HTML_DOCUMENT_NODE:
10637*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
10638*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE:
10639*7c568831SAndroid Build Coastguard Worker case XML_PI_NODE:
10640*7c568831SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
10641*7c568831SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
10642*7c568831SAndroid Build Coastguard Worker case XML_TEXT_NODE:
10643*7c568831SAndroid Build Coastguard Worker XP_TEST_HIT
10644*7c568831SAndroid Build Coastguard Worker break;
10645*7c568831SAndroid Build Coastguard Worker case XML_NAMESPACE_DECL: {
10646*7c568831SAndroid Build Coastguard Worker if (axis == AXIS_NAMESPACE) {
10647*7c568831SAndroid Build Coastguard Worker XP_TEST_HIT_NS
10648*7c568831SAndroid Build Coastguard Worker } else {
10649*7c568831SAndroid Build Coastguard Worker hasNsNodes = 1;
10650*7c568831SAndroid Build Coastguard Worker XP_TEST_HIT
10651*7c568831SAndroid Build Coastguard Worker }
10652*7c568831SAndroid Build Coastguard Worker break;
10653*7c568831SAndroid Build Coastguard Worker }
10654*7c568831SAndroid Build Coastguard Worker default:
10655*7c568831SAndroid Build Coastguard Worker break;
10656*7c568831SAndroid Build Coastguard Worker }
10657*7c568831SAndroid Build Coastguard Worker } else if (cur->type == (xmlElementType) type) {
10658*7c568831SAndroid Build Coastguard Worker if (cur->type == XML_NAMESPACE_DECL)
10659*7c568831SAndroid Build Coastguard Worker XP_TEST_HIT_NS
10660*7c568831SAndroid Build Coastguard Worker else
10661*7c568831SAndroid Build Coastguard Worker XP_TEST_HIT
10662*7c568831SAndroid Build Coastguard Worker } else if ((type == NODE_TYPE_TEXT) &&
10663*7c568831SAndroid Build Coastguard Worker (cur->type == XML_CDATA_SECTION_NODE))
10664*7c568831SAndroid Build Coastguard Worker {
10665*7c568831SAndroid Build Coastguard Worker XP_TEST_HIT
10666*7c568831SAndroid Build Coastguard Worker }
10667*7c568831SAndroid Build Coastguard Worker break;
10668*7c568831SAndroid Build Coastguard Worker case NODE_TEST_PI:
10669*7c568831SAndroid Build Coastguard Worker if ((cur->type == XML_PI_NODE) &&
10670*7c568831SAndroid Build Coastguard Worker ((name == NULL) || xmlStrEqual(name, cur->name)))
10671*7c568831SAndroid Build Coastguard Worker {
10672*7c568831SAndroid Build Coastguard Worker XP_TEST_HIT
10673*7c568831SAndroid Build Coastguard Worker }
10674*7c568831SAndroid Build Coastguard Worker break;
10675*7c568831SAndroid Build Coastguard Worker case NODE_TEST_ALL:
10676*7c568831SAndroid Build Coastguard Worker if (axis == AXIS_ATTRIBUTE) {
10677*7c568831SAndroid Build Coastguard Worker if (cur->type == XML_ATTRIBUTE_NODE)
10678*7c568831SAndroid Build Coastguard Worker {
10679*7c568831SAndroid Build Coastguard Worker if (prefix == NULL)
10680*7c568831SAndroid Build Coastguard Worker {
10681*7c568831SAndroid Build Coastguard Worker XP_TEST_HIT
10682*7c568831SAndroid Build Coastguard Worker } else if ((cur->ns != NULL) &&
10683*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(URI, cur->ns->href)))
10684*7c568831SAndroid Build Coastguard Worker {
10685*7c568831SAndroid Build Coastguard Worker XP_TEST_HIT
10686*7c568831SAndroid Build Coastguard Worker }
10687*7c568831SAndroid Build Coastguard Worker }
10688*7c568831SAndroid Build Coastguard Worker } else if (axis == AXIS_NAMESPACE) {
10689*7c568831SAndroid Build Coastguard Worker if (cur->type == XML_NAMESPACE_DECL)
10690*7c568831SAndroid Build Coastguard Worker {
10691*7c568831SAndroid Build Coastguard Worker XP_TEST_HIT_NS
10692*7c568831SAndroid Build Coastguard Worker }
10693*7c568831SAndroid Build Coastguard Worker } else {
10694*7c568831SAndroid Build Coastguard Worker if (cur->type == XML_ELEMENT_NODE) {
10695*7c568831SAndroid Build Coastguard Worker if (prefix == NULL)
10696*7c568831SAndroid Build Coastguard Worker {
10697*7c568831SAndroid Build Coastguard Worker XP_TEST_HIT
10698*7c568831SAndroid Build Coastguard Worker
10699*7c568831SAndroid Build Coastguard Worker } else if ((cur->ns != NULL) &&
10700*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(URI, cur->ns->href)))
10701*7c568831SAndroid Build Coastguard Worker {
10702*7c568831SAndroid Build Coastguard Worker XP_TEST_HIT
10703*7c568831SAndroid Build Coastguard Worker }
10704*7c568831SAndroid Build Coastguard Worker }
10705*7c568831SAndroid Build Coastguard Worker }
10706*7c568831SAndroid Build Coastguard Worker break;
10707*7c568831SAndroid Build Coastguard Worker case NODE_TEST_NS:{
10708*7c568831SAndroid Build Coastguard Worker /* TODO */
10709*7c568831SAndroid Build Coastguard Worker break;
10710*7c568831SAndroid Build Coastguard Worker }
10711*7c568831SAndroid Build Coastguard Worker case NODE_TEST_NAME:
10712*7c568831SAndroid Build Coastguard Worker if (axis == AXIS_ATTRIBUTE) {
10713*7c568831SAndroid Build Coastguard Worker if (cur->type != XML_ATTRIBUTE_NODE)
10714*7c568831SAndroid Build Coastguard Worker break;
10715*7c568831SAndroid Build Coastguard Worker } else if (axis == AXIS_NAMESPACE) {
10716*7c568831SAndroid Build Coastguard Worker if (cur->type != XML_NAMESPACE_DECL)
10717*7c568831SAndroid Build Coastguard Worker break;
10718*7c568831SAndroid Build Coastguard Worker } else {
10719*7c568831SAndroid Build Coastguard Worker if (cur->type != XML_ELEMENT_NODE)
10720*7c568831SAndroid Build Coastguard Worker break;
10721*7c568831SAndroid Build Coastguard Worker }
10722*7c568831SAndroid Build Coastguard Worker switch (cur->type) {
10723*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
10724*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(name, cur->name)) {
10725*7c568831SAndroid Build Coastguard Worker if (prefix == NULL) {
10726*7c568831SAndroid Build Coastguard Worker if (cur->ns == NULL)
10727*7c568831SAndroid Build Coastguard Worker {
10728*7c568831SAndroid Build Coastguard Worker XP_TEST_HIT
10729*7c568831SAndroid Build Coastguard Worker }
10730*7c568831SAndroid Build Coastguard Worker } else {
10731*7c568831SAndroid Build Coastguard Worker if ((cur->ns != NULL) &&
10732*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(URI, cur->ns->href)))
10733*7c568831SAndroid Build Coastguard Worker {
10734*7c568831SAndroid Build Coastguard Worker XP_TEST_HIT
10735*7c568831SAndroid Build Coastguard Worker }
10736*7c568831SAndroid Build Coastguard Worker }
10737*7c568831SAndroid Build Coastguard Worker }
10738*7c568831SAndroid Build Coastguard Worker break;
10739*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE:{
10740*7c568831SAndroid Build Coastguard Worker xmlAttrPtr attr = (xmlAttrPtr) cur;
10741*7c568831SAndroid Build Coastguard Worker
10742*7c568831SAndroid Build Coastguard Worker if (xmlStrEqual(name, attr->name)) {
10743*7c568831SAndroid Build Coastguard Worker if (prefix == NULL) {
10744*7c568831SAndroid Build Coastguard Worker if ((attr->ns == NULL) ||
10745*7c568831SAndroid Build Coastguard Worker (attr->ns->prefix == NULL))
10746*7c568831SAndroid Build Coastguard Worker {
10747*7c568831SAndroid Build Coastguard Worker XP_TEST_HIT
10748*7c568831SAndroid Build Coastguard Worker }
10749*7c568831SAndroid Build Coastguard Worker } else {
10750*7c568831SAndroid Build Coastguard Worker if ((attr->ns != NULL) &&
10751*7c568831SAndroid Build Coastguard Worker (xmlStrEqual(URI,
10752*7c568831SAndroid Build Coastguard Worker attr->ns->href)))
10753*7c568831SAndroid Build Coastguard Worker {
10754*7c568831SAndroid Build Coastguard Worker XP_TEST_HIT
10755*7c568831SAndroid Build Coastguard Worker }
10756*7c568831SAndroid Build Coastguard Worker }
10757*7c568831SAndroid Build Coastguard Worker }
10758*7c568831SAndroid Build Coastguard Worker break;
10759*7c568831SAndroid Build Coastguard Worker }
10760*7c568831SAndroid Build Coastguard Worker case XML_NAMESPACE_DECL:
10761*7c568831SAndroid Build Coastguard Worker if (cur->type == XML_NAMESPACE_DECL) {
10762*7c568831SAndroid Build Coastguard Worker xmlNsPtr ns = (xmlNsPtr) cur;
10763*7c568831SAndroid Build Coastguard Worker
10764*7c568831SAndroid Build Coastguard Worker if ((ns->prefix != NULL) && (name != NULL)
10765*7c568831SAndroid Build Coastguard Worker && (xmlStrEqual(ns->prefix, name)))
10766*7c568831SAndroid Build Coastguard Worker {
10767*7c568831SAndroid Build Coastguard Worker XP_TEST_HIT_NS
10768*7c568831SAndroid Build Coastguard Worker }
10769*7c568831SAndroid Build Coastguard Worker }
10770*7c568831SAndroid Build Coastguard Worker break;
10771*7c568831SAndroid Build Coastguard Worker default:
10772*7c568831SAndroid Build Coastguard Worker break;
10773*7c568831SAndroid Build Coastguard Worker }
10774*7c568831SAndroid Build Coastguard Worker break;
10775*7c568831SAndroid Build Coastguard Worker } /* switch(test) */
10776*7c568831SAndroid Build Coastguard Worker } while ((cur != NULL) && (ctxt->error == XPATH_EXPRESSION_OK));
10777*7c568831SAndroid Build Coastguard Worker
10778*7c568831SAndroid Build Coastguard Worker goto apply_predicates;
10779*7c568831SAndroid Build Coastguard Worker
10780*7c568831SAndroid Build Coastguard Worker axis_range_end: /* ----------------------------------------------------- */
10781*7c568831SAndroid Build Coastguard Worker /*
10782*7c568831SAndroid Build Coastguard Worker * We have a "/foo[n]", and position() = n was reached.
10783*7c568831SAndroid Build Coastguard Worker * Note that we can have as well "/foo/::parent::foo[1]", so
10784*7c568831SAndroid Build Coastguard Worker * a duplicate-aware merge is still needed.
10785*7c568831SAndroid Build Coastguard Worker * Merge with the result.
10786*7c568831SAndroid Build Coastguard Worker */
10787*7c568831SAndroid Build Coastguard Worker if (outSeq == NULL) {
10788*7c568831SAndroid Build Coastguard Worker outSeq = seq;
10789*7c568831SAndroid Build Coastguard Worker seq = NULL;
10790*7c568831SAndroid Build Coastguard Worker } else {
10791*7c568831SAndroid Build Coastguard Worker outSeq = mergeAndClear(outSeq, seq);
10792*7c568831SAndroid Build Coastguard Worker if (outSeq == NULL)
10793*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
10794*7c568831SAndroid Build Coastguard Worker }
10795*7c568831SAndroid Build Coastguard Worker /*
10796*7c568831SAndroid Build Coastguard Worker * Break if only a true/false result was requested.
10797*7c568831SAndroid Build Coastguard Worker */
10798*7c568831SAndroid Build Coastguard Worker if (toBool)
10799*7c568831SAndroid Build Coastguard Worker break;
10800*7c568831SAndroid Build Coastguard Worker continue;
10801*7c568831SAndroid Build Coastguard Worker
10802*7c568831SAndroid Build Coastguard Worker first_hit: /* ---------------------------------------------------------- */
10803*7c568831SAndroid Build Coastguard Worker /*
10804*7c568831SAndroid Build Coastguard Worker * Break if only a true/false result was requested and
10805*7c568831SAndroid Build Coastguard Worker * no predicates existed and a node test succeeded.
10806*7c568831SAndroid Build Coastguard Worker */
10807*7c568831SAndroid Build Coastguard Worker if (outSeq == NULL) {
10808*7c568831SAndroid Build Coastguard Worker outSeq = seq;
10809*7c568831SAndroid Build Coastguard Worker seq = NULL;
10810*7c568831SAndroid Build Coastguard Worker } else {
10811*7c568831SAndroid Build Coastguard Worker outSeq = mergeAndClear(outSeq, seq);
10812*7c568831SAndroid Build Coastguard Worker if (outSeq == NULL)
10813*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
10814*7c568831SAndroid Build Coastguard Worker }
10815*7c568831SAndroid Build Coastguard Worker break;
10816*7c568831SAndroid Build Coastguard Worker
10817*7c568831SAndroid Build Coastguard Worker apply_predicates: /* --------------------------------------------------- */
10818*7c568831SAndroid Build Coastguard Worker if (ctxt->error != XPATH_EXPRESSION_OK)
10819*7c568831SAndroid Build Coastguard Worker goto error;
10820*7c568831SAndroid Build Coastguard Worker
10821*7c568831SAndroid Build Coastguard Worker /*
10822*7c568831SAndroid Build Coastguard Worker * Apply predicates.
10823*7c568831SAndroid Build Coastguard Worker */
10824*7c568831SAndroid Build Coastguard Worker if ((predOp != NULL) && (seq->nodeNr > 0)) {
10825*7c568831SAndroid Build Coastguard Worker /*
10826*7c568831SAndroid Build Coastguard Worker * E.g. when we have a "/foo[some expression][n]".
10827*7c568831SAndroid Build Coastguard Worker */
10828*7c568831SAndroid Build Coastguard Worker /*
10829*7c568831SAndroid Build Coastguard Worker * QUESTION TODO: The old predicate evaluation took into
10830*7c568831SAndroid Build Coastguard Worker * account location-sets.
10831*7c568831SAndroid Build Coastguard Worker * (E.g. ctxt->value->type == XPATH_LOCATIONSET)
10832*7c568831SAndroid Build Coastguard Worker * Do we expect such a set here?
10833*7c568831SAndroid Build Coastguard Worker * All what I learned now from the evaluation semantics
10834*7c568831SAndroid Build Coastguard Worker * does not indicate that a location-set will be processed
10835*7c568831SAndroid Build Coastguard Worker * here, so this looks OK.
10836*7c568831SAndroid Build Coastguard Worker */
10837*7c568831SAndroid Build Coastguard Worker /*
10838*7c568831SAndroid Build Coastguard Worker * Iterate over all predicates, starting with the outermost
10839*7c568831SAndroid Build Coastguard Worker * predicate.
10840*7c568831SAndroid Build Coastguard Worker * TODO: Problem: we cannot execute the inner predicates first
10841*7c568831SAndroid Build Coastguard Worker * since we cannot go back *up* the operator tree!
10842*7c568831SAndroid Build Coastguard Worker * Options we have:
10843*7c568831SAndroid Build Coastguard Worker * 1) Use of recursive functions (like is it currently done
10844*7c568831SAndroid Build Coastguard Worker * via xmlXPathCompOpEval())
10845*7c568831SAndroid Build Coastguard Worker * 2) Add a predicate evaluation information stack to the
10846*7c568831SAndroid Build Coastguard Worker * context struct
10847*7c568831SAndroid Build Coastguard Worker * 3) Change the way the operators are linked; we need a
10848*7c568831SAndroid Build Coastguard Worker * "parent" field on xmlXPathStepOp
10849*7c568831SAndroid Build Coastguard Worker *
10850*7c568831SAndroid Build Coastguard Worker * For the moment, I'll try to solve this with a recursive
10851*7c568831SAndroid Build Coastguard Worker * function: xmlXPathCompOpEvalPredicate().
10852*7c568831SAndroid Build Coastguard Worker */
10853*7c568831SAndroid Build Coastguard Worker if (hasPredicateRange != 0)
10854*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalPredicate(ctxt, predOp, seq, maxPos, maxPos,
10855*7c568831SAndroid Build Coastguard Worker hasNsNodes);
10856*7c568831SAndroid Build Coastguard Worker else
10857*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalPredicate(ctxt, predOp, seq, 1, seq->nodeNr,
10858*7c568831SAndroid Build Coastguard Worker hasNsNodes);
10859*7c568831SAndroid Build Coastguard Worker
10860*7c568831SAndroid Build Coastguard Worker if (ctxt->error != XPATH_EXPRESSION_OK) {
10861*7c568831SAndroid Build Coastguard Worker total = 0;
10862*7c568831SAndroid Build Coastguard Worker goto error;
10863*7c568831SAndroid Build Coastguard Worker }
10864*7c568831SAndroid Build Coastguard Worker }
10865*7c568831SAndroid Build Coastguard Worker
10866*7c568831SAndroid Build Coastguard Worker if (seq->nodeNr > 0) {
10867*7c568831SAndroid Build Coastguard Worker /*
10868*7c568831SAndroid Build Coastguard Worker * Add to result set.
10869*7c568831SAndroid Build Coastguard Worker */
10870*7c568831SAndroid Build Coastguard Worker if (outSeq == NULL) {
10871*7c568831SAndroid Build Coastguard Worker outSeq = seq;
10872*7c568831SAndroid Build Coastguard Worker seq = NULL;
10873*7c568831SAndroid Build Coastguard Worker } else {
10874*7c568831SAndroid Build Coastguard Worker outSeq = mergeAndClear(outSeq, seq);
10875*7c568831SAndroid Build Coastguard Worker if (outSeq == NULL)
10876*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
10877*7c568831SAndroid Build Coastguard Worker }
10878*7c568831SAndroid Build Coastguard Worker
10879*7c568831SAndroid Build Coastguard Worker if (toBool)
10880*7c568831SAndroid Build Coastguard Worker break;
10881*7c568831SAndroid Build Coastguard Worker }
10882*7c568831SAndroid Build Coastguard Worker }
10883*7c568831SAndroid Build Coastguard Worker
10884*7c568831SAndroid Build Coastguard Worker error:
10885*7c568831SAndroid Build Coastguard Worker if ((obj->boolval) && (obj->user != NULL)) {
10886*7c568831SAndroid Build Coastguard Worker /*
10887*7c568831SAndroid Build Coastguard Worker * QUESTION TODO: What does this do and why?
10888*7c568831SAndroid Build Coastguard Worker * TODO: Do we have to do this also for the "error"
10889*7c568831SAndroid Build Coastguard Worker * cleanup further down?
10890*7c568831SAndroid Build Coastguard Worker */
10891*7c568831SAndroid Build Coastguard Worker ctxt->value->boolval = 1;
10892*7c568831SAndroid Build Coastguard Worker ctxt->value->user = obj->user;
10893*7c568831SAndroid Build Coastguard Worker obj->user = NULL;
10894*7c568831SAndroid Build Coastguard Worker obj->boolval = 0;
10895*7c568831SAndroid Build Coastguard Worker }
10896*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(xpctxt, obj);
10897*7c568831SAndroid Build Coastguard Worker
10898*7c568831SAndroid Build Coastguard Worker /*
10899*7c568831SAndroid Build Coastguard Worker * Ensure we return at least an empty set.
10900*7c568831SAndroid Build Coastguard Worker */
10901*7c568831SAndroid Build Coastguard Worker if (outSeq == NULL) {
10902*7c568831SAndroid Build Coastguard Worker if ((seq != NULL) && (seq->nodeNr == 0)) {
10903*7c568831SAndroid Build Coastguard Worker outSeq = seq;
10904*7c568831SAndroid Build Coastguard Worker } else {
10905*7c568831SAndroid Build Coastguard Worker outSeq = xmlXPathNodeSetCreate(NULL);
10906*7c568831SAndroid Build Coastguard Worker if (outSeq == NULL)
10907*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
10908*7c568831SAndroid Build Coastguard Worker }
10909*7c568831SAndroid Build Coastguard Worker }
10910*7c568831SAndroid Build Coastguard Worker if ((seq != NULL) && (seq != outSeq)) {
10911*7c568831SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(seq);
10912*7c568831SAndroid Build Coastguard Worker }
10913*7c568831SAndroid Build Coastguard Worker /*
10914*7c568831SAndroid Build Coastguard Worker * Hand over the result. Better to push the set also in
10915*7c568831SAndroid Build Coastguard Worker * case of errors.
10916*7c568831SAndroid Build Coastguard Worker */
10917*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt, outSeq));
10918*7c568831SAndroid Build Coastguard Worker /*
10919*7c568831SAndroid Build Coastguard Worker * Reset the context node.
10920*7c568831SAndroid Build Coastguard Worker */
10921*7c568831SAndroid Build Coastguard Worker xpctxt->node = oldContextNode;
10922*7c568831SAndroid Build Coastguard Worker /*
10923*7c568831SAndroid Build Coastguard Worker * When traversing the namespace axis in "toBool" mode, it's
10924*7c568831SAndroid Build Coastguard Worker * possible that tmpNsList wasn't freed.
10925*7c568831SAndroid Build Coastguard Worker */
10926*7c568831SAndroid Build Coastguard Worker if (xpctxt->tmpNsList != NULL) {
10927*7c568831SAndroid Build Coastguard Worker xmlFree(xpctxt->tmpNsList);
10928*7c568831SAndroid Build Coastguard Worker xpctxt->tmpNsList = NULL;
10929*7c568831SAndroid Build Coastguard Worker }
10930*7c568831SAndroid Build Coastguard Worker
10931*7c568831SAndroid Build Coastguard Worker return(total);
10932*7c568831SAndroid Build Coastguard Worker }
10933*7c568831SAndroid Build Coastguard Worker
10934*7c568831SAndroid Build Coastguard Worker static int
10935*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
10936*7c568831SAndroid Build Coastguard Worker xmlXPathStepOpPtr op, xmlNodePtr * first);
10937*7c568831SAndroid Build Coastguard Worker
10938*7c568831SAndroid Build Coastguard Worker /**
10939*7c568831SAndroid Build Coastguard Worker * xmlXPathCompOpEvalFirst:
10940*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath parser context with the compiled expression
10941*7c568831SAndroid Build Coastguard Worker * @op: an XPath compiled operation
10942*7c568831SAndroid Build Coastguard Worker * @first: the first elem found so far
10943*7c568831SAndroid Build Coastguard Worker *
10944*7c568831SAndroid Build Coastguard Worker * Evaluate the Precompiled XPath operation searching only the first
10945*7c568831SAndroid Build Coastguard Worker * element in document order
10946*7c568831SAndroid Build Coastguard Worker *
10947*7c568831SAndroid Build Coastguard Worker * Returns the number of examined objects.
10948*7c568831SAndroid Build Coastguard Worker */
10949*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt,xmlXPathStepOpPtr op,xmlNodePtr * first)10950*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt,
10951*7c568831SAndroid Build Coastguard Worker xmlXPathStepOpPtr op, xmlNodePtr * first)
10952*7c568831SAndroid Build Coastguard Worker {
10953*7c568831SAndroid Build Coastguard Worker int total = 0, cur;
10954*7c568831SAndroid Build Coastguard Worker xmlXPathCompExprPtr comp;
10955*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr arg1, arg2;
10956*7c568831SAndroid Build Coastguard Worker
10957*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
10958*7c568831SAndroid Build Coastguard Worker if (OP_LIMIT_EXCEEDED(ctxt, 1))
10959*7c568831SAndroid Build Coastguard Worker return(0);
10960*7c568831SAndroid Build Coastguard Worker if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH)
10961*7c568831SAndroid Build Coastguard Worker XP_ERROR0(XPATH_RECURSION_LIMIT_EXCEEDED);
10962*7c568831SAndroid Build Coastguard Worker ctxt->context->depth += 1;
10963*7c568831SAndroid Build Coastguard Worker comp = ctxt->comp;
10964*7c568831SAndroid Build Coastguard Worker switch (op->op) {
10965*7c568831SAndroid Build Coastguard Worker case XPATH_OP_END:
10966*7c568831SAndroid Build Coastguard Worker break;
10967*7c568831SAndroid Build Coastguard Worker case XPATH_OP_UNION:
10968*7c568831SAndroid Build Coastguard Worker total =
10969*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch1],
10970*7c568831SAndroid Build Coastguard Worker first);
10971*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
10972*7c568831SAndroid Build Coastguard Worker if ((ctxt->value != NULL)
10973*7c568831SAndroid Build Coastguard Worker && (ctxt->value->type == XPATH_NODESET)
10974*7c568831SAndroid Build Coastguard Worker && (ctxt->value->nodesetval != NULL)
10975*7c568831SAndroid Build Coastguard Worker && (ctxt->value->nodesetval->nodeNr >= 1)) {
10976*7c568831SAndroid Build Coastguard Worker /*
10977*7c568831SAndroid Build Coastguard Worker * limit tree traversing to first node in the result
10978*7c568831SAndroid Build Coastguard Worker */
10979*7c568831SAndroid Build Coastguard Worker /*
10980*7c568831SAndroid Build Coastguard Worker * OPTIMIZE TODO: This implicitly sorts
10981*7c568831SAndroid Build Coastguard Worker * the result, even if not needed. E.g. if the argument
10982*7c568831SAndroid Build Coastguard Worker * of the count() function, no sorting is needed.
10983*7c568831SAndroid Build Coastguard Worker * OPTIMIZE TODO: How do we know if the node-list wasn't
10984*7c568831SAndroid Build Coastguard Worker * already sorted?
10985*7c568831SAndroid Build Coastguard Worker */
10986*7c568831SAndroid Build Coastguard Worker if (ctxt->value->nodesetval->nodeNr > 1)
10987*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetSort(ctxt->value->nodesetval);
10988*7c568831SAndroid Build Coastguard Worker *first = ctxt->value->nodesetval->nodeTab[0];
10989*7c568831SAndroid Build Coastguard Worker }
10990*7c568831SAndroid Build Coastguard Worker cur =
10991*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch2],
10992*7c568831SAndroid Build Coastguard Worker first);
10993*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
10994*7c568831SAndroid Build Coastguard Worker
10995*7c568831SAndroid Build Coastguard Worker arg2 = valuePop(ctxt);
10996*7c568831SAndroid Build Coastguard Worker arg1 = valuePop(ctxt);
10997*7c568831SAndroid Build Coastguard Worker if ((arg1 == NULL) || (arg1->type != XPATH_NODESET) ||
10998*7c568831SAndroid Build Coastguard Worker (arg2 == NULL) || (arg2->type != XPATH_NODESET)) {
10999*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
11000*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
11001*7c568831SAndroid Build Coastguard Worker XP_ERROR0(XPATH_INVALID_TYPE);
11002*7c568831SAndroid Build Coastguard Worker }
11003*7c568831SAndroid Build Coastguard Worker if ((ctxt->context->opLimit != 0) &&
11004*7c568831SAndroid Build Coastguard Worker (((arg1->nodesetval != NULL) &&
11005*7c568831SAndroid Build Coastguard Worker (xmlXPathCheckOpLimit(ctxt,
11006*7c568831SAndroid Build Coastguard Worker arg1->nodesetval->nodeNr) < 0)) ||
11007*7c568831SAndroid Build Coastguard Worker ((arg2->nodesetval != NULL) &&
11008*7c568831SAndroid Build Coastguard Worker (xmlXPathCheckOpLimit(ctxt,
11009*7c568831SAndroid Build Coastguard Worker arg2->nodesetval->nodeNr) < 0)))) {
11010*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
11011*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
11012*7c568831SAndroid Build Coastguard Worker break;
11013*7c568831SAndroid Build Coastguard Worker }
11014*7c568831SAndroid Build Coastguard Worker
11015*7c568831SAndroid Build Coastguard Worker if ((arg2->nodesetval != NULL) &&
11016*7c568831SAndroid Build Coastguard Worker (arg2->nodesetval->nodeNr != 0)) {
11017*7c568831SAndroid Build Coastguard Worker arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
11018*7c568831SAndroid Build Coastguard Worker arg2->nodesetval);
11019*7c568831SAndroid Build Coastguard Worker if (arg1->nodesetval == NULL)
11020*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
11021*7c568831SAndroid Build Coastguard Worker }
11022*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, arg1);
11023*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
11024*7c568831SAndroid Build Coastguard Worker total += cur;
11025*7c568831SAndroid Build Coastguard Worker break;
11026*7c568831SAndroid Build Coastguard Worker case XPATH_OP_ROOT:
11027*7c568831SAndroid Build Coastguard Worker xmlXPathRoot(ctxt);
11028*7c568831SAndroid Build Coastguard Worker break;
11029*7c568831SAndroid Build Coastguard Worker case XPATH_OP_NODE:
11030*7c568831SAndroid Build Coastguard Worker if (op->ch1 != -1)
11031*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11032*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11033*7c568831SAndroid Build Coastguard Worker if (op->ch2 != -1)
11034*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11035*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11036*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt,
11037*7c568831SAndroid Build Coastguard Worker ctxt->context->node));
11038*7c568831SAndroid Build Coastguard Worker break;
11039*7c568831SAndroid Build Coastguard Worker case XPATH_OP_COLLECT:{
11040*7c568831SAndroid Build Coastguard Worker if (op->ch1 == -1)
11041*7c568831SAndroid Build Coastguard Worker break;
11042*7c568831SAndroid Build Coastguard Worker
11043*7c568831SAndroid Build Coastguard Worker total = xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11044*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11045*7c568831SAndroid Build Coastguard Worker
11046*7c568831SAndroid Build Coastguard Worker total += xmlXPathNodeCollectAndTest(ctxt, op, first, NULL, 0);
11047*7c568831SAndroid Build Coastguard Worker break;
11048*7c568831SAndroid Build Coastguard Worker }
11049*7c568831SAndroid Build Coastguard Worker case XPATH_OP_VALUE:
11050*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt, op->value4));
11051*7c568831SAndroid Build Coastguard Worker break;
11052*7c568831SAndroid Build Coastguard Worker case XPATH_OP_SORT:
11053*7c568831SAndroid Build Coastguard Worker if (op->ch1 != -1)
11054*7c568831SAndroid Build Coastguard Worker total +=
11055*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch1],
11056*7c568831SAndroid Build Coastguard Worker first);
11057*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11058*7c568831SAndroid Build Coastguard Worker if ((ctxt->value != NULL)
11059*7c568831SAndroid Build Coastguard Worker && (ctxt->value->type == XPATH_NODESET)
11060*7c568831SAndroid Build Coastguard Worker && (ctxt->value->nodesetval != NULL)
11061*7c568831SAndroid Build Coastguard Worker && (ctxt->value->nodesetval->nodeNr > 1))
11062*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetSort(ctxt->value->nodesetval);
11063*7c568831SAndroid Build Coastguard Worker break;
11064*7c568831SAndroid Build Coastguard Worker #ifdef XP_OPTIMIZED_FILTER_FIRST
11065*7c568831SAndroid Build Coastguard Worker case XPATH_OP_FILTER:
11066*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEvalFilterFirst(ctxt, op, first);
11067*7c568831SAndroid Build Coastguard Worker break;
11068*7c568831SAndroid Build Coastguard Worker #endif
11069*7c568831SAndroid Build Coastguard Worker default:
11070*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, op);
11071*7c568831SAndroid Build Coastguard Worker break;
11072*7c568831SAndroid Build Coastguard Worker }
11073*7c568831SAndroid Build Coastguard Worker
11074*7c568831SAndroid Build Coastguard Worker ctxt->context->depth -= 1;
11075*7c568831SAndroid Build Coastguard Worker return(total);
11076*7c568831SAndroid Build Coastguard Worker }
11077*7c568831SAndroid Build Coastguard Worker
11078*7c568831SAndroid Build Coastguard Worker /**
11079*7c568831SAndroid Build Coastguard Worker * xmlXPathCompOpEvalLast:
11080*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath parser context with the compiled expression
11081*7c568831SAndroid Build Coastguard Worker * @op: an XPath compiled operation
11082*7c568831SAndroid Build Coastguard Worker * @last: the last elem found so far
11083*7c568831SAndroid Build Coastguard Worker *
11084*7c568831SAndroid Build Coastguard Worker * Evaluate the Precompiled XPath operation searching only the last
11085*7c568831SAndroid Build Coastguard Worker * element in document order
11086*7c568831SAndroid Build Coastguard Worker *
11087*7c568831SAndroid Build Coastguard Worker * Returns the number of nodes traversed
11088*7c568831SAndroid Build Coastguard Worker */
11089*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt,xmlXPathStepOpPtr op,xmlNodePtr * last)11090*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
11091*7c568831SAndroid Build Coastguard Worker xmlNodePtr * last)
11092*7c568831SAndroid Build Coastguard Worker {
11093*7c568831SAndroid Build Coastguard Worker int total = 0, cur;
11094*7c568831SAndroid Build Coastguard Worker xmlXPathCompExprPtr comp;
11095*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr arg1, arg2;
11096*7c568831SAndroid Build Coastguard Worker
11097*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11098*7c568831SAndroid Build Coastguard Worker if (OP_LIMIT_EXCEEDED(ctxt, 1))
11099*7c568831SAndroid Build Coastguard Worker return(0);
11100*7c568831SAndroid Build Coastguard Worker if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH)
11101*7c568831SAndroid Build Coastguard Worker XP_ERROR0(XPATH_RECURSION_LIMIT_EXCEEDED);
11102*7c568831SAndroid Build Coastguard Worker ctxt->context->depth += 1;
11103*7c568831SAndroid Build Coastguard Worker comp = ctxt->comp;
11104*7c568831SAndroid Build Coastguard Worker switch (op->op) {
11105*7c568831SAndroid Build Coastguard Worker case XPATH_OP_END:
11106*7c568831SAndroid Build Coastguard Worker break;
11107*7c568831SAndroid Build Coastguard Worker case XPATH_OP_UNION:
11108*7c568831SAndroid Build Coastguard Worker total =
11109*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch1], last);
11110*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11111*7c568831SAndroid Build Coastguard Worker if ((ctxt->value != NULL)
11112*7c568831SAndroid Build Coastguard Worker && (ctxt->value->type == XPATH_NODESET)
11113*7c568831SAndroid Build Coastguard Worker && (ctxt->value->nodesetval != NULL)
11114*7c568831SAndroid Build Coastguard Worker && (ctxt->value->nodesetval->nodeNr >= 1)) {
11115*7c568831SAndroid Build Coastguard Worker /*
11116*7c568831SAndroid Build Coastguard Worker * limit tree traversing to first node in the result
11117*7c568831SAndroid Build Coastguard Worker */
11118*7c568831SAndroid Build Coastguard Worker if (ctxt->value->nodesetval->nodeNr > 1)
11119*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetSort(ctxt->value->nodesetval);
11120*7c568831SAndroid Build Coastguard Worker *last =
11121*7c568831SAndroid Build Coastguard Worker ctxt->value->nodesetval->nodeTab[ctxt->value->
11122*7c568831SAndroid Build Coastguard Worker nodesetval->nodeNr -
11123*7c568831SAndroid Build Coastguard Worker 1];
11124*7c568831SAndroid Build Coastguard Worker }
11125*7c568831SAndroid Build Coastguard Worker cur =
11126*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch2], last);
11127*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11128*7c568831SAndroid Build Coastguard Worker if ((ctxt->value != NULL)
11129*7c568831SAndroid Build Coastguard Worker && (ctxt->value->type == XPATH_NODESET)
11130*7c568831SAndroid Build Coastguard Worker && (ctxt->value->nodesetval != NULL)
11131*7c568831SAndroid Build Coastguard Worker && (ctxt->value->nodesetval->nodeNr >= 1)) { /* TODO: NOP ? */
11132*7c568831SAndroid Build Coastguard Worker }
11133*7c568831SAndroid Build Coastguard Worker
11134*7c568831SAndroid Build Coastguard Worker arg2 = valuePop(ctxt);
11135*7c568831SAndroid Build Coastguard Worker arg1 = valuePop(ctxt);
11136*7c568831SAndroid Build Coastguard Worker if ((arg1 == NULL) || (arg1->type != XPATH_NODESET) ||
11137*7c568831SAndroid Build Coastguard Worker (arg2 == NULL) || (arg2->type != XPATH_NODESET)) {
11138*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
11139*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
11140*7c568831SAndroid Build Coastguard Worker XP_ERROR0(XPATH_INVALID_TYPE);
11141*7c568831SAndroid Build Coastguard Worker }
11142*7c568831SAndroid Build Coastguard Worker if ((ctxt->context->opLimit != 0) &&
11143*7c568831SAndroid Build Coastguard Worker (((arg1->nodesetval != NULL) &&
11144*7c568831SAndroid Build Coastguard Worker (xmlXPathCheckOpLimit(ctxt,
11145*7c568831SAndroid Build Coastguard Worker arg1->nodesetval->nodeNr) < 0)) ||
11146*7c568831SAndroid Build Coastguard Worker ((arg2->nodesetval != NULL) &&
11147*7c568831SAndroid Build Coastguard Worker (xmlXPathCheckOpLimit(ctxt,
11148*7c568831SAndroid Build Coastguard Worker arg2->nodesetval->nodeNr) < 0)))) {
11149*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
11150*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
11151*7c568831SAndroid Build Coastguard Worker break;
11152*7c568831SAndroid Build Coastguard Worker }
11153*7c568831SAndroid Build Coastguard Worker
11154*7c568831SAndroid Build Coastguard Worker if ((arg2->nodesetval != NULL) &&
11155*7c568831SAndroid Build Coastguard Worker (arg2->nodesetval->nodeNr != 0)) {
11156*7c568831SAndroid Build Coastguard Worker arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
11157*7c568831SAndroid Build Coastguard Worker arg2->nodesetval);
11158*7c568831SAndroid Build Coastguard Worker if (arg1->nodesetval == NULL)
11159*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
11160*7c568831SAndroid Build Coastguard Worker }
11161*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, arg1);
11162*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
11163*7c568831SAndroid Build Coastguard Worker total += cur;
11164*7c568831SAndroid Build Coastguard Worker break;
11165*7c568831SAndroid Build Coastguard Worker case XPATH_OP_ROOT:
11166*7c568831SAndroid Build Coastguard Worker xmlXPathRoot(ctxt);
11167*7c568831SAndroid Build Coastguard Worker break;
11168*7c568831SAndroid Build Coastguard Worker case XPATH_OP_NODE:
11169*7c568831SAndroid Build Coastguard Worker if (op->ch1 != -1)
11170*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11171*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11172*7c568831SAndroid Build Coastguard Worker if (op->ch2 != -1)
11173*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11174*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11175*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt,
11176*7c568831SAndroid Build Coastguard Worker ctxt->context->node));
11177*7c568831SAndroid Build Coastguard Worker break;
11178*7c568831SAndroid Build Coastguard Worker case XPATH_OP_COLLECT:{
11179*7c568831SAndroid Build Coastguard Worker if (op->ch1 == -1)
11180*7c568831SAndroid Build Coastguard Worker break;
11181*7c568831SAndroid Build Coastguard Worker
11182*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11183*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11184*7c568831SAndroid Build Coastguard Worker
11185*7c568831SAndroid Build Coastguard Worker total += xmlXPathNodeCollectAndTest(ctxt, op, NULL, last, 0);
11186*7c568831SAndroid Build Coastguard Worker break;
11187*7c568831SAndroid Build Coastguard Worker }
11188*7c568831SAndroid Build Coastguard Worker case XPATH_OP_VALUE:
11189*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt, op->value4));
11190*7c568831SAndroid Build Coastguard Worker break;
11191*7c568831SAndroid Build Coastguard Worker case XPATH_OP_SORT:
11192*7c568831SAndroid Build Coastguard Worker if (op->ch1 != -1)
11193*7c568831SAndroid Build Coastguard Worker total +=
11194*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch1],
11195*7c568831SAndroid Build Coastguard Worker last);
11196*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11197*7c568831SAndroid Build Coastguard Worker if ((ctxt->value != NULL)
11198*7c568831SAndroid Build Coastguard Worker && (ctxt->value->type == XPATH_NODESET)
11199*7c568831SAndroid Build Coastguard Worker && (ctxt->value->nodesetval != NULL)
11200*7c568831SAndroid Build Coastguard Worker && (ctxt->value->nodesetval->nodeNr > 1))
11201*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetSort(ctxt->value->nodesetval);
11202*7c568831SAndroid Build Coastguard Worker break;
11203*7c568831SAndroid Build Coastguard Worker default:
11204*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, op);
11205*7c568831SAndroid Build Coastguard Worker break;
11206*7c568831SAndroid Build Coastguard Worker }
11207*7c568831SAndroid Build Coastguard Worker
11208*7c568831SAndroid Build Coastguard Worker ctxt->context->depth -= 1;
11209*7c568831SAndroid Build Coastguard Worker return (total);
11210*7c568831SAndroid Build Coastguard Worker }
11211*7c568831SAndroid Build Coastguard Worker
11212*7c568831SAndroid Build Coastguard Worker #ifdef XP_OPTIMIZED_FILTER_FIRST
11213*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,xmlXPathStepOpPtr op,xmlNodePtr * first)11214*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
11215*7c568831SAndroid Build Coastguard Worker xmlXPathStepOpPtr op, xmlNodePtr * first)
11216*7c568831SAndroid Build Coastguard Worker {
11217*7c568831SAndroid Build Coastguard Worker int total = 0;
11218*7c568831SAndroid Build Coastguard Worker xmlXPathCompExprPtr comp;
11219*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr obj;
11220*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr set;
11221*7c568831SAndroid Build Coastguard Worker
11222*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11223*7c568831SAndroid Build Coastguard Worker comp = ctxt->comp;
11224*7c568831SAndroid Build Coastguard Worker /*
11225*7c568831SAndroid Build Coastguard Worker * Optimization for ()[last()] selection i.e. the last elem
11226*7c568831SAndroid Build Coastguard Worker */
11227*7c568831SAndroid Build Coastguard Worker if ((op->ch1 != -1) && (op->ch2 != -1) &&
11228*7c568831SAndroid Build Coastguard Worker (comp->steps[op->ch1].op == XPATH_OP_SORT) &&
11229*7c568831SAndroid Build Coastguard Worker (comp->steps[op->ch2].op == XPATH_OP_SORT)) {
11230*7c568831SAndroid Build Coastguard Worker int f = comp->steps[op->ch2].ch1;
11231*7c568831SAndroid Build Coastguard Worker
11232*7c568831SAndroid Build Coastguard Worker if ((f != -1) &&
11233*7c568831SAndroid Build Coastguard Worker (comp->steps[f].op == XPATH_OP_FUNCTION) &&
11234*7c568831SAndroid Build Coastguard Worker (comp->steps[f].value5 == NULL) &&
11235*7c568831SAndroid Build Coastguard Worker (comp->steps[f].value == 0) &&
11236*7c568831SAndroid Build Coastguard Worker (comp->steps[f].value4 != NULL) &&
11237*7c568831SAndroid Build Coastguard Worker (xmlStrEqual
11238*7c568831SAndroid Build Coastguard Worker (comp->steps[f].value4, BAD_CAST "last"))) {
11239*7c568831SAndroid Build Coastguard Worker xmlNodePtr last = NULL;
11240*7c568831SAndroid Build Coastguard Worker
11241*7c568831SAndroid Build Coastguard Worker total +=
11242*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalLast(ctxt,
11243*7c568831SAndroid Build Coastguard Worker &comp->steps[op->ch1],
11244*7c568831SAndroid Build Coastguard Worker &last);
11245*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11246*7c568831SAndroid Build Coastguard Worker /*
11247*7c568831SAndroid Build Coastguard Worker * The nodeset should be in document order,
11248*7c568831SAndroid Build Coastguard Worker * Keep only the last value
11249*7c568831SAndroid Build Coastguard Worker */
11250*7c568831SAndroid Build Coastguard Worker if ((ctxt->value != NULL) &&
11251*7c568831SAndroid Build Coastguard Worker (ctxt->value->type == XPATH_NODESET) &&
11252*7c568831SAndroid Build Coastguard Worker (ctxt->value->nodesetval != NULL) &&
11253*7c568831SAndroid Build Coastguard Worker (ctxt->value->nodesetval->nodeTab != NULL) &&
11254*7c568831SAndroid Build Coastguard Worker (ctxt->value->nodesetval->nodeNr > 1)) {
11255*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetKeepLast(ctxt->value->nodesetval);
11256*7c568831SAndroid Build Coastguard Worker *first = *(ctxt->value->nodesetval->nodeTab);
11257*7c568831SAndroid Build Coastguard Worker }
11258*7c568831SAndroid Build Coastguard Worker return (total);
11259*7c568831SAndroid Build Coastguard Worker }
11260*7c568831SAndroid Build Coastguard Worker }
11261*7c568831SAndroid Build Coastguard Worker
11262*7c568831SAndroid Build Coastguard Worker if (op->ch1 != -1)
11263*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11264*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11265*7c568831SAndroid Build Coastguard Worker if (op->ch2 == -1)
11266*7c568831SAndroid Build Coastguard Worker return (total);
11267*7c568831SAndroid Build Coastguard Worker if (ctxt->value == NULL)
11268*7c568831SAndroid Build Coastguard Worker return (total);
11269*7c568831SAndroid Build Coastguard Worker
11270*7c568831SAndroid Build Coastguard Worker /*
11271*7c568831SAndroid Build Coastguard Worker * In case of errors, xmlXPathNodeSetFilter can pop additional nodes from
11272*7c568831SAndroid Build Coastguard Worker * the stack. We have to temporarily remove the nodeset object from the
11273*7c568831SAndroid Build Coastguard Worker * stack to avoid freeing it prematurely.
11274*7c568831SAndroid Build Coastguard Worker */
11275*7c568831SAndroid Build Coastguard Worker CHECK_TYPE0(XPATH_NODESET);
11276*7c568831SAndroid Build Coastguard Worker obj = valuePop(ctxt);
11277*7c568831SAndroid Build Coastguard Worker set = obj->nodesetval;
11278*7c568831SAndroid Build Coastguard Worker if (set != NULL) {
11279*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetFilter(ctxt, set, op->ch2, 1, 1, 1);
11280*7c568831SAndroid Build Coastguard Worker if (set->nodeNr > 0)
11281*7c568831SAndroid Build Coastguard Worker *first = set->nodeTab[0];
11282*7c568831SAndroid Build Coastguard Worker }
11283*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, obj);
11284*7c568831SAndroid Build Coastguard Worker
11285*7c568831SAndroid Build Coastguard Worker return (total);
11286*7c568831SAndroid Build Coastguard Worker }
11287*7c568831SAndroid Build Coastguard Worker #endif /* XP_OPTIMIZED_FILTER_FIRST */
11288*7c568831SAndroid Build Coastguard Worker
11289*7c568831SAndroid Build Coastguard Worker /**
11290*7c568831SAndroid Build Coastguard Worker * xmlXPathCompOpEval:
11291*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath parser context with the compiled expression
11292*7c568831SAndroid Build Coastguard Worker * @op: an XPath compiled operation
11293*7c568831SAndroid Build Coastguard Worker *
11294*7c568831SAndroid Build Coastguard Worker * Evaluate the Precompiled XPath operation
11295*7c568831SAndroid Build Coastguard Worker * Returns the number of nodes traversed
11296*7c568831SAndroid Build Coastguard Worker */
11297*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt,xmlXPathStepOpPtr op)11298*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
11299*7c568831SAndroid Build Coastguard Worker {
11300*7c568831SAndroid Build Coastguard Worker int total = 0;
11301*7c568831SAndroid Build Coastguard Worker int equal, ret;
11302*7c568831SAndroid Build Coastguard Worker xmlXPathCompExprPtr comp;
11303*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr arg1, arg2;
11304*7c568831SAndroid Build Coastguard Worker
11305*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11306*7c568831SAndroid Build Coastguard Worker if (OP_LIMIT_EXCEEDED(ctxt, 1))
11307*7c568831SAndroid Build Coastguard Worker return(0);
11308*7c568831SAndroid Build Coastguard Worker if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH)
11309*7c568831SAndroid Build Coastguard Worker XP_ERROR0(XPATH_RECURSION_LIMIT_EXCEEDED);
11310*7c568831SAndroid Build Coastguard Worker ctxt->context->depth += 1;
11311*7c568831SAndroid Build Coastguard Worker comp = ctxt->comp;
11312*7c568831SAndroid Build Coastguard Worker switch (op->op) {
11313*7c568831SAndroid Build Coastguard Worker case XPATH_OP_END:
11314*7c568831SAndroid Build Coastguard Worker break;
11315*7c568831SAndroid Build Coastguard Worker case XPATH_OP_AND:
11316*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11317*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11318*7c568831SAndroid Build Coastguard Worker xmlXPathBooleanFunction(ctxt, 1);
11319*7c568831SAndroid Build Coastguard Worker if ((ctxt->value == NULL) || (ctxt->value->boolval == 0))
11320*7c568831SAndroid Build Coastguard Worker break;
11321*7c568831SAndroid Build Coastguard Worker arg2 = valuePop(ctxt);
11322*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11323*7c568831SAndroid Build Coastguard Worker if (ctxt->error) {
11324*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(arg2);
11325*7c568831SAndroid Build Coastguard Worker break;
11326*7c568831SAndroid Build Coastguard Worker }
11327*7c568831SAndroid Build Coastguard Worker xmlXPathBooleanFunction(ctxt, 1);
11328*7c568831SAndroid Build Coastguard Worker if (ctxt->value != NULL)
11329*7c568831SAndroid Build Coastguard Worker ctxt->value->boolval &= arg2->boolval;
11330*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
11331*7c568831SAndroid Build Coastguard Worker break;
11332*7c568831SAndroid Build Coastguard Worker case XPATH_OP_OR:
11333*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11334*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11335*7c568831SAndroid Build Coastguard Worker xmlXPathBooleanFunction(ctxt, 1);
11336*7c568831SAndroid Build Coastguard Worker if ((ctxt->value == NULL) || (ctxt->value->boolval == 1))
11337*7c568831SAndroid Build Coastguard Worker break;
11338*7c568831SAndroid Build Coastguard Worker arg2 = valuePop(ctxt);
11339*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11340*7c568831SAndroid Build Coastguard Worker if (ctxt->error) {
11341*7c568831SAndroid Build Coastguard Worker xmlXPathFreeObject(arg2);
11342*7c568831SAndroid Build Coastguard Worker break;
11343*7c568831SAndroid Build Coastguard Worker }
11344*7c568831SAndroid Build Coastguard Worker xmlXPathBooleanFunction(ctxt, 1);
11345*7c568831SAndroid Build Coastguard Worker if (ctxt->value != NULL)
11346*7c568831SAndroid Build Coastguard Worker ctxt->value->boolval |= arg2->boolval;
11347*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
11348*7c568831SAndroid Build Coastguard Worker break;
11349*7c568831SAndroid Build Coastguard Worker case XPATH_OP_EQUAL:
11350*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11351*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11352*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11353*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11354*7c568831SAndroid Build Coastguard Worker if (op->value)
11355*7c568831SAndroid Build Coastguard Worker equal = xmlXPathEqualValues(ctxt);
11356*7c568831SAndroid Build Coastguard Worker else
11357*7c568831SAndroid Build Coastguard Worker equal = xmlXPathNotEqualValues(ctxt);
11358*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, equal));
11359*7c568831SAndroid Build Coastguard Worker break;
11360*7c568831SAndroid Build Coastguard Worker case XPATH_OP_CMP:
11361*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11362*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11363*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11364*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11365*7c568831SAndroid Build Coastguard Worker ret = xmlXPathCompareValues(ctxt, op->value, op->value2);
11366*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, ret));
11367*7c568831SAndroid Build Coastguard Worker break;
11368*7c568831SAndroid Build Coastguard Worker case XPATH_OP_PLUS:
11369*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11370*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11371*7c568831SAndroid Build Coastguard Worker if (op->ch2 != -1) {
11372*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11373*7c568831SAndroid Build Coastguard Worker }
11374*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11375*7c568831SAndroid Build Coastguard Worker if (op->value == 0)
11376*7c568831SAndroid Build Coastguard Worker xmlXPathSubValues(ctxt);
11377*7c568831SAndroid Build Coastguard Worker else if (op->value == 1)
11378*7c568831SAndroid Build Coastguard Worker xmlXPathAddValues(ctxt);
11379*7c568831SAndroid Build Coastguard Worker else if (op->value == 2)
11380*7c568831SAndroid Build Coastguard Worker xmlXPathValueFlipSign(ctxt);
11381*7c568831SAndroid Build Coastguard Worker else if (op->value == 3) {
11382*7c568831SAndroid Build Coastguard Worker CAST_TO_NUMBER;
11383*7c568831SAndroid Build Coastguard Worker CHECK_TYPE0(XPATH_NUMBER);
11384*7c568831SAndroid Build Coastguard Worker }
11385*7c568831SAndroid Build Coastguard Worker break;
11386*7c568831SAndroid Build Coastguard Worker case XPATH_OP_MULT:
11387*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11388*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11389*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11390*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11391*7c568831SAndroid Build Coastguard Worker if (op->value == 0)
11392*7c568831SAndroid Build Coastguard Worker xmlXPathMultValues(ctxt);
11393*7c568831SAndroid Build Coastguard Worker else if (op->value == 1)
11394*7c568831SAndroid Build Coastguard Worker xmlXPathDivValues(ctxt);
11395*7c568831SAndroid Build Coastguard Worker else if (op->value == 2)
11396*7c568831SAndroid Build Coastguard Worker xmlXPathModValues(ctxt);
11397*7c568831SAndroid Build Coastguard Worker break;
11398*7c568831SAndroid Build Coastguard Worker case XPATH_OP_UNION:
11399*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11400*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11401*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11402*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11403*7c568831SAndroid Build Coastguard Worker
11404*7c568831SAndroid Build Coastguard Worker arg2 = valuePop(ctxt);
11405*7c568831SAndroid Build Coastguard Worker arg1 = valuePop(ctxt);
11406*7c568831SAndroid Build Coastguard Worker if ((arg1 == NULL) || (arg1->type != XPATH_NODESET) ||
11407*7c568831SAndroid Build Coastguard Worker (arg2 == NULL) || (arg2->type != XPATH_NODESET)) {
11408*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
11409*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
11410*7c568831SAndroid Build Coastguard Worker XP_ERROR0(XPATH_INVALID_TYPE);
11411*7c568831SAndroid Build Coastguard Worker }
11412*7c568831SAndroid Build Coastguard Worker if ((ctxt->context->opLimit != 0) &&
11413*7c568831SAndroid Build Coastguard Worker (((arg1->nodesetval != NULL) &&
11414*7c568831SAndroid Build Coastguard Worker (xmlXPathCheckOpLimit(ctxt,
11415*7c568831SAndroid Build Coastguard Worker arg1->nodesetval->nodeNr) < 0)) ||
11416*7c568831SAndroid Build Coastguard Worker ((arg2->nodesetval != NULL) &&
11417*7c568831SAndroid Build Coastguard Worker (xmlXPathCheckOpLimit(ctxt,
11418*7c568831SAndroid Build Coastguard Worker arg2->nodesetval->nodeNr) < 0)))) {
11419*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
11420*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
11421*7c568831SAndroid Build Coastguard Worker break;
11422*7c568831SAndroid Build Coastguard Worker }
11423*7c568831SAndroid Build Coastguard Worker
11424*7c568831SAndroid Build Coastguard Worker if (((arg2->nodesetval != NULL) &&
11425*7c568831SAndroid Build Coastguard Worker (arg2->nodesetval->nodeNr != 0)))
11426*7c568831SAndroid Build Coastguard Worker {
11427*7c568831SAndroid Build Coastguard Worker arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
11428*7c568831SAndroid Build Coastguard Worker arg2->nodesetval);
11429*7c568831SAndroid Build Coastguard Worker if (arg1->nodesetval == NULL)
11430*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
11431*7c568831SAndroid Build Coastguard Worker }
11432*7c568831SAndroid Build Coastguard Worker
11433*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, arg1);
11434*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
11435*7c568831SAndroid Build Coastguard Worker break;
11436*7c568831SAndroid Build Coastguard Worker case XPATH_OP_ROOT:
11437*7c568831SAndroid Build Coastguard Worker xmlXPathRoot(ctxt);
11438*7c568831SAndroid Build Coastguard Worker break;
11439*7c568831SAndroid Build Coastguard Worker case XPATH_OP_NODE:
11440*7c568831SAndroid Build Coastguard Worker if (op->ch1 != -1)
11441*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11442*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11443*7c568831SAndroid Build Coastguard Worker if (op->ch2 != -1)
11444*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11445*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11446*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt,
11447*7c568831SAndroid Build Coastguard Worker ctxt->context->node));
11448*7c568831SAndroid Build Coastguard Worker break;
11449*7c568831SAndroid Build Coastguard Worker case XPATH_OP_COLLECT:{
11450*7c568831SAndroid Build Coastguard Worker if (op->ch1 == -1)
11451*7c568831SAndroid Build Coastguard Worker break;
11452*7c568831SAndroid Build Coastguard Worker
11453*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11454*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11455*7c568831SAndroid Build Coastguard Worker
11456*7c568831SAndroid Build Coastguard Worker total += xmlXPathNodeCollectAndTest(ctxt, op, NULL, NULL, 0);
11457*7c568831SAndroid Build Coastguard Worker break;
11458*7c568831SAndroid Build Coastguard Worker }
11459*7c568831SAndroid Build Coastguard Worker case XPATH_OP_VALUE:
11460*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt, op->value4));
11461*7c568831SAndroid Build Coastguard Worker break;
11462*7c568831SAndroid Build Coastguard Worker case XPATH_OP_VARIABLE:{
11463*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr val;
11464*7c568831SAndroid Build Coastguard Worker
11465*7c568831SAndroid Build Coastguard Worker if (op->ch1 != -1)
11466*7c568831SAndroid Build Coastguard Worker total +=
11467*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11468*7c568831SAndroid Build Coastguard Worker if (op->value5 == NULL) {
11469*7c568831SAndroid Build Coastguard Worker val = xmlXPathVariableLookup(ctxt->context, op->value4);
11470*7c568831SAndroid Build Coastguard Worker if (val == NULL)
11471*7c568831SAndroid Build Coastguard Worker XP_ERROR0(XPATH_UNDEF_VARIABLE_ERROR);
11472*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, val);
11473*7c568831SAndroid Build Coastguard Worker } else {
11474*7c568831SAndroid Build Coastguard Worker const xmlChar *URI;
11475*7c568831SAndroid Build Coastguard Worker
11476*7c568831SAndroid Build Coastguard Worker URI = xmlXPathNsLookup(ctxt->context, op->value5);
11477*7c568831SAndroid Build Coastguard Worker if (URI == NULL) {
11478*7c568831SAndroid Build Coastguard Worker XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
11479*7c568831SAndroid Build Coastguard Worker break;
11480*7c568831SAndroid Build Coastguard Worker }
11481*7c568831SAndroid Build Coastguard Worker val = xmlXPathVariableLookupNS(ctxt->context,
11482*7c568831SAndroid Build Coastguard Worker op->value4, URI);
11483*7c568831SAndroid Build Coastguard Worker if (val == NULL)
11484*7c568831SAndroid Build Coastguard Worker XP_ERROR0(XPATH_UNDEF_VARIABLE_ERROR);
11485*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, val);
11486*7c568831SAndroid Build Coastguard Worker }
11487*7c568831SAndroid Build Coastguard Worker break;
11488*7c568831SAndroid Build Coastguard Worker }
11489*7c568831SAndroid Build Coastguard Worker case XPATH_OP_FUNCTION:{
11490*7c568831SAndroid Build Coastguard Worker xmlXPathFunction func;
11491*7c568831SAndroid Build Coastguard Worker const xmlChar *oldFunc, *oldFuncURI;
11492*7c568831SAndroid Build Coastguard Worker int i;
11493*7c568831SAndroid Build Coastguard Worker int frame;
11494*7c568831SAndroid Build Coastguard Worker
11495*7c568831SAndroid Build Coastguard Worker frame = ctxt->valueNr;
11496*7c568831SAndroid Build Coastguard Worker if (op->ch1 != -1) {
11497*7c568831SAndroid Build Coastguard Worker total +=
11498*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11499*7c568831SAndroid Build Coastguard Worker if (ctxt->error != XPATH_EXPRESSION_OK)
11500*7c568831SAndroid Build Coastguard Worker break;
11501*7c568831SAndroid Build Coastguard Worker }
11502*7c568831SAndroid Build Coastguard Worker if (ctxt->valueNr < frame + op->value)
11503*7c568831SAndroid Build Coastguard Worker XP_ERROR0(XPATH_INVALID_OPERAND);
11504*7c568831SAndroid Build Coastguard Worker for (i = 0; i < op->value; i++) {
11505*7c568831SAndroid Build Coastguard Worker if (ctxt->valueTab[(ctxt->valueNr - 1) - i] == NULL)
11506*7c568831SAndroid Build Coastguard Worker XP_ERROR0(XPATH_INVALID_OPERAND);
11507*7c568831SAndroid Build Coastguard Worker }
11508*7c568831SAndroid Build Coastguard Worker if (op->cache != NULL)
11509*7c568831SAndroid Build Coastguard Worker func = op->cache;
11510*7c568831SAndroid Build Coastguard Worker else {
11511*7c568831SAndroid Build Coastguard Worker const xmlChar *URI = NULL;
11512*7c568831SAndroid Build Coastguard Worker
11513*7c568831SAndroid Build Coastguard Worker if (op->value5 == NULL)
11514*7c568831SAndroid Build Coastguard Worker func =
11515*7c568831SAndroid Build Coastguard Worker xmlXPathFunctionLookup(ctxt->context,
11516*7c568831SAndroid Build Coastguard Worker op->value4);
11517*7c568831SAndroid Build Coastguard Worker else {
11518*7c568831SAndroid Build Coastguard Worker URI = xmlXPathNsLookup(ctxt->context, op->value5);
11519*7c568831SAndroid Build Coastguard Worker if (URI == NULL)
11520*7c568831SAndroid Build Coastguard Worker XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
11521*7c568831SAndroid Build Coastguard Worker func = xmlXPathFunctionLookupNS(ctxt->context,
11522*7c568831SAndroid Build Coastguard Worker op->value4, URI);
11523*7c568831SAndroid Build Coastguard Worker }
11524*7c568831SAndroid Build Coastguard Worker if (func == NULL)
11525*7c568831SAndroid Build Coastguard Worker XP_ERROR0(XPATH_UNKNOWN_FUNC_ERROR);
11526*7c568831SAndroid Build Coastguard Worker op->cache = func;
11527*7c568831SAndroid Build Coastguard Worker op->cacheURI = (void *) URI;
11528*7c568831SAndroid Build Coastguard Worker }
11529*7c568831SAndroid Build Coastguard Worker oldFunc = ctxt->context->function;
11530*7c568831SAndroid Build Coastguard Worker oldFuncURI = ctxt->context->functionURI;
11531*7c568831SAndroid Build Coastguard Worker ctxt->context->function = op->value4;
11532*7c568831SAndroid Build Coastguard Worker ctxt->context->functionURI = op->cacheURI;
11533*7c568831SAndroid Build Coastguard Worker func(ctxt, op->value);
11534*7c568831SAndroid Build Coastguard Worker ctxt->context->function = oldFunc;
11535*7c568831SAndroid Build Coastguard Worker ctxt->context->functionURI = oldFuncURI;
11536*7c568831SAndroid Build Coastguard Worker if ((ctxt->error == XPATH_EXPRESSION_OK) &&
11537*7c568831SAndroid Build Coastguard Worker (ctxt->valueNr != frame + 1))
11538*7c568831SAndroid Build Coastguard Worker XP_ERROR0(XPATH_STACK_ERROR);
11539*7c568831SAndroid Build Coastguard Worker break;
11540*7c568831SAndroid Build Coastguard Worker }
11541*7c568831SAndroid Build Coastguard Worker case XPATH_OP_ARG:
11542*7c568831SAndroid Build Coastguard Worker if (op->ch1 != -1) {
11543*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11544*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11545*7c568831SAndroid Build Coastguard Worker }
11546*7c568831SAndroid Build Coastguard Worker if (op->ch2 != -1) {
11547*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11548*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11549*7c568831SAndroid Build Coastguard Worker }
11550*7c568831SAndroid Build Coastguard Worker break;
11551*7c568831SAndroid Build Coastguard Worker case XPATH_OP_PREDICATE:
11552*7c568831SAndroid Build Coastguard Worker case XPATH_OP_FILTER:{
11553*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr obj;
11554*7c568831SAndroid Build Coastguard Worker xmlNodeSetPtr set;
11555*7c568831SAndroid Build Coastguard Worker
11556*7c568831SAndroid Build Coastguard Worker /*
11557*7c568831SAndroid Build Coastguard Worker * Optimization for ()[1] selection i.e. the first elem
11558*7c568831SAndroid Build Coastguard Worker */
11559*7c568831SAndroid Build Coastguard Worker if ((op->ch1 != -1) && (op->ch2 != -1) &&
11560*7c568831SAndroid Build Coastguard Worker #ifdef XP_OPTIMIZED_FILTER_FIRST
11561*7c568831SAndroid Build Coastguard Worker /*
11562*7c568831SAndroid Build Coastguard Worker * FILTER TODO: Can we assume that the inner processing
11563*7c568831SAndroid Build Coastguard Worker * will result in an ordered list if we have an
11564*7c568831SAndroid Build Coastguard Worker * XPATH_OP_FILTER?
11565*7c568831SAndroid Build Coastguard Worker * What about an additional field or flag on
11566*7c568831SAndroid Build Coastguard Worker * xmlXPathObject like @sorted ? This way we wouldn't need
11567*7c568831SAndroid Build Coastguard Worker * to assume anything, so it would be more robust and
11568*7c568831SAndroid Build Coastguard Worker * easier to optimize.
11569*7c568831SAndroid Build Coastguard Worker */
11570*7c568831SAndroid Build Coastguard Worker ((comp->steps[op->ch1].op == XPATH_OP_SORT) || /* 18 */
11571*7c568831SAndroid Build Coastguard Worker (comp->steps[op->ch1].op == XPATH_OP_FILTER)) && /* 17 */
11572*7c568831SAndroid Build Coastguard Worker #else
11573*7c568831SAndroid Build Coastguard Worker (comp->steps[op->ch1].op == XPATH_OP_SORT) &&
11574*7c568831SAndroid Build Coastguard Worker #endif
11575*7c568831SAndroid Build Coastguard Worker (comp->steps[op->ch2].op == XPATH_OP_VALUE)) { /* 12 */
11576*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr val;
11577*7c568831SAndroid Build Coastguard Worker
11578*7c568831SAndroid Build Coastguard Worker val = comp->steps[op->ch2].value4;
11579*7c568831SAndroid Build Coastguard Worker if ((val != NULL) && (val->type == XPATH_NUMBER) &&
11580*7c568831SAndroid Build Coastguard Worker (val->floatval == 1.0)) {
11581*7c568831SAndroid Build Coastguard Worker xmlNodePtr first = NULL;
11582*7c568831SAndroid Build Coastguard Worker
11583*7c568831SAndroid Build Coastguard Worker total +=
11584*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalFirst(ctxt,
11585*7c568831SAndroid Build Coastguard Worker &comp->steps[op->ch1],
11586*7c568831SAndroid Build Coastguard Worker &first);
11587*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11588*7c568831SAndroid Build Coastguard Worker /*
11589*7c568831SAndroid Build Coastguard Worker * The nodeset should be in document order,
11590*7c568831SAndroid Build Coastguard Worker * Keep only the first value
11591*7c568831SAndroid Build Coastguard Worker */
11592*7c568831SAndroid Build Coastguard Worker if ((ctxt->value != NULL) &&
11593*7c568831SAndroid Build Coastguard Worker (ctxt->value->type == XPATH_NODESET) &&
11594*7c568831SAndroid Build Coastguard Worker (ctxt->value->nodesetval != NULL) &&
11595*7c568831SAndroid Build Coastguard Worker (ctxt->value->nodesetval->nodeNr > 1))
11596*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetClearFromPos(ctxt->value->nodesetval,
11597*7c568831SAndroid Build Coastguard Worker 1, 1);
11598*7c568831SAndroid Build Coastguard Worker break;
11599*7c568831SAndroid Build Coastguard Worker }
11600*7c568831SAndroid Build Coastguard Worker }
11601*7c568831SAndroid Build Coastguard Worker /*
11602*7c568831SAndroid Build Coastguard Worker * Optimization for ()[last()] selection i.e. the last elem
11603*7c568831SAndroid Build Coastguard Worker */
11604*7c568831SAndroid Build Coastguard Worker if ((op->ch1 != -1) && (op->ch2 != -1) &&
11605*7c568831SAndroid Build Coastguard Worker (comp->steps[op->ch1].op == XPATH_OP_SORT) &&
11606*7c568831SAndroid Build Coastguard Worker (comp->steps[op->ch2].op == XPATH_OP_SORT)) {
11607*7c568831SAndroid Build Coastguard Worker int f = comp->steps[op->ch2].ch1;
11608*7c568831SAndroid Build Coastguard Worker
11609*7c568831SAndroid Build Coastguard Worker if ((f != -1) &&
11610*7c568831SAndroid Build Coastguard Worker (comp->steps[f].op == XPATH_OP_FUNCTION) &&
11611*7c568831SAndroid Build Coastguard Worker (comp->steps[f].value5 == NULL) &&
11612*7c568831SAndroid Build Coastguard Worker (comp->steps[f].value == 0) &&
11613*7c568831SAndroid Build Coastguard Worker (comp->steps[f].value4 != NULL) &&
11614*7c568831SAndroid Build Coastguard Worker (xmlStrEqual
11615*7c568831SAndroid Build Coastguard Worker (comp->steps[f].value4, BAD_CAST "last"))) {
11616*7c568831SAndroid Build Coastguard Worker xmlNodePtr last = NULL;
11617*7c568831SAndroid Build Coastguard Worker
11618*7c568831SAndroid Build Coastguard Worker total +=
11619*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalLast(ctxt,
11620*7c568831SAndroid Build Coastguard Worker &comp->steps[op->ch1],
11621*7c568831SAndroid Build Coastguard Worker &last);
11622*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11623*7c568831SAndroid Build Coastguard Worker /*
11624*7c568831SAndroid Build Coastguard Worker * The nodeset should be in document order,
11625*7c568831SAndroid Build Coastguard Worker * Keep only the last value
11626*7c568831SAndroid Build Coastguard Worker */
11627*7c568831SAndroid Build Coastguard Worker if ((ctxt->value != NULL) &&
11628*7c568831SAndroid Build Coastguard Worker (ctxt->value->type == XPATH_NODESET) &&
11629*7c568831SAndroid Build Coastguard Worker (ctxt->value->nodesetval != NULL) &&
11630*7c568831SAndroid Build Coastguard Worker (ctxt->value->nodesetval->nodeTab != NULL) &&
11631*7c568831SAndroid Build Coastguard Worker (ctxt->value->nodesetval->nodeNr > 1))
11632*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetKeepLast(ctxt->value->nodesetval);
11633*7c568831SAndroid Build Coastguard Worker break;
11634*7c568831SAndroid Build Coastguard Worker }
11635*7c568831SAndroid Build Coastguard Worker }
11636*7c568831SAndroid Build Coastguard Worker /*
11637*7c568831SAndroid Build Coastguard Worker * Process inner predicates first.
11638*7c568831SAndroid Build Coastguard Worker * Example "index[parent::book][1]":
11639*7c568831SAndroid Build Coastguard Worker * ...
11640*7c568831SAndroid Build Coastguard Worker * PREDICATE <-- we are here "[1]"
11641*7c568831SAndroid Build Coastguard Worker * PREDICATE <-- process "[parent::book]" first
11642*7c568831SAndroid Build Coastguard Worker * SORT
11643*7c568831SAndroid Build Coastguard Worker * COLLECT 'parent' 'name' 'node' book
11644*7c568831SAndroid Build Coastguard Worker * NODE
11645*7c568831SAndroid Build Coastguard Worker * ELEM Object is a number : 1
11646*7c568831SAndroid Build Coastguard Worker */
11647*7c568831SAndroid Build Coastguard Worker if (op->ch1 != -1)
11648*7c568831SAndroid Build Coastguard Worker total +=
11649*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11650*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11651*7c568831SAndroid Build Coastguard Worker if (op->ch2 == -1)
11652*7c568831SAndroid Build Coastguard Worker break;
11653*7c568831SAndroid Build Coastguard Worker if (ctxt->value == NULL)
11654*7c568831SAndroid Build Coastguard Worker break;
11655*7c568831SAndroid Build Coastguard Worker
11656*7c568831SAndroid Build Coastguard Worker /*
11657*7c568831SAndroid Build Coastguard Worker * In case of errors, xmlXPathNodeSetFilter can pop additional
11658*7c568831SAndroid Build Coastguard Worker * nodes from the stack. We have to temporarily remove the
11659*7c568831SAndroid Build Coastguard Worker * nodeset object from the stack to avoid freeing it
11660*7c568831SAndroid Build Coastguard Worker * prematurely.
11661*7c568831SAndroid Build Coastguard Worker */
11662*7c568831SAndroid Build Coastguard Worker CHECK_TYPE0(XPATH_NODESET);
11663*7c568831SAndroid Build Coastguard Worker obj = valuePop(ctxt);
11664*7c568831SAndroid Build Coastguard Worker set = obj->nodesetval;
11665*7c568831SAndroid Build Coastguard Worker if (set != NULL)
11666*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetFilter(ctxt, set, op->ch2,
11667*7c568831SAndroid Build Coastguard Worker 1, set->nodeNr, 1);
11668*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, obj);
11669*7c568831SAndroid Build Coastguard Worker break;
11670*7c568831SAndroid Build Coastguard Worker }
11671*7c568831SAndroid Build Coastguard Worker case XPATH_OP_SORT:
11672*7c568831SAndroid Build Coastguard Worker if (op->ch1 != -1)
11673*7c568831SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11674*7c568831SAndroid Build Coastguard Worker CHECK_ERROR0;
11675*7c568831SAndroid Build Coastguard Worker if ((ctxt->value != NULL) &&
11676*7c568831SAndroid Build Coastguard Worker (ctxt->value->type == XPATH_NODESET) &&
11677*7c568831SAndroid Build Coastguard Worker (ctxt->value->nodesetval != NULL) &&
11678*7c568831SAndroid Build Coastguard Worker (ctxt->value->nodesetval->nodeNr > 1))
11679*7c568831SAndroid Build Coastguard Worker {
11680*7c568831SAndroid Build Coastguard Worker xmlXPathNodeSetSort(ctxt->value->nodesetval);
11681*7c568831SAndroid Build Coastguard Worker }
11682*7c568831SAndroid Build Coastguard Worker break;
11683*7c568831SAndroid Build Coastguard Worker default:
11684*7c568831SAndroid Build Coastguard Worker XP_ERROR0(XPATH_INVALID_OPERAND);
11685*7c568831SAndroid Build Coastguard Worker break;
11686*7c568831SAndroid Build Coastguard Worker }
11687*7c568831SAndroid Build Coastguard Worker
11688*7c568831SAndroid Build Coastguard Worker ctxt->context->depth -= 1;
11689*7c568831SAndroid Build Coastguard Worker return (total);
11690*7c568831SAndroid Build Coastguard Worker }
11691*7c568831SAndroid Build Coastguard Worker
11692*7c568831SAndroid Build Coastguard Worker /**
11693*7c568831SAndroid Build Coastguard Worker * xmlXPathCompOpEvalToBoolean:
11694*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath parser context
11695*7c568831SAndroid Build Coastguard Worker *
11696*7c568831SAndroid Build Coastguard Worker * Evaluates if the expression evaluates to true.
11697*7c568831SAndroid Build Coastguard Worker *
11698*7c568831SAndroid Build Coastguard Worker * Returns 1 if true, 0 if false and -1 on API or internal errors.
11699*7c568831SAndroid Build Coastguard Worker */
11700*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCompOpEvalToBoolean(xmlXPathParserContextPtr ctxt,xmlXPathStepOpPtr op,int isPredicate)11701*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEvalToBoolean(xmlXPathParserContextPtr ctxt,
11702*7c568831SAndroid Build Coastguard Worker xmlXPathStepOpPtr op,
11703*7c568831SAndroid Build Coastguard Worker int isPredicate)
11704*7c568831SAndroid Build Coastguard Worker {
11705*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr resObj = NULL;
11706*7c568831SAndroid Build Coastguard Worker
11707*7c568831SAndroid Build Coastguard Worker start:
11708*7c568831SAndroid Build Coastguard Worker if (OP_LIMIT_EXCEEDED(ctxt, 1))
11709*7c568831SAndroid Build Coastguard Worker return(0);
11710*7c568831SAndroid Build Coastguard Worker /* comp = ctxt->comp; */
11711*7c568831SAndroid Build Coastguard Worker switch (op->op) {
11712*7c568831SAndroid Build Coastguard Worker case XPATH_OP_END:
11713*7c568831SAndroid Build Coastguard Worker return (0);
11714*7c568831SAndroid Build Coastguard Worker case XPATH_OP_VALUE:
11715*7c568831SAndroid Build Coastguard Worker resObj = (xmlXPathObjectPtr) op->value4;
11716*7c568831SAndroid Build Coastguard Worker if (isPredicate)
11717*7c568831SAndroid Build Coastguard Worker return(xmlXPathEvaluatePredicateResult(ctxt, resObj));
11718*7c568831SAndroid Build Coastguard Worker return(xmlXPathCastToBoolean(resObj));
11719*7c568831SAndroid Build Coastguard Worker case XPATH_OP_SORT:
11720*7c568831SAndroid Build Coastguard Worker /*
11721*7c568831SAndroid Build Coastguard Worker * We don't need sorting for boolean results. Skip this one.
11722*7c568831SAndroid Build Coastguard Worker */
11723*7c568831SAndroid Build Coastguard Worker if (op->ch1 != -1) {
11724*7c568831SAndroid Build Coastguard Worker op = &ctxt->comp->steps[op->ch1];
11725*7c568831SAndroid Build Coastguard Worker goto start;
11726*7c568831SAndroid Build Coastguard Worker }
11727*7c568831SAndroid Build Coastguard Worker return(0);
11728*7c568831SAndroid Build Coastguard Worker case XPATH_OP_COLLECT:
11729*7c568831SAndroid Build Coastguard Worker if (op->ch1 == -1)
11730*7c568831SAndroid Build Coastguard Worker return(0);
11731*7c568831SAndroid Build Coastguard Worker
11732*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEval(ctxt, &ctxt->comp->steps[op->ch1]);
11733*7c568831SAndroid Build Coastguard Worker if (ctxt->error != XPATH_EXPRESSION_OK)
11734*7c568831SAndroid Build Coastguard Worker return(-1);
11735*7c568831SAndroid Build Coastguard Worker
11736*7c568831SAndroid Build Coastguard Worker xmlXPathNodeCollectAndTest(ctxt, op, NULL, NULL, 1);
11737*7c568831SAndroid Build Coastguard Worker if (ctxt->error != XPATH_EXPRESSION_OK)
11738*7c568831SAndroid Build Coastguard Worker return(-1);
11739*7c568831SAndroid Build Coastguard Worker
11740*7c568831SAndroid Build Coastguard Worker resObj = valuePop(ctxt);
11741*7c568831SAndroid Build Coastguard Worker if (resObj == NULL)
11742*7c568831SAndroid Build Coastguard Worker return(-1);
11743*7c568831SAndroid Build Coastguard Worker break;
11744*7c568831SAndroid Build Coastguard Worker default:
11745*7c568831SAndroid Build Coastguard Worker /*
11746*7c568831SAndroid Build Coastguard Worker * Fallback to call xmlXPathCompOpEval().
11747*7c568831SAndroid Build Coastguard Worker */
11748*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEval(ctxt, op);
11749*7c568831SAndroid Build Coastguard Worker if (ctxt->error != XPATH_EXPRESSION_OK)
11750*7c568831SAndroid Build Coastguard Worker return(-1);
11751*7c568831SAndroid Build Coastguard Worker
11752*7c568831SAndroid Build Coastguard Worker resObj = valuePop(ctxt);
11753*7c568831SAndroid Build Coastguard Worker if (resObj == NULL)
11754*7c568831SAndroid Build Coastguard Worker return(-1);
11755*7c568831SAndroid Build Coastguard Worker break;
11756*7c568831SAndroid Build Coastguard Worker }
11757*7c568831SAndroid Build Coastguard Worker
11758*7c568831SAndroid Build Coastguard Worker if (resObj) {
11759*7c568831SAndroid Build Coastguard Worker int res;
11760*7c568831SAndroid Build Coastguard Worker
11761*7c568831SAndroid Build Coastguard Worker if (resObj->type == XPATH_BOOLEAN) {
11762*7c568831SAndroid Build Coastguard Worker res = resObj->boolval;
11763*7c568831SAndroid Build Coastguard Worker } else if (isPredicate) {
11764*7c568831SAndroid Build Coastguard Worker /*
11765*7c568831SAndroid Build Coastguard Worker * For predicates a result of type "number" is handled
11766*7c568831SAndroid Build Coastguard Worker * differently:
11767*7c568831SAndroid Build Coastguard Worker * SPEC XPath 1.0:
11768*7c568831SAndroid Build Coastguard Worker * "If the result is a number, the result will be converted
11769*7c568831SAndroid Build Coastguard Worker * to true if the number is equal to the context position
11770*7c568831SAndroid Build Coastguard Worker * and will be converted to false otherwise;"
11771*7c568831SAndroid Build Coastguard Worker */
11772*7c568831SAndroid Build Coastguard Worker res = xmlXPathEvaluatePredicateResult(ctxt, resObj);
11773*7c568831SAndroid Build Coastguard Worker } else {
11774*7c568831SAndroid Build Coastguard Worker res = xmlXPathCastToBoolean(resObj);
11775*7c568831SAndroid Build Coastguard Worker }
11776*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, resObj);
11777*7c568831SAndroid Build Coastguard Worker return(res);
11778*7c568831SAndroid Build Coastguard Worker }
11779*7c568831SAndroid Build Coastguard Worker
11780*7c568831SAndroid Build Coastguard Worker return(0);
11781*7c568831SAndroid Build Coastguard Worker }
11782*7c568831SAndroid Build Coastguard Worker
11783*7c568831SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
11784*7c568831SAndroid Build Coastguard Worker /**
11785*7c568831SAndroid Build Coastguard Worker * xmlXPathRunStreamEval:
11786*7c568831SAndroid Build Coastguard Worker * @pctxt: the XPath parser context with the compiled expression
11787*7c568831SAndroid Build Coastguard Worker *
11788*7c568831SAndroid Build Coastguard Worker * Evaluate the Precompiled Streamable XPath expression in the given context.
11789*7c568831SAndroid Build Coastguard Worker */
11790*7c568831SAndroid Build Coastguard Worker static int
xmlXPathRunStreamEval(xmlXPathParserContextPtr pctxt,xmlPatternPtr comp,xmlXPathObjectPtr * resultSeq,int toBool)11791*7c568831SAndroid Build Coastguard Worker xmlXPathRunStreamEval(xmlXPathParserContextPtr pctxt, xmlPatternPtr comp,
11792*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr *resultSeq, int toBool)
11793*7c568831SAndroid Build Coastguard Worker {
11794*7c568831SAndroid Build Coastguard Worker int max_depth, min_depth;
11795*7c568831SAndroid Build Coastguard Worker int from_root;
11796*7c568831SAndroid Build Coastguard Worker int ret, depth;
11797*7c568831SAndroid Build Coastguard Worker int eval_all_nodes;
11798*7c568831SAndroid Build Coastguard Worker xmlNodePtr cur = NULL, limit = NULL;
11799*7c568831SAndroid Build Coastguard Worker xmlStreamCtxtPtr patstream = NULL;
11800*7c568831SAndroid Build Coastguard Worker xmlXPathContextPtr ctxt = pctxt->context;
11801*7c568831SAndroid Build Coastguard Worker
11802*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (comp == NULL))
11803*7c568831SAndroid Build Coastguard Worker return(-1);
11804*7c568831SAndroid Build Coastguard Worker max_depth = xmlPatternMaxDepth(comp);
11805*7c568831SAndroid Build Coastguard Worker if (max_depth == -1)
11806*7c568831SAndroid Build Coastguard Worker return(-1);
11807*7c568831SAndroid Build Coastguard Worker if (max_depth == -2)
11808*7c568831SAndroid Build Coastguard Worker max_depth = 10000;
11809*7c568831SAndroid Build Coastguard Worker min_depth = xmlPatternMinDepth(comp);
11810*7c568831SAndroid Build Coastguard Worker if (min_depth == -1)
11811*7c568831SAndroid Build Coastguard Worker return(-1);
11812*7c568831SAndroid Build Coastguard Worker from_root = xmlPatternFromRoot(comp);
11813*7c568831SAndroid Build Coastguard Worker if (from_root < 0)
11814*7c568831SAndroid Build Coastguard Worker return(-1);
11815*7c568831SAndroid Build Coastguard Worker
11816*7c568831SAndroid Build Coastguard Worker if (! toBool) {
11817*7c568831SAndroid Build Coastguard Worker if (resultSeq == NULL)
11818*7c568831SAndroid Build Coastguard Worker return(-1);
11819*7c568831SAndroid Build Coastguard Worker *resultSeq = xmlXPathCacheNewNodeSet(pctxt, NULL);
11820*7c568831SAndroid Build Coastguard Worker if (*resultSeq == NULL)
11821*7c568831SAndroid Build Coastguard Worker return(-1);
11822*7c568831SAndroid Build Coastguard Worker }
11823*7c568831SAndroid Build Coastguard Worker
11824*7c568831SAndroid Build Coastguard Worker /*
11825*7c568831SAndroid Build Coastguard Worker * handle the special cases of "/" amd "." being matched
11826*7c568831SAndroid Build Coastguard Worker */
11827*7c568831SAndroid Build Coastguard Worker if (min_depth == 0) {
11828*7c568831SAndroid Build Coastguard Worker int res;
11829*7c568831SAndroid Build Coastguard Worker
11830*7c568831SAndroid Build Coastguard Worker if (from_root) {
11831*7c568831SAndroid Build Coastguard Worker /* Select "/" */
11832*7c568831SAndroid Build Coastguard Worker if (toBool)
11833*7c568831SAndroid Build Coastguard Worker return(1);
11834*7c568831SAndroid Build Coastguard Worker res = xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval,
11835*7c568831SAndroid Build Coastguard Worker (xmlNodePtr) ctxt->doc);
11836*7c568831SAndroid Build Coastguard Worker } else {
11837*7c568831SAndroid Build Coastguard Worker /* Select "self::node()" */
11838*7c568831SAndroid Build Coastguard Worker if (toBool)
11839*7c568831SAndroid Build Coastguard Worker return(1);
11840*7c568831SAndroid Build Coastguard Worker res = xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval,
11841*7c568831SAndroid Build Coastguard Worker ctxt->node);
11842*7c568831SAndroid Build Coastguard Worker }
11843*7c568831SAndroid Build Coastguard Worker
11844*7c568831SAndroid Build Coastguard Worker if (res < 0)
11845*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
11846*7c568831SAndroid Build Coastguard Worker }
11847*7c568831SAndroid Build Coastguard Worker if (max_depth == 0) {
11848*7c568831SAndroid Build Coastguard Worker return(0);
11849*7c568831SAndroid Build Coastguard Worker }
11850*7c568831SAndroid Build Coastguard Worker
11851*7c568831SAndroid Build Coastguard Worker if (from_root) {
11852*7c568831SAndroid Build Coastguard Worker cur = (xmlNodePtr)ctxt->doc;
11853*7c568831SAndroid Build Coastguard Worker } else if (ctxt->node != NULL) {
11854*7c568831SAndroid Build Coastguard Worker switch (ctxt->node->type) {
11855*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
11856*7c568831SAndroid Build Coastguard Worker case XML_DOCUMENT_NODE:
11857*7c568831SAndroid Build Coastguard Worker case XML_DOCUMENT_FRAG_NODE:
11858*7c568831SAndroid Build Coastguard Worker case XML_HTML_DOCUMENT_NODE:
11859*7c568831SAndroid Build Coastguard Worker cur = ctxt->node;
11860*7c568831SAndroid Build Coastguard Worker break;
11861*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE:
11862*7c568831SAndroid Build Coastguard Worker case XML_TEXT_NODE:
11863*7c568831SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
11864*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_REF_NODE:
11865*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_NODE:
11866*7c568831SAndroid Build Coastguard Worker case XML_PI_NODE:
11867*7c568831SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
11868*7c568831SAndroid Build Coastguard Worker case XML_NOTATION_NODE:
11869*7c568831SAndroid Build Coastguard Worker case XML_DTD_NODE:
11870*7c568831SAndroid Build Coastguard Worker case XML_DOCUMENT_TYPE_NODE:
11871*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_DECL:
11872*7c568831SAndroid Build Coastguard Worker case XML_ATTRIBUTE_DECL:
11873*7c568831SAndroid Build Coastguard Worker case XML_ENTITY_DECL:
11874*7c568831SAndroid Build Coastguard Worker case XML_NAMESPACE_DECL:
11875*7c568831SAndroid Build Coastguard Worker case XML_XINCLUDE_START:
11876*7c568831SAndroid Build Coastguard Worker case XML_XINCLUDE_END:
11877*7c568831SAndroid Build Coastguard Worker break;
11878*7c568831SAndroid Build Coastguard Worker }
11879*7c568831SAndroid Build Coastguard Worker limit = cur;
11880*7c568831SAndroid Build Coastguard Worker }
11881*7c568831SAndroid Build Coastguard Worker if (cur == NULL) {
11882*7c568831SAndroid Build Coastguard Worker return(0);
11883*7c568831SAndroid Build Coastguard Worker }
11884*7c568831SAndroid Build Coastguard Worker
11885*7c568831SAndroid Build Coastguard Worker patstream = xmlPatternGetStreamCtxt(comp);
11886*7c568831SAndroid Build Coastguard Worker if (patstream == NULL) {
11887*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
11888*7c568831SAndroid Build Coastguard Worker return(-1);
11889*7c568831SAndroid Build Coastguard Worker }
11890*7c568831SAndroid Build Coastguard Worker
11891*7c568831SAndroid Build Coastguard Worker eval_all_nodes = xmlStreamWantsAnyNode(patstream);
11892*7c568831SAndroid Build Coastguard Worker
11893*7c568831SAndroid Build Coastguard Worker if (from_root) {
11894*7c568831SAndroid Build Coastguard Worker ret = xmlStreamPush(patstream, NULL, NULL);
11895*7c568831SAndroid Build Coastguard Worker if (ret < 0) {
11896*7c568831SAndroid Build Coastguard Worker } else if (ret == 1) {
11897*7c568831SAndroid Build Coastguard Worker if (toBool)
11898*7c568831SAndroid Build Coastguard Worker goto return_1;
11899*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, cur) < 0)
11900*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
11901*7c568831SAndroid Build Coastguard Worker }
11902*7c568831SAndroid Build Coastguard Worker }
11903*7c568831SAndroid Build Coastguard Worker depth = 0;
11904*7c568831SAndroid Build Coastguard Worker goto scan_children;
11905*7c568831SAndroid Build Coastguard Worker next_node:
11906*7c568831SAndroid Build Coastguard Worker do {
11907*7c568831SAndroid Build Coastguard Worker if (ctxt->opLimit != 0) {
11908*7c568831SAndroid Build Coastguard Worker if (ctxt->opCount >= ctxt->opLimit) {
11909*7c568831SAndroid Build Coastguard Worker xmlXPathErr(ctxt, XPATH_RECURSION_LIMIT_EXCEEDED);
11910*7c568831SAndroid Build Coastguard Worker xmlFreeStreamCtxt(patstream);
11911*7c568831SAndroid Build Coastguard Worker return(-1);
11912*7c568831SAndroid Build Coastguard Worker }
11913*7c568831SAndroid Build Coastguard Worker ctxt->opCount++;
11914*7c568831SAndroid Build Coastguard Worker }
11915*7c568831SAndroid Build Coastguard Worker
11916*7c568831SAndroid Build Coastguard Worker switch (cur->type) {
11917*7c568831SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
11918*7c568831SAndroid Build Coastguard Worker case XML_TEXT_NODE:
11919*7c568831SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
11920*7c568831SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
11921*7c568831SAndroid Build Coastguard Worker case XML_PI_NODE:
11922*7c568831SAndroid Build Coastguard Worker if (cur->type == XML_ELEMENT_NODE) {
11923*7c568831SAndroid Build Coastguard Worker ret = xmlStreamPush(patstream, cur->name,
11924*7c568831SAndroid Build Coastguard Worker (cur->ns ? cur->ns->href : NULL));
11925*7c568831SAndroid Build Coastguard Worker } else if (eval_all_nodes)
11926*7c568831SAndroid Build Coastguard Worker ret = xmlStreamPushNode(patstream, NULL, NULL, cur->type);
11927*7c568831SAndroid Build Coastguard Worker else
11928*7c568831SAndroid Build Coastguard Worker break;
11929*7c568831SAndroid Build Coastguard Worker
11930*7c568831SAndroid Build Coastguard Worker if (ret < 0) {
11931*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
11932*7c568831SAndroid Build Coastguard Worker } else if (ret == 1) {
11933*7c568831SAndroid Build Coastguard Worker if (toBool)
11934*7c568831SAndroid Build Coastguard Worker goto return_1;
11935*7c568831SAndroid Build Coastguard Worker if (xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval,
11936*7c568831SAndroid Build Coastguard Worker cur) < 0)
11937*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
11938*7c568831SAndroid Build Coastguard Worker }
11939*7c568831SAndroid Build Coastguard Worker if ((cur->children == NULL) || (depth >= max_depth)) {
11940*7c568831SAndroid Build Coastguard Worker ret = xmlStreamPop(patstream);
11941*7c568831SAndroid Build Coastguard Worker while (cur->next != NULL) {
11942*7c568831SAndroid Build Coastguard Worker cur = cur->next;
11943*7c568831SAndroid Build Coastguard Worker if ((cur->type != XML_ENTITY_DECL) &&
11944*7c568831SAndroid Build Coastguard Worker (cur->type != XML_DTD_NODE))
11945*7c568831SAndroid Build Coastguard Worker goto next_node;
11946*7c568831SAndroid Build Coastguard Worker }
11947*7c568831SAndroid Build Coastguard Worker }
11948*7c568831SAndroid Build Coastguard Worker default:
11949*7c568831SAndroid Build Coastguard Worker break;
11950*7c568831SAndroid Build Coastguard Worker }
11951*7c568831SAndroid Build Coastguard Worker
11952*7c568831SAndroid Build Coastguard Worker scan_children:
11953*7c568831SAndroid Build Coastguard Worker if (cur->type == XML_NAMESPACE_DECL) break;
11954*7c568831SAndroid Build Coastguard Worker if ((cur->children != NULL) && (depth < max_depth)) {
11955*7c568831SAndroid Build Coastguard Worker /*
11956*7c568831SAndroid Build Coastguard Worker * Do not descend on entities declarations
11957*7c568831SAndroid Build Coastguard Worker */
11958*7c568831SAndroid Build Coastguard Worker if (cur->children->type != XML_ENTITY_DECL) {
11959*7c568831SAndroid Build Coastguard Worker cur = cur->children;
11960*7c568831SAndroid Build Coastguard Worker depth++;
11961*7c568831SAndroid Build Coastguard Worker /*
11962*7c568831SAndroid Build Coastguard Worker * Skip DTDs
11963*7c568831SAndroid Build Coastguard Worker */
11964*7c568831SAndroid Build Coastguard Worker if (cur->type != XML_DTD_NODE)
11965*7c568831SAndroid Build Coastguard Worker continue;
11966*7c568831SAndroid Build Coastguard Worker }
11967*7c568831SAndroid Build Coastguard Worker }
11968*7c568831SAndroid Build Coastguard Worker
11969*7c568831SAndroid Build Coastguard Worker if (cur == limit)
11970*7c568831SAndroid Build Coastguard Worker break;
11971*7c568831SAndroid Build Coastguard Worker
11972*7c568831SAndroid Build Coastguard Worker while (cur->next != NULL) {
11973*7c568831SAndroid Build Coastguard Worker cur = cur->next;
11974*7c568831SAndroid Build Coastguard Worker if ((cur->type != XML_ENTITY_DECL) &&
11975*7c568831SAndroid Build Coastguard Worker (cur->type != XML_DTD_NODE))
11976*7c568831SAndroid Build Coastguard Worker goto next_node;
11977*7c568831SAndroid Build Coastguard Worker }
11978*7c568831SAndroid Build Coastguard Worker
11979*7c568831SAndroid Build Coastguard Worker do {
11980*7c568831SAndroid Build Coastguard Worker cur = cur->parent;
11981*7c568831SAndroid Build Coastguard Worker depth--;
11982*7c568831SAndroid Build Coastguard Worker if ((cur == NULL) || (cur == limit) ||
11983*7c568831SAndroid Build Coastguard Worker (cur->type == XML_DOCUMENT_NODE))
11984*7c568831SAndroid Build Coastguard Worker goto done;
11985*7c568831SAndroid Build Coastguard Worker if (cur->type == XML_ELEMENT_NODE) {
11986*7c568831SAndroid Build Coastguard Worker ret = xmlStreamPop(patstream);
11987*7c568831SAndroid Build Coastguard Worker } else if ((eval_all_nodes) &&
11988*7c568831SAndroid Build Coastguard Worker ((cur->type == XML_TEXT_NODE) ||
11989*7c568831SAndroid Build Coastguard Worker (cur->type == XML_CDATA_SECTION_NODE) ||
11990*7c568831SAndroid Build Coastguard Worker (cur->type == XML_COMMENT_NODE) ||
11991*7c568831SAndroid Build Coastguard Worker (cur->type == XML_PI_NODE)))
11992*7c568831SAndroid Build Coastguard Worker {
11993*7c568831SAndroid Build Coastguard Worker ret = xmlStreamPop(patstream);
11994*7c568831SAndroid Build Coastguard Worker }
11995*7c568831SAndroid Build Coastguard Worker if (cur->next != NULL) {
11996*7c568831SAndroid Build Coastguard Worker cur = cur->next;
11997*7c568831SAndroid Build Coastguard Worker break;
11998*7c568831SAndroid Build Coastguard Worker }
11999*7c568831SAndroid Build Coastguard Worker } while (cur != NULL);
12000*7c568831SAndroid Build Coastguard Worker
12001*7c568831SAndroid Build Coastguard Worker } while ((cur != NULL) && (depth >= 0));
12002*7c568831SAndroid Build Coastguard Worker
12003*7c568831SAndroid Build Coastguard Worker done:
12004*7c568831SAndroid Build Coastguard Worker
12005*7c568831SAndroid Build Coastguard Worker if (patstream)
12006*7c568831SAndroid Build Coastguard Worker xmlFreeStreamCtxt(patstream);
12007*7c568831SAndroid Build Coastguard Worker return(0);
12008*7c568831SAndroid Build Coastguard Worker
12009*7c568831SAndroid Build Coastguard Worker return_1:
12010*7c568831SAndroid Build Coastguard Worker if (patstream)
12011*7c568831SAndroid Build Coastguard Worker xmlFreeStreamCtxt(patstream);
12012*7c568831SAndroid Build Coastguard Worker return(1);
12013*7c568831SAndroid Build Coastguard Worker }
12014*7c568831SAndroid Build Coastguard Worker #endif /* XPATH_STREAMING */
12015*7c568831SAndroid Build Coastguard Worker
12016*7c568831SAndroid Build Coastguard Worker /**
12017*7c568831SAndroid Build Coastguard Worker * xmlXPathRunEval:
12018*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath parser context with the compiled expression
12019*7c568831SAndroid Build Coastguard Worker * @toBool: evaluate to a boolean result
12020*7c568831SAndroid Build Coastguard Worker *
12021*7c568831SAndroid Build Coastguard Worker * Evaluate the Precompiled XPath expression in the given context.
12022*7c568831SAndroid Build Coastguard Worker */
12023*7c568831SAndroid Build Coastguard Worker static int
xmlXPathRunEval(xmlXPathParserContextPtr ctxt,int toBool)12024*7c568831SAndroid Build Coastguard Worker xmlXPathRunEval(xmlXPathParserContextPtr ctxt, int toBool)
12025*7c568831SAndroid Build Coastguard Worker {
12026*7c568831SAndroid Build Coastguard Worker xmlXPathCompExprPtr comp;
12027*7c568831SAndroid Build Coastguard Worker int oldDepth;
12028*7c568831SAndroid Build Coastguard Worker
12029*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->comp == NULL))
12030*7c568831SAndroid Build Coastguard Worker return(-1);
12031*7c568831SAndroid Build Coastguard Worker
12032*7c568831SAndroid Build Coastguard Worker if (ctxt->valueTab == NULL) {
12033*7c568831SAndroid Build Coastguard Worker /* Allocate the value stack */
12034*7c568831SAndroid Build Coastguard Worker ctxt->valueTab = (xmlXPathObjectPtr *)
12035*7c568831SAndroid Build Coastguard Worker xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
12036*7c568831SAndroid Build Coastguard Worker if (ctxt->valueTab == NULL) {
12037*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
12038*7c568831SAndroid Build Coastguard Worker return(-1);
12039*7c568831SAndroid Build Coastguard Worker }
12040*7c568831SAndroid Build Coastguard Worker ctxt->valueNr = 0;
12041*7c568831SAndroid Build Coastguard Worker ctxt->valueMax = 10;
12042*7c568831SAndroid Build Coastguard Worker ctxt->value = NULL;
12043*7c568831SAndroid Build Coastguard Worker }
12044*7c568831SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
12045*7c568831SAndroid Build Coastguard Worker if (ctxt->comp->stream) {
12046*7c568831SAndroid Build Coastguard Worker int res;
12047*7c568831SAndroid Build Coastguard Worker
12048*7c568831SAndroid Build Coastguard Worker if (toBool) {
12049*7c568831SAndroid Build Coastguard Worker /*
12050*7c568831SAndroid Build Coastguard Worker * Evaluation to boolean result.
12051*7c568831SAndroid Build Coastguard Worker */
12052*7c568831SAndroid Build Coastguard Worker res = xmlXPathRunStreamEval(ctxt, ctxt->comp->stream, NULL, 1);
12053*7c568831SAndroid Build Coastguard Worker if (res != -1)
12054*7c568831SAndroid Build Coastguard Worker return(res);
12055*7c568831SAndroid Build Coastguard Worker } else {
12056*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr resObj = NULL;
12057*7c568831SAndroid Build Coastguard Worker
12058*7c568831SAndroid Build Coastguard Worker /*
12059*7c568831SAndroid Build Coastguard Worker * Evaluation to a sequence.
12060*7c568831SAndroid Build Coastguard Worker */
12061*7c568831SAndroid Build Coastguard Worker res = xmlXPathRunStreamEval(ctxt, ctxt->comp->stream, &resObj, 0);
12062*7c568831SAndroid Build Coastguard Worker
12063*7c568831SAndroid Build Coastguard Worker if ((res != -1) && (resObj != NULL)) {
12064*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, resObj);
12065*7c568831SAndroid Build Coastguard Worker return(0);
12066*7c568831SAndroid Build Coastguard Worker }
12067*7c568831SAndroid Build Coastguard Worker if (resObj != NULL)
12068*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, resObj);
12069*7c568831SAndroid Build Coastguard Worker }
12070*7c568831SAndroid Build Coastguard Worker /*
12071*7c568831SAndroid Build Coastguard Worker * QUESTION TODO: This falls back to normal XPath evaluation
12072*7c568831SAndroid Build Coastguard Worker * if res == -1. Is this intended?
12073*7c568831SAndroid Build Coastguard Worker */
12074*7c568831SAndroid Build Coastguard Worker }
12075*7c568831SAndroid Build Coastguard Worker #endif
12076*7c568831SAndroid Build Coastguard Worker comp = ctxt->comp;
12077*7c568831SAndroid Build Coastguard Worker if (comp->last < 0) {
12078*7c568831SAndroid Build Coastguard Worker xmlXPathErr(ctxt, XPATH_STACK_ERROR);
12079*7c568831SAndroid Build Coastguard Worker return(-1);
12080*7c568831SAndroid Build Coastguard Worker }
12081*7c568831SAndroid Build Coastguard Worker oldDepth = ctxt->context->depth;
12082*7c568831SAndroid Build Coastguard Worker if (toBool)
12083*7c568831SAndroid Build Coastguard Worker return(xmlXPathCompOpEvalToBoolean(ctxt,
12084*7c568831SAndroid Build Coastguard Worker &comp->steps[comp->last], 0));
12085*7c568831SAndroid Build Coastguard Worker else
12086*7c568831SAndroid Build Coastguard Worker xmlXPathCompOpEval(ctxt, &comp->steps[comp->last]);
12087*7c568831SAndroid Build Coastguard Worker ctxt->context->depth = oldDepth;
12088*7c568831SAndroid Build Coastguard Worker
12089*7c568831SAndroid Build Coastguard Worker return(0);
12090*7c568831SAndroid Build Coastguard Worker }
12091*7c568831SAndroid Build Coastguard Worker
12092*7c568831SAndroid Build Coastguard Worker /************************************************************************
12093*7c568831SAndroid Build Coastguard Worker * *
12094*7c568831SAndroid Build Coastguard Worker * Public interfaces *
12095*7c568831SAndroid Build Coastguard Worker * *
12096*7c568831SAndroid Build Coastguard Worker ************************************************************************/
12097*7c568831SAndroid Build Coastguard Worker
12098*7c568831SAndroid Build Coastguard Worker /**
12099*7c568831SAndroid Build Coastguard Worker * xmlXPathEvalPredicate:
12100*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath context
12101*7c568831SAndroid Build Coastguard Worker * @res: the Predicate Expression evaluation result
12102*7c568831SAndroid Build Coastguard Worker *
12103*7c568831SAndroid Build Coastguard Worker * Evaluate a predicate result for the current node.
12104*7c568831SAndroid Build Coastguard Worker * A PredicateExpr is evaluated by evaluating the Expr and converting
12105*7c568831SAndroid Build Coastguard Worker * the result to a boolean. If the result is a number, the result will
12106*7c568831SAndroid Build Coastguard Worker * be converted to true if the number is equal to the position of the
12107*7c568831SAndroid Build Coastguard Worker * context node in the context node list (as returned by the position
12108*7c568831SAndroid Build Coastguard Worker * function) and will be converted to false otherwise; if the result
12109*7c568831SAndroid Build Coastguard Worker * is not a number, then the result will be converted as if by a call
12110*7c568831SAndroid Build Coastguard Worker * to the boolean function.
12111*7c568831SAndroid Build Coastguard Worker *
12112*7c568831SAndroid Build Coastguard Worker * Returns 1 if predicate is true, 0 otherwise
12113*7c568831SAndroid Build Coastguard Worker */
12114*7c568831SAndroid Build Coastguard Worker int
xmlXPathEvalPredicate(xmlXPathContextPtr ctxt,xmlXPathObjectPtr res)12115*7c568831SAndroid Build Coastguard Worker xmlXPathEvalPredicate(xmlXPathContextPtr ctxt, xmlXPathObjectPtr res) {
12116*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (res == NULL)) return(0);
12117*7c568831SAndroid Build Coastguard Worker switch (res->type) {
12118*7c568831SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
12119*7c568831SAndroid Build Coastguard Worker return(res->boolval);
12120*7c568831SAndroid Build Coastguard Worker case XPATH_NUMBER:
12121*7c568831SAndroid Build Coastguard Worker return(res->floatval == ctxt->proximityPosition);
12122*7c568831SAndroid Build Coastguard Worker case XPATH_NODESET:
12123*7c568831SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
12124*7c568831SAndroid Build Coastguard Worker if (res->nodesetval == NULL)
12125*7c568831SAndroid Build Coastguard Worker return(0);
12126*7c568831SAndroid Build Coastguard Worker return(res->nodesetval->nodeNr != 0);
12127*7c568831SAndroid Build Coastguard Worker case XPATH_STRING:
12128*7c568831SAndroid Build Coastguard Worker return((res->stringval != NULL) &&
12129*7c568831SAndroid Build Coastguard Worker (xmlStrlen(res->stringval) != 0));
12130*7c568831SAndroid Build Coastguard Worker default:
12131*7c568831SAndroid Build Coastguard Worker break;
12132*7c568831SAndroid Build Coastguard Worker }
12133*7c568831SAndroid Build Coastguard Worker return(0);
12134*7c568831SAndroid Build Coastguard Worker }
12135*7c568831SAndroid Build Coastguard Worker
12136*7c568831SAndroid Build Coastguard Worker /**
12137*7c568831SAndroid Build Coastguard Worker * xmlXPathEvaluatePredicateResult:
12138*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
12139*7c568831SAndroid Build Coastguard Worker * @res: the Predicate Expression evaluation result
12140*7c568831SAndroid Build Coastguard Worker *
12141*7c568831SAndroid Build Coastguard Worker * Evaluate a predicate result for the current node.
12142*7c568831SAndroid Build Coastguard Worker * A PredicateExpr is evaluated by evaluating the Expr and converting
12143*7c568831SAndroid Build Coastguard Worker * the result to a boolean. If the result is a number, the result will
12144*7c568831SAndroid Build Coastguard Worker * be converted to true if the number is equal to the position of the
12145*7c568831SAndroid Build Coastguard Worker * context node in the context node list (as returned by the position
12146*7c568831SAndroid Build Coastguard Worker * function) and will be converted to false otherwise; if the result
12147*7c568831SAndroid Build Coastguard Worker * is not a number, then the result will be converted as if by a call
12148*7c568831SAndroid Build Coastguard Worker * to the boolean function.
12149*7c568831SAndroid Build Coastguard Worker *
12150*7c568831SAndroid Build Coastguard Worker * Returns 1 if predicate is true, 0 otherwise
12151*7c568831SAndroid Build Coastguard Worker */
12152*7c568831SAndroid Build Coastguard Worker int
xmlXPathEvaluatePredicateResult(xmlXPathParserContextPtr ctxt,xmlXPathObjectPtr res)12153*7c568831SAndroid Build Coastguard Worker xmlXPathEvaluatePredicateResult(xmlXPathParserContextPtr ctxt,
12154*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr res) {
12155*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (res == NULL)) return(0);
12156*7c568831SAndroid Build Coastguard Worker switch (res->type) {
12157*7c568831SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
12158*7c568831SAndroid Build Coastguard Worker return(res->boolval);
12159*7c568831SAndroid Build Coastguard Worker case XPATH_NUMBER:
12160*7c568831SAndroid Build Coastguard Worker #if defined(__BORLANDC__) || (defined(_MSC_VER) && (_MSC_VER == 1200))
12161*7c568831SAndroid Build Coastguard Worker return((res->floatval == ctxt->context->proximityPosition) &&
12162*7c568831SAndroid Build Coastguard Worker (!xmlXPathIsNaN(res->floatval))); /* MSC pbm Mark Vakoc !*/
12163*7c568831SAndroid Build Coastguard Worker #else
12164*7c568831SAndroid Build Coastguard Worker return(res->floatval == ctxt->context->proximityPosition);
12165*7c568831SAndroid Build Coastguard Worker #endif
12166*7c568831SAndroid Build Coastguard Worker case XPATH_NODESET:
12167*7c568831SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
12168*7c568831SAndroid Build Coastguard Worker if (res->nodesetval == NULL)
12169*7c568831SAndroid Build Coastguard Worker return(0);
12170*7c568831SAndroid Build Coastguard Worker return(res->nodesetval->nodeNr != 0);
12171*7c568831SAndroid Build Coastguard Worker case XPATH_STRING:
12172*7c568831SAndroid Build Coastguard Worker return((res->stringval != NULL) && (res->stringval[0] != 0));
12173*7c568831SAndroid Build Coastguard Worker default:
12174*7c568831SAndroid Build Coastguard Worker break;
12175*7c568831SAndroid Build Coastguard Worker }
12176*7c568831SAndroid Build Coastguard Worker return(0);
12177*7c568831SAndroid Build Coastguard Worker }
12178*7c568831SAndroid Build Coastguard Worker
12179*7c568831SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
12180*7c568831SAndroid Build Coastguard Worker /**
12181*7c568831SAndroid Build Coastguard Worker * xmlXPathTryStreamCompile:
12182*7c568831SAndroid Build Coastguard Worker * @ctxt: an XPath context
12183*7c568831SAndroid Build Coastguard Worker * @str: the XPath expression
12184*7c568831SAndroid Build Coastguard Worker *
12185*7c568831SAndroid Build Coastguard Worker * Try to compile the XPath expression as a streamable subset.
12186*7c568831SAndroid Build Coastguard Worker *
12187*7c568831SAndroid Build Coastguard Worker * Returns the compiled expression or NULL if failed to compile.
12188*7c568831SAndroid Build Coastguard Worker */
12189*7c568831SAndroid Build Coastguard Worker static xmlXPathCompExprPtr
xmlXPathTryStreamCompile(xmlXPathContextPtr ctxt,const xmlChar * str)12190*7c568831SAndroid Build Coastguard Worker xmlXPathTryStreamCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
12191*7c568831SAndroid Build Coastguard Worker /*
12192*7c568831SAndroid Build Coastguard Worker * Optimization: use streaming patterns when the XPath expression can
12193*7c568831SAndroid Build Coastguard Worker * be compiled to a stream lookup
12194*7c568831SAndroid Build Coastguard Worker */
12195*7c568831SAndroid Build Coastguard Worker xmlPatternPtr stream;
12196*7c568831SAndroid Build Coastguard Worker xmlXPathCompExprPtr comp;
12197*7c568831SAndroid Build Coastguard Worker xmlDictPtr dict = NULL;
12198*7c568831SAndroid Build Coastguard Worker const xmlChar **namespaces = NULL;
12199*7c568831SAndroid Build Coastguard Worker xmlNsPtr ns;
12200*7c568831SAndroid Build Coastguard Worker int i, j;
12201*7c568831SAndroid Build Coastguard Worker
12202*7c568831SAndroid Build Coastguard Worker if ((!xmlStrchr(str, '[')) && (!xmlStrchr(str, '(')) &&
12203*7c568831SAndroid Build Coastguard Worker (!xmlStrchr(str, '@'))) {
12204*7c568831SAndroid Build Coastguard Worker const xmlChar *tmp;
12205*7c568831SAndroid Build Coastguard Worker int res;
12206*7c568831SAndroid Build Coastguard Worker
12207*7c568831SAndroid Build Coastguard Worker /*
12208*7c568831SAndroid Build Coastguard Worker * We don't try to handle expressions using the verbose axis
12209*7c568831SAndroid Build Coastguard Worker * specifiers ("::"), just the simplified form at this point.
12210*7c568831SAndroid Build Coastguard Worker * Additionally, if there is no list of namespaces available and
12211*7c568831SAndroid Build Coastguard Worker * there's a ":" in the expression, indicating a prefixed QName,
12212*7c568831SAndroid Build Coastguard Worker * then we won't try to compile either. xmlPatterncompile() needs
12213*7c568831SAndroid Build Coastguard Worker * to have a list of namespaces at compilation time in order to
12214*7c568831SAndroid Build Coastguard Worker * compile prefixed name tests.
12215*7c568831SAndroid Build Coastguard Worker */
12216*7c568831SAndroid Build Coastguard Worker tmp = xmlStrchr(str, ':');
12217*7c568831SAndroid Build Coastguard Worker if ((tmp != NULL) &&
12218*7c568831SAndroid Build Coastguard Worker ((ctxt == NULL) || (ctxt->nsNr == 0) || (tmp[1] == ':')))
12219*7c568831SAndroid Build Coastguard Worker return(NULL);
12220*7c568831SAndroid Build Coastguard Worker
12221*7c568831SAndroid Build Coastguard Worker if (ctxt != NULL) {
12222*7c568831SAndroid Build Coastguard Worker dict = ctxt->dict;
12223*7c568831SAndroid Build Coastguard Worker if (ctxt->nsNr > 0) {
12224*7c568831SAndroid Build Coastguard Worker namespaces = xmlMalloc(2 * (ctxt->nsNr + 1) * sizeof(xmlChar*));
12225*7c568831SAndroid Build Coastguard Worker if (namespaces == NULL) {
12226*7c568831SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt);
12227*7c568831SAndroid Build Coastguard Worker return(NULL);
12228*7c568831SAndroid Build Coastguard Worker }
12229*7c568831SAndroid Build Coastguard Worker for (i = 0, j = 0; (j < ctxt->nsNr); j++) {
12230*7c568831SAndroid Build Coastguard Worker ns = ctxt->namespaces[j];
12231*7c568831SAndroid Build Coastguard Worker namespaces[i++] = ns->href;
12232*7c568831SAndroid Build Coastguard Worker namespaces[i++] = ns->prefix;
12233*7c568831SAndroid Build Coastguard Worker }
12234*7c568831SAndroid Build Coastguard Worker namespaces[i++] = NULL;
12235*7c568831SAndroid Build Coastguard Worker namespaces[i] = NULL;
12236*7c568831SAndroid Build Coastguard Worker }
12237*7c568831SAndroid Build Coastguard Worker }
12238*7c568831SAndroid Build Coastguard Worker
12239*7c568831SAndroid Build Coastguard Worker res = xmlPatternCompileSafe(str, dict, XML_PATTERN_XPATH, namespaces,
12240*7c568831SAndroid Build Coastguard Worker &stream);
12241*7c568831SAndroid Build Coastguard Worker if (namespaces != NULL) {
12242*7c568831SAndroid Build Coastguard Worker xmlFree((xmlChar **)namespaces);
12243*7c568831SAndroid Build Coastguard Worker }
12244*7c568831SAndroid Build Coastguard Worker if (res < 0) {
12245*7c568831SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt);
12246*7c568831SAndroid Build Coastguard Worker return(NULL);
12247*7c568831SAndroid Build Coastguard Worker }
12248*7c568831SAndroid Build Coastguard Worker if ((stream != NULL) && (xmlPatternStreamable(stream) == 1)) {
12249*7c568831SAndroid Build Coastguard Worker comp = xmlXPathNewCompExpr();
12250*7c568831SAndroid Build Coastguard Worker if (comp == NULL) {
12251*7c568831SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt);
12252*7c568831SAndroid Build Coastguard Worker xmlFreePattern(stream);
12253*7c568831SAndroid Build Coastguard Worker return(NULL);
12254*7c568831SAndroid Build Coastguard Worker }
12255*7c568831SAndroid Build Coastguard Worker comp->stream = stream;
12256*7c568831SAndroid Build Coastguard Worker comp->dict = dict;
12257*7c568831SAndroid Build Coastguard Worker if (comp->dict)
12258*7c568831SAndroid Build Coastguard Worker xmlDictReference(comp->dict);
12259*7c568831SAndroid Build Coastguard Worker return(comp);
12260*7c568831SAndroid Build Coastguard Worker }
12261*7c568831SAndroid Build Coastguard Worker xmlFreePattern(stream);
12262*7c568831SAndroid Build Coastguard Worker }
12263*7c568831SAndroid Build Coastguard Worker return(NULL);
12264*7c568831SAndroid Build Coastguard Worker }
12265*7c568831SAndroid Build Coastguard Worker #endif /* XPATH_STREAMING */
12266*7c568831SAndroid Build Coastguard Worker
12267*7c568831SAndroid Build Coastguard Worker static void
xmlXPathOptimizeExpression(xmlXPathParserContextPtr pctxt,xmlXPathStepOpPtr op)12268*7c568831SAndroid Build Coastguard Worker xmlXPathOptimizeExpression(xmlXPathParserContextPtr pctxt,
12269*7c568831SAndroid Build Coastguard Worker xmlXPathStepOpPtr op)
12270*7c568831SAndroid Build Coastguard Worker {
12271*7c568831SAndroid Build Coastguard Worker xmlXPathCompExprPtr comp = pctxt->comp;
12272*7c568831SAndroid Build Coastguard Worker xmlXPathContextPtr ctxt;
12273*7c568831SAndroid Build Coastguard Worker
12274*7c568831SAndroid Build Coastguard Worker /*
12275*7c568831SAndroid Build Coastguard Worker * Try to rewrite "descendant-or-self::node()/foo" to an optimized
12276*7c568831SAndroid Build Coastguard Worker * internal representation.
12277*7c568831SAndroid Build Coastguard Worker */
12278*7c568831SAndroid Build Coastguard Worker
12279*7c568831SAndroid Build Coastguard Worker if ((op->op == XPATH_OP_COLLECT /* 11 */) &&
12280*7c568831SAndroid Build Coastguard Worker (op->ch1 != -1) &&
12281*7c568831SAndroid Build Coastguard Worker (op->ch2 == -1 /* no predicate */))
12282*7c568831SAndroid Build Coastguard Worker {
12283*7c568831SAndroid Build Coastguard Worker xmlXPathStepOpPtr prevop = &comp->steps[op->ch1];
12284*7c568831SAndroid Build Coastguard Worker
12285*7c568831SAndroid Build Coastguard Worker if ((prevop->op == XPATH_OP_COLLECT /* 11 */) &&
12286*7c568831SAndroid Build Coastguard Worker ((xmlXPathAxisVal) prevop->value ==
12287*7c568831SAndroid Build Coastguard Worker AXIS_DESCENDANT_OR_SELF) &&
12288*7c568831SAndroid Build Coastguard Worker (prevop->ch2 == -1) &&
12289*7c568831SAndroid Build Coastguard Worker ((xmlXPathTestVal) prevop->value2 == NODE_TEST_TYPE) &&
12290*7c568831SAndroid Build Coastguard Worker ((xmlXPathTypeVal) prevop->value3 == NODE_TYPE_NODE))
12291*7c568831SAndroid Build Coastguard Worker {
12292*7c568831SAndroid Build Coastguard Worker /*
12293*7c568831SAndroid Build Coastguard Worker * This is a "descendant-or-self::node()" without predicates.
12294*7c568831SAndroid Build Coastguard Worker * Try to eliminate it.
12295*7c568831SAndroid Build Coastguard Worker */
12296*7c568831SAndroid Build Coastguard Worker
12297*7c568831SAndroid Build Coastguard Worker switch ((xmlXPathAxisVal) op->value) {
12298*7c568831SAndroid Build Coastguard Worker case AXIS_CHILD:
12299*7c568831SAndroid Build Coastguard Worker case AXIS_DESCENDANT:
12300*7c568831SAndroid Build Coastguard Worker /*
12301*7c568831SAndroid Build Coastguard Worker * Convert "descendant-or-self::node()/child::" or
12302*7c568831SAndroid Build Coastguard Worker * "descendant-or-self::node()/descendant::" to
12303*7c568831SAndroid Build Coastguard Worker * "descendant::"
12304*7c568831SAndroid Build Coastguard Worker */
12305*7c568831SAndroid Build Coastguard Worker op->ch1 = prevop->ch1;
12306*7c568831SAndroid Build Coastguard Worker op->value = AXIS_DESCENDANT;
12307*7c568831SAndroid Build Coastguard Worker break;
12308*7c568831SAndroid Build Coastguard Worker case AXIS_SELF:
12309*7c568831SAndroid Build Coastguard Worker case AXIS_DESCENDANT_OR_SELF:
12310*7c568831SAndroid Build Coastguard Worker /*
12311*7c568831SAndroid Build Coastguard Worker * Convert "descendant-or-self::node()/self::" or
12312*7c568831SAndroid Build Coastguard Worker * "descendant-or-self::node()/descendant-or-self::" to
12313*7c568831SAndroid Build Coastguard Worker * to "descendant-or-self::"
12314*7c568831SAndroid Build Coastguard Worker */
12315*7c568831SAndroid Build Coastguard Worker op->ch1 = prevop->ch1;
12316*7c568831SAndroid Build Coastguard Worker op->value = AXIS_DESCENDANT_OR_SELF;
12317*7c568831SAndroid Build Coastguard Worker break;
12318*7c568831SAndroid Build Coastguard Worker default:
12319*7c568831SAndroid Build Coastguard Worker break;
12320*7c568831SAndroid Build Coastguard Worker }
12321*7c568831SAndroid Build Coastguard Worker }
12322*7c568831SAndroid Build Coastguard Worker }
12323*7c568831SAndroid Build Coastguard Worker
12324*7c568831SAndroid Build Coastguard Worker /* OP_VALUE has invalid ch1. */
12325*7c568831SAndroid Build Coastguard Worker if (op->op == XPATH_OP_VALUE)
12326*7c568831SAndroid Build Coastguard Worker return;
12327*7c568831SAndroid Build Coastguard Worker
12328*7c568831SAndroid Build Coastguard Worker /* Recurse */
12329*7c568831SAndroid Build Coastguard Worker ctxt = pctxt->context;
12330*7c568831SAndroid Build Coastguard Worker if (ctxt != NULL) {
12331*7c568831SAndroid Build Coastguard Worker if (ctxt->depth >= XPATH_MAX_RECURSION_DEPTH)
12332*7c568831SAndroid Build Coastguard Worker return;
12333*7c568831SAndroid Build Coastguard Worker ctxt->depth += 1;
12334*7c568831SAndroid Build Coastguard Worker }
12335*7c568831SAndroid Build Coastguard Worker if (op->ch1 != -1)
12336*7c568831SAndroid Build Coastguard Worker xmlXPathOptimizeExpression(pctxt, &comp->steps[op->ch1]);
12337*7c568831SAndroid Build Coastguard Worker if (op->ch2 != -1)
12338*7c568831SAndroid Build Coastguard Worker xmlXPathOptimizeExpression(pctxt, &comp->steps[op->ch2]);
12339*7c568831SAndroid Build Coastguard Worker if (ctxt != NULL)
12340*7c568831SAndroid Build Coastguard Worker ctxt->depth -= 1;
12341*7c568831SAndroid Build Coastguard Worker }
12342*7c568831SAndroid Build Coastguard Worker
12343*7c568831SAndroid Build Coastguard Worker /**
12344*7c568831SAndroid Build Coastguard Worker * xmlXPathCtxtCompile:
12345*7c568831SAndroid Build Coastguard Worker * @ctxt: an XPath context
12346*7c568831SAndroid Build Coastguard Worker * @str: the XPath expression
12347*7c568831SAndroid Build Coastguard Worker *
12348*7c568831SAndroid Build Coastguard Worker * Compile an XPath expression
12349*7c568831SAndroid Build Coastguard Worker *
12350*7c568831SAndroid Build Coastguard Worker * Returns the xmlXPathCompExprPtr resulting from the compilation or NULL.
12351*7c568831SAndroid Build Coastguard Worker * the caller has to free the object.
12352*7c568831SAndroid Build Coastguard Worker */
12353*7c568831SAndroid Build Coastguard Worker xmlXPathCompExprPtr
xmlXPathCtxtCompile(xmlXPathContextPtr ctxt,const xmlChar * str)12354*7c568831SAndroid Build Coastguard Worker xmlXPathCtxtCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
12355*7c568831SAndroid Build Coastguard Worker xmlXPathParserContextPtr pctxt;
12356*7c568831SAndroid Build Coastguard Worker xmlXPathContextPtr tmpctxt = NULL;
12357*7c568831SAndroid Build Coastguard Worker xmlXPathCompExprPtr comp;
12358*7c568831SAndroid Build Coastguard Worker int oldDepth = 0;
12359*7c568831SAndroid Build Coastguard Worker
12360*7c568831SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
12361*7c568831SAndroid Build Coastguard Worker comp = xmlXPathTryStreamCompile(ctxt, str);
12362*7c568831SAndroid Build Coastguard Worker if (comp != NULL)
12363*7c568831SAndroid Build Coastguard Worker return(comp);
12364*7c568831SAndroid Build Coastguard Worker #endif
12365*7c568831SAndroid Build Coastguard Worker
12366*7c568831SAndroid Build Coastguard Worker xmlInitParser();
12367*7c568831SAndroid Build Coastguard Worker
12368*7c568831SAndroid Build Coastguard Worker /*
12369*7c568831SAndroid Build Coastguard Worker * We need an xmlXPathContext for the depth check.
12370*7c568831SAndroid Build Coastguard Worker */
12371*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL) {
12372*7c568831SAndroid Build Coastguard Worker tmpctxt = xmlXPathNewContext(NULL);
12373*7c568831SAndroid Build Coastguard Worker if (tmpctxt == NULL)
12374*7c568831SAndroid Build Coastguard Worker return(NULL);
12375*7c568831SAndroid Build Coastguard Worker ctxt = tmpctxt;
12376*7c568831SAndroid Build Coastguard Worker }
12377*7c568831SAndroid Build Coastguard Worker
12378*7c568831SAndroid Build Coastguard Worker pctxt = xmlXPathNewParserContext(str, ctxt);
12379*7c568831SAndroid Build Coastguard Worker if (pctxt == NULL) {
12380*7c568831SAndroid Build Coastguard Worker if (tmpctxt != NULL)
12381*7c568831SAndroid Build Coastguard Worker xmlXPathFreeContext(tmpctxt);
12382*7c568831SAndroid Build Coastguard Worker return NULL;
12383*7c568831SAndroid Build Coastguard Worker }
12384*7c568831SAndroid Build Coastguard Worker
12385*7c568831SAndroid Build Coastguard Worker oldDepth = ctxt->depth;
12386*7c568831SAndroid Build Coastguard Worker xmlXPathCompileExpr(pctxt, 1);
12387*7c568831SAndroid Build Coastguard Worker ctxt->depth = oldDepth;
12388*7c568831SAndroid Build Coastguard Worker
12389*7c568831SAndroid Build Coastguard Worker if( pctxt->error != XPATH_EXPRESSION_OK )
12390*7c568831SAndroid Build Coastguard Worker {
12391*7c568831SAndroid Build Coastguard Worker xmlXPathFreeParserContext(pctxt);
12392*7c568831SAndroid Build Coastguard Worker if (tmpctxt != NULL)
12393*7c568831SAndroid Build Coastguard Worker xmlXPathFreeContext(tmpctxt);
12394*7c568831SAndroid Build Coastguard Worker return(NULL);
12395*7c568831SAndroid Build Coastguard Worker }
12396*7c568831SAndroid Build Coastguard Worker
12397*7c568831SAndroid Build Coastguard Worker if (*pctxt->cur != 0) {
12398*7c568831SAndroid Build Coastguard Worker /*
12399*7c568831SAndroid Build Coastguard Worker * aleksey: in some cases this line prints *second* error message
12400*7c568831SAndroid Build Coastguard Worker * (see bug #78858) and probably this should be fixed.
12401*7c568831SAndroid Build Coastguard Worker * However, we are not sure that all error messages are printed
12402*7c568831SAndroid Build Coastguard Worker * out in other places. It's not critical so we leave it as-is for now
12403*7c568831SAndroid Build Coastguard Worker */
12404*7c568831SAndroid Build Coastguard Worker xmlXPatherror(pctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR);
12405*7c568831SAndroid Build Coastguard Worker comp = NULL;
12406*7c568831SAndroid Build Coastguard Worker } else {
12407*7c568831SAndroid Build Coastguard Worker comp = pctxt->comp;
12408*7c568831SAndroid Build Coastguard Worker if ((comp->nbStep > 1) && (comp->last >= 0)) {
12409*7c568831SAndroid Build Coastguard Worker if (ctxt != NULL)
12410*7c568831SAndroid Build Coastguard Worker oldDepth = ctxt->depth;
12411*7c568831SAndroid Build Coastguard Worker xmlXPathOptimizeExpression(pctxt, &comp->steps[comp->last]);
12412*7c568831SAndroid Build Coastguard Worker if (ctxt != NULL)
12413*7c568831SAndroid Build Coastguard Worker ctxt->depth = oldDepth;
12414*7c568831SAndroid Build Coastguard Worker }
12415*7c568831SAndroid Build Coastguard Worker pctxt->comp = NULL;
12416*7c568831SAndroid Build Coastguard Worker }
12417*7c568831SAndroid Build Coastguard Worker xmlXPathFreeParserContext(pctxt);
12418*7c568831SAndroid Build Coastguard Worker if (tmpctxt != NULL)
12419*7c568831SAndroid Build Coastguard Worker xmlXPathFreeContext(tmpctxt);
12420*7c568831SAndroid Build Coastguard Worker
12421*7c568831SAndroid Build Coastguard Worker if (comp != NULL) {
12422*7c568831SAndroid Build Coastguard Worker comp->expr = xmlStrdup(str);
12423*7c568831SAndroid Build Coastguard Worker }
12424*7c568831SAndroid Build Coastguard Worker return(comp);
12425*7c568831SAndroid Build Coastguard Worker }
12426*7c568831SAndroid Build Coastguard Worker
12427*7c568831SAndroid Build Coastguard Worker /**
12428*7c568831SAndroid Build Coastguard Worker * xmlXPathCompile:
12429*7c568831SAndroid Build Coastguard Worker * @str: the XPath expression
12430*7c568831SAndroid Build Coastguard Worker *
12431*7c568831SAndroid Build Coastguard Worker * Compile an XPath expression
12432*7c568831SAndroid Build Coastguard Worker *
12433*7c568831SAndroid Build Coastguard Worker * Returns the xmlXPathCompExprPtr resulting from the compilation or NULL.
12434*7c568831SAndroid Build Coastguard Worker * the caller has to free the object.
12435*7c568831SAndroid Build Coastguard Worker */
12436*7c568831SAndroid Build Coastguard Worker xmlXPathCompExprPtr
xmlXPathCompile(const xmlChar * str)12437*7c568831SAndroid Build Coastguard Worker xmlXPathCompile(const xmlChar *str) {
12438*7c568831SAndroid Build Coastguard Worker return(xmlXPathCtxtCompile(NULL, str));
12439*7c568831SAndroid Build Coastguard Worker }
12440*7c568831SAndroid Build Coastguard Worker
12441*7c568831SAndroid Build Coastguard Worker /**
12442*7c568831SAndroid Build Coastguard Worker * xmlXPathCompiledEvalInternal:
12443*7c568831SAndroid Build Coastguard Worker * @comp: the compiled XPath expression
12444*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath context
12445*7c568831SAndroid Build Coastguard Worker * @resObj: the resulting XPath object or NULL
12446*7c568831SAndroid Build Coastguard Worker * @toBool: 1 if only a boolean result is requested
12447*7c568831SAndroid Build Coastguard Worker *
12448*7c568831SAndroid Build Coastguard Worker * Evaluate the Precompiled XPath expression in the given context.
12449*7c568831SAndroid Build Coastguard Worker * The caller has to free @resObj.
12450*7c568831SAndroid Build Coastguard Worker *
12451*7c568831SAndroid Build Coastguard Worker * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
12452*7c568831SAndroid Build Coastguard Worker * the caller has to free the object.
12453*7c568831SAndroid Build Coastguard Worker */
12454*7c568831SAndroid Build Coastguard Worker static int
xmlXPathCompiledEvalInternal(xmlXPathCompExprPtr comp,xmlXPathContextPtr ctxt,xmlXPathObjectPtr * resObjPtr,int toBool)12455*7c568831SAndroid Build Coastguard Worker xmlXPathCompiledEvalInternal(xmlXPathCompExprPtr comp,
12456*7c568831SAndroid Build Coastguard Worker xmlXPathContextPtr ctxt,
12457*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr *resObjPtr,
12458*7c568831SAndroid Build Coastguard Worker int toBool)
12459*7c568831SAndroid Build Coastguard Worker {
12460*7c568831SAndroid Build Coastguard Worker xmlXPathParserContextPtr pctxt;
12461*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr resObj = NULL;
12462*7c568831SAndroid Build Coastguard Worker int res;
12463*7c568831SAndroid Build Coastguard Worker
12464*7c568831SAndroid Build Coastguard Worker if (comp == NULL)
12465*7c568831SAndroid Build Coastguard Worker return(-1);
12466*7c568831SAndroid Build Coastguard Worker xmlInitParser();
12467*7c568831SAndroid Build Coastguard Worker
12468*7c568831SAndroid Build Coastguard Worker xmlResetError(&ctxt->lastError);
12469*7c568831SAndroid Build Coastguard Worker
12470*7c568831SAndroid Build Coastguard Worker pctxt = xmlXPathCompParserContext(comp, ctxt);
12471*7c568831SAndroid Build Coastguard Worker if (pctxt == NULL)
12472*7c568831SAndroid Build Coastguard Worker return(-1);
12473*7c568831SAndroid Build Coastguard Worker res = xmlXPathRunEval(pctxt, toBool);
12474*7c568831SAndroid Build Coastguard Worker
12475*7c568831SAndroid Build Coastguard Worker if (pctxt->error == XPATH_EXPRESSION_OK) {
12476*7c568831SAndroid Build Coastguard Worker if (pctxt->valueNr != ((toBool) ? 0 : 1))
12477*7c568831SAndroid Build Coastguard Worker xmlXPathErr(pctxt, XPATH_STACK_ERROR);
12478*7c568831SAndroid Build Coastguard Worker else if (!toBool)
12479*7c568831SAndroid Build Coastguard Worker resObj = valuePop(pctxt);
12480*7c568831SAndroid Build Coastguard Worker }
12481*7c568831SAndroid Build Coastguard Worker
12482*7c568831SAndroid Build Coastguard Worker if (resObjPtr)
12483*7c568831SAndroid Build Coastguard Worker *resObjPtr = resObj;
12484*7c568831SAndroid Build Coastguard Worker else
12485*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt, resObj);
12486*7c568831SAndroid Build Coastguard Worker
12487*7c568831SAndroid Build Coastguard Worker pctxt->comp = NULL;
12488*7c568831SAndroid Build Coastguard Worker xmlXPathFreeParserContext(pctxt);
12489*7c568831SAndroid Build Coastguard Worker
12490*7c568831SAndroid Build Coastguard Worker return(res);
12491*7c568831SAndroid Build Coastguard Worker }
12492*7c568831SAndroid Build Coastguard Worker
12493*7c568831SAndroid Build Coastguard Worker /**
12494*7c568831SAndroid Build Coastguard Worker * xmlXPathCompiledEval:
12495*7c568831SAndroid Build Coastguard Worker * @comp: the compiled XPath expression
12496*7c568831SAndroid Build Coastguard Worker * @ctx: the XPath context
12497*7c568831SAndroid Build Coastguard Worker *
12498*7c568831SAndroid Build Coastguard Worker * Evaluate the Precompiled XPath expression in the given context.
12499*7c568831SAndroid Build Coastguard Worker *
12500*7c568831SAndroid Build Coastguard Worker * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
12501*7c568831SAndroid Build Coastguard Worker * the caller has to free the object.
12502*7c568831SAndroid Build Coastguard Worker */
12503*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathCompiledEval(xmlXPathCompExprPtr comp,xmlXPathContextPtr ctx)12504*7c568831SAndroid Build Coastguard Worker xmlXPathCompiledEval(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctx)
12505*7c568831SAndroid Build Coastguard Worker {
12506*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr res = NULL;
12507*7c568831SAndroid Build Coastguard Worker
12508*7c568831SAndroid Build Coastguard Worker xmlXPathCompiledEvalInternal(comp, ctx, &res, 0);
12509*7c568831SAndroid Build Coastguard Worker return(res);
12510*7c568831SAndroid Build Coastguard Worker }
12511*7c568831SAndroid Build Coastguard Worker
12512*7c568831SAndroid Build Coastguard Worker /**
12513*7c568831SAndroid Build Coastguard Worker * xmlXPathCompiledEvalToBoolean:
12514*7c568831SAndroid Build Coastguard Worker * @comp: the compiled XPath expression
12515*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath context
12516*7c568831SAndroid Build Coastguard Worker *
12517*7c568831SAndroid Build Coastguard Worker * Applies the XPath boolean() function on the result of the given
12518*7c568831SAndroid Build Coastguard Worker * compiled expression.
12519*7c568831SAndroid Build Coastguard Worker *
12520*7c568831SAndroid Build Coastguard Worker * Returns 1 if the expression evaluated to true, 0 if to false and
12521*7c568831SAndroid Build Coastguard Worker * -1 in API and internal errors.
12522*7c568831SAndroid Build Coastguard Worker */
12523*7c568831SAndroid Build Coastguard Worker int
xmlXPathCompiledEvalToBoolean(xmlXPathCompExprPtr comp,xmlXPathContextPtr ctxt)12524*7c568831SAndroid Build Coastguard Worker xmlXPathCompiledEvalToBoolean(xmlXPathCompExprPtr comp,
12525*7c568831SAndroid Build Coastguard Worker xmlXPathContextPtr ctxt)
12526*7c568831SAndroid Build Coastguard Worker {
12527*7c568831SAndroid Build Coastguard Worker return(xmlXPathCompiledEvalInternal(comp, ctxt, NULL, 1));
12528*7c568831SAndroid Build Coastguard Worker }
12529*7c568831SAndroid Build Coastguard Worker
12530*7c568831SAndroid Build Coastguard Worker /**
12531*7c568831SAndroid Build Coastguard Worker * xmlXPathEvalExpr:
12532*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
12533*7c568831SAndroid Build Coastguard Worker *
12534*7c568831SAndroid Build Coastguard Worker * DEPRECATED: Internal function, don't use.
12535*7c568831SAndroid Build Coastguard Worker *
12536*7c568831SAndroid Build Coastguard Worker * Parse and evaluate an XPath expression in the given context,
12537*7c568831SAndroid Build Coastguard Worker * then push the result on the context stack
12538*7c568831SAndroid Build Coastguard Worker */
12539*7c568831SAndroid Build Coastguard Worker void
xmlXPathEvalExpr(xmlXPathParserContextPtr ctxt)12540*7c568831SAndroid Build Coastguard Worker xmlXPathEvalExpr(xmlXPathParserContextPtr ctxt) {
12541*7c568831SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
12542*7c568831SAndroid Build Coastguard Worker xmlXPathCompExprPtr comp;
12543*7c568831SAndroid Build Coastguard Worker #endif
12544*7c568831SAndroid Build Coastguard Worker int oldDepth = 0;
12545*7c568831SAndroid Build Coastguard Worker
12546*7c568831SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL))
12547*7c568831SAndroid Build Coastguard Worker return;
12548*7c568831SAndroid Build Coastguard Worker if (ctxt->context->lastError.code != 0)
12549*7c568831SAndroid Build Coastguard Worker return;
12550*7c568831SAndroid Build Coastguard Worker
12551*7c568831SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
12552*7c568831SAndroid Build Coastguard Worker comp = xmlXPathTryStreamCompile(ctxt->context, ctxt->base);
12553*7c568831SAndroid Build Coastguard Worker if ((comp == NULL) &&
12554*7c568831SAndroid Build Coastguard Worker (ctxt->context->lastError.code == XML_ERR_NO_MEMORY)) {
12555*7c568831SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
12556*7c568831SAndroid Build Coastguard Worker return;
12557*7c568831SAndroid Build Coastguard Worker }
12558*7c568831SAndroid Build Coastguard Worker if (comp != NULL) {
12559*7c568831SAndroid Build Coastguard Worker if (ctxt->comp != NULL)
12560*7c568831SAndroid Build Coastguard Worker xmlXPathFreeCompExpr(ctxt->comp);
12561*7c568831SAndroid Build Coastguard Worker ctxt->comp = comp;
12562*7c568831SAndroid Build Coastguard Worker } else
12563*7c568831SAndroid Build Coastguard Worker #endif
12564*7c568831SAndroid Build Coastguard Worker {
12565*7c568831SAndroid Build Coastguard Worker if (ctxt->context != NULL)
12566*7c568831SAndroid Build Coastguard Worker oldDepth = ctxt->context->depth;
12567*7c568831SAndroid Build Coastguard Worker xmlXPathCompileExpr(ctxt, 1);
12568*7c568831SAndroid Build Coastguard Worker if (ctxt->context != NULL)
12569*7c568831SAndroid Build Coastguard Worker ctxt->context->depth = oldDepth;
12570*7c568831SAndroid Build Coastguard Worker CHECK_ERROR;
12571*7c568831SAndroid Build Coastguard Worker
12572*7c568831SAndroid Build Coastguard Worker /* Check for trailing characters. */
12573*7c568831SAndroid Build Coastguard Worker if (*ctxt->cur != 0)
12574*7c568831SAndroid Build Coastguard Worker XP_ERROR(XPATH_EXPR_ERROR);
12575*7c568831SAndroid Build Coastguard Worker
12576*7c568831SAndroid Build Coastguard Worker if ((ctxt->comp->nbStep > 1) && (ctxt->comp->last >= 0)) {
12577*7c568831SAndroid Build Coastguard Worker if (ctxt->context != NULL)
12578*7c568831SAndroid Build Coastguard Worker oldDepth = ctxt->context->depth;
12579*7c568831SAndroid Build Coastguard Worker xmlXPathOptimizeExpression(ctxt,
12580*7c568831SAndroid Build Coastguard Worker &ctxt->comp->steps[ctxt->comp->last]);
12581*7c568831SAndroid Build Coastguard Worker if (ctxt->context != NULL)
12582*7c568831SAndroid Build Coastguard Worker ctxt->context->depth = oldDepth;
12583*7c568831SAndroid Build Coastguard Worker }
12584*7c568831SAndroid Build Coastguard Worker }
12585*7c568831SAndroid Build Coastguard Worker
12586*7c568831SAndroid Build Coastguard Worker xmlXPathRunEval(ctxt, 0);
12587*7c568831SAndroid Build Coastguard Worker }
12588*7c568831SAndroid Build Coastguard Worker
12589*7c568831SAndroid Build Coastguard Worker /**
12590*7c568831SAndroid Build Coastguard Worker * xmlXPathEval:
12591*7c568831SAndroid Build Coastguard Worker * @str: the XPath expression
12592*7c568831SAndroid Build Coastguard Worker * @ctx: the XPath context
12593*7c568831SAndroid Build Coastguard Worker *
12594*7c568831SAndroid Build Coastguard Worker * Evaluate the XPath Location Path in the given context.
12595*7c568831SAndroid Build Coastguard Worker *
12596*7c568831SAndroid Build Coastguard Worker * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
12597*7c568831SAndroid Build Coastguard Worker * the caller has to free the object.
12598*7c568831SAndroid Build Coastguard Worker */
12599*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathEval(const xmlChar * str,xmlXPathContextPtr ctx)12600*7c568831SAndroid Build Coastguard Worker xmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctx) {
12601*7c568831SAndroid Build Coastguard Worker xmlXPathParserContextPtr ctxt;
12602*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr res;
12603*7c568831SAndroid Build Coastguard Worker
12604*7c568831SAndroid Build Coastguard Worker if (ctx == NULL)
12605*7c568831SAndroid Build Coastguard Worker return(NULL);
12606*7c568831SAndroid Build Coastguard Worker
12607*7c568831SAndroid Build Coastguard Worker xmlInitParser();
12608*7c568831SAndroid Build Coastguard Worker
12609*7c568831SAndroid Build Coastguard Worker xmlResetError(&ctx->lastError);
12610*7c568831SAndroid Build Coastguard Worker
12611*7c568831SAndroid Build Coastguard Worker ctxt = xmlXPathNewParserContext(str, ctx);
12612*7c568831SAndroid Build Coastguard Worker if (ctxt == NULL)
12613*7c568831SAndroid Build Coastguard Worker return NULL;
12614*7c568831SAndroid Build Coastguard Worker xmlXPathEvalExpr(ctxt);
12615*7c568831SAndroid Build Coastguard Worker
12616*7c568831SAndroid Build Coastguard Worker if (ctxt->error != XPATH_EXPRESSION_OK) {
12617*7c568831SAndroid Build Coastguard Worker res = NULL;
12618*7c568831SAndroid Build Coastguard Worker } else if (ctxt->valueNr != 1) {
12619*7c568831SAndroid Build Coastguard Worker xmlXPathErr(ctxt, XPATH_STACK_ERROR);
12620*7c568831SAndroid Build Coastguard Worker res = NULL;
12621*7c568831SAndroid Build Coastguard Worker } else {
12622*7c568831SAndroid Build Coastguard Worker res = valuePop(ctxt);
12623*7c568831SAndroid Build Coastguard Worker }
12624*7c568831SAndroid Build Coastguard Worker
12625*7c568831SAndroid Build Coastguard Worker xmlXPathFreeParserContext(ctxt);
12626*7c568831SAndroid Build Coastguard Worker return(res);
12627*7c568831SAndroid Build Coastguard Worker }
12628*7c568831SAndroid Build Coastguard Worker
12629*7c568831SAndroid Build Coastguard Worker /**
12630*7c568831SAndroid Build Coastguard Worker * xmlXPathSetContextNode:
12631*7c568831SAndroid Build Coastguard Worker * @node: the node to to use as the context node
12632*7c568831SAndroid Build Coastguard Worker * @ctx: the XPath context
12633*7c568831SAndroid Build Coastguard Worker *
12634*7c568831SAndroid Build Coastguard Worker * Sets 'node' as the context node. The node must be in the same
12635*7c568831SAndroid Build Coastguard Worker * document as that associated with the context.
12636*7c568831SAndroid Build Coastguard Worker *
12637*7c568831SAndroid Build Coastguard Worker * Returns -1 in case of error or 0 if successful
12638*7c568831SAndroid Build Coastguard Worker */
12639*7c568831SAndroid Build Coastguard Worker int
xmlXPathSetContextNode(xmlNodePtr node,xmlXPathContextPtr ctx)12640*7c568831SAndroid Build Coastguard Worker xmlXPathSetContextNode(xmlNodePtr node, xmlXPathContextPtr ctx) {
12641*7c568831SAndroid Build Coastguard Worker if ((node == NULL) || (ctx == NULL))
12642*7c568831SAndroid Build Coastguard Worker return(-1);
12643*7c568831SAndroid Build Coastguard Worker
12644*7c568831SAndroid Build Coastguard Worker if (node->doc == ctx->doc) {
12645*7c568831SAndroid Build Coastguard Worker ctx->node = node;
12646*7c568831SAndroid Build Coastguard Worker return(0);
12647*7c568831SAndroid Build Coastguard Worker }
12648*7c568831SAndroid Build Coastguard Worker return(-1);
12649*7c568831SAndroid Build Coastguard Worker }
12650*7c568831SAndroid Build Coastguard Worker
12651*7c568831SAndroid Build Coastguard Worker /**
12652*7c568831SAndroid Build Coastguard Worker * xmlXPathNodeEval:
12653*7c568831SAndroid Build Coastguard Worker * @node: the node to to use as the context node
12654*7c568831SAndroid Build Coastguard Worker * @str: the XPath expression
12655*7c568831SAndroid Build Coastguard Worker * @ctx: the XPath context
12656*7c568831SAndroid Build Coastguard Worker *
12657*7c568831SAndroid Build Coastguard Worker * Evaluate the XPath Location Path in the given context. The node 'node'
12658*7c568831SAndroid Build Coastguard Worker * is set as the context node. The context node is not restored.
12659*7c568831SAndroid Build Coastguard Worker *
12660*7c568831SAndroid Build Coastguard Worker * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
12661*7c568831SAndroid Build Coastguard Worker * the caller has to free the object.
12662*7c568831SAndroid Build Coastguard Worker */
12663*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathNodeEval(xmlNodePtr node,const xmlChar * str,xmlXPathContextPtr ctx)12664*7c568831SAndroid Build Coastguard Worker xmlXPathNodeEval(xmlNodePtr node, const xmlChar *str, xmlXPathContextPtr ctx) {
12665*7c568831SAndroid Build Coastguard Worker if (str == NULL)
12666*7c568831SAndroid Build Coastguard Worker return(NULL);
12667*7c568831SAndroid Build Coastguard Worker if (xmlXPathSetContextNode(node, ctx) < 0)
12668*7c568831SAndroid Build Coastguard Worker return(NULL);
12669*7c568831SAndroid Build Coastguard Worker return(xmlXPathEval(str, ctx));
12670*7c568831SAndroid Build Coastguard Worker }
12671*7c568831SAndroid Build Coastguard Worker
12672*7c568831SAndroid Build Coastguard Worker /**
12673*7c568831SAndroid Build Coastguard Worker * xmlXPathEvalExpression:
12674*7c568831SAndroid Build Coastguard Worker * @str: the XPath expression
12675*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath context
12676*7c568831SAndroid Build Coastguard Worker *
12677*7c568831SAndroid Build Coastguard Worker * Alias for xmlXPathEval().
12678*7c568831SAndroid Build Coastguard Worker *
12679*7c568831SAndroid Build Coastguard Worker * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
12680*7c568831SAndroid Build Coastguard Worker * the caller has to free the object.
12681*7c568831SAndroid Build Coastguard Worker */
12682*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathEvalExpression(const xmlChar * str,xmlXPathContextPtr ctxt)12683*7c568831SAndroid Build Coastguard Worker xmlXPathEvalExpression(const xmlChar *str, xmlXPathContextPtr ctxt) {
12684*7c568831SAndroid Build Coastguard Worker return(xmlXPathEval(str, ctxt));
12685*7c568831SAndroid Build Coastguard Worker }
12686*7c568831SAndroid Build Coastguard Worker
12687*7c568831SAndroid Build Coastguard Worker /************************************************************************
12688*7c568831SAndroid Build Coastguard Worker * *
12689*7c568831SAndroid Build Coastguard Worker * Extra functions not pertaining to the XPath spec *
12690*7c568831SAndroid Build Coastguard Worker * *
12691*7c568831SAndroid Build Coastguard Worker ************************************************************************/
12692*7c568831SAndroid Build Coastguard Worker /**
12693*7c568831SAndroid Build Coastguard Worker * xmlXPathEscapeUriFunction:
12694*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
12695*7c568831SAndroid Build Coastguard Worker * @nargs: the number of arguments
12696*7c568831SAndroid Build Coastguard Worker *
12697*7c568831SAndroid Build Coastguard Worker * Implement the escape-uri() XPath function
12698*7c568831SAndroid Build Coastguard Worker * string escape-uri(string $str, bool $escape-reserved)
12699*7c568831SAndroid Build Coastguard Worker *
12700*7c568831SAndroid Build Coastguard Worker * This function applies the URI escaping rules defined in section 2 of [RFC
12701*7c568831SAndroid Build Coastguard Worker * 2396] to the string supplied as $uri-part, which typically represents all
12702*7c568831SAndroid Build Coastguard Worker * or part of a URI. The effect of the function is to replace any special
12703*7c568831SAndroid Build Coastguard Worker * character in the string by an escape sequence of the form %xx%yy...,
12704*7c568831SAndroid Build Coastguard Worker * where xxyy... is the hexadecimal representation of the octets used to
12705*7c568831SAndroid Build Coastguard Worker * represent the character in UTF-8.
12706*7c568831SAndroid Build Coastguard Worker *
12707*7c568831SAndroid Build Coastguard Worker * The set of characters that are escaped depends on the setting of the
12708*7c568831SAndroid Build Coastguard Worker * boolean argument $escape-reserved.
12709*7c568831SAndroid Build Coastguard Worker *
12710*7c568831SAndroid Build Coastguard Worker * If $escape-reserved is true, all characters are escaped other than lower
12711*7c568831SAndroid Build Coastguard Worker * case letters a-z, upper case letters A-Z, digits 0-9, and the characters
12712*7c568831SAndroid Build Coastguard Worker * referred to in [RFC 2396] as "marks": specifically, "-" | "_" | "." | "!"
12713*7c568831SAndroid Build Coastguard Worker * | "~" | "*" | "'" | "(" | ")". The "%" character itself is escaped only
12714*7c568831SAndroid Build Coastguard Worker * if it is not followed by two hexadecimal digits (that is, 0-9, a-f, and
12715*7c568831SAndroid Build Coastguard Worker * A-F).
12716*7c568831SAndroid Build Coastguard Worker *
12717*7c568831SAndroid Build Coastguard Worker * If $escape-reserved is false, the behavior differs in that characters
12718*7c568831SAndroid Build Coastguard Worker * referred to in [RFC 2396] as reserved characters are not escaped. These
12719*7c568831SAndroid Build Coastguard Worker * characters are ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ",".
12720*7c568831SAndroid Build Coastguard Worker *
12721*7c568831SAndroid Build Coastguard Worker * [RFC 2396] does not define whether escaped URIs should use lower case or
12722*7c568831SAndroid Build Coastguard Worker * upper case for hexadecimal digits. To ensure that escaped URIs can be
12723*7c568831SAndroid Build Coastguard Worker * compared using string comparison functions, this function must always use
12724*7c568831SAndroid Build Coastguard Worker * the upper-case letters A-F.
12725*7c568831SAndroid Build Coastguard Worker *
12726*7c568831SAndroid Build Coastguard Worker * Generally, $escape-reserved should be set to true when escaping a string
12727*7c568831SAndroid Build Coastguard Worker * that is to form a single part of a URI, and to false when escaping an
12728*7c568831SAndroid Build Coastguard Worker * entire URI or URI reference.
12729*7c568831SAndroid Build Coastguard Worker *
12730*7c568831SAndroid Build Coastguard Worker * In the case of non-ascii characters, the string is encoded according to
12731*7c568831SAndroid Build Coastguard Worker * utf-8 and then converted according to RFC 2396.
12732*7c568831SAndroid Build Coastguard Worker *
12733*7c568831SAndroid Build Coastguard Worker * Examples
12734*7c568831SAndroid Build Coastguard Worker * xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles#ocean"), true())
12735*7c568831SAndroid Build Coastguard Worker * returns "gopher%3A%2F%2Fspinaltap.micro.umn.edu%2F00%2FWeather%2FCalifornia%2FLos%20Angeles%23ocean"
12736*7c568831SAndroid Build Coastguard Worker * xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles#ocean"), false())
12737*7c568831SAndroid Build Coastguard Worker * returns "gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles%23ocean"
12738*7c568831SAndroid Build Coastguard Worker *
12739*7c568831SAndroid Build Coastguard Worker */
12740*7c568831SAndroid Build Coastguard Worker static void
xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt,int nargs)12741*7c568831SAndroid Build Coastguard Worker xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt, int nargs) {
12742*7c568831SAndroid Build Coastguard Worker xmlXPathObjectPtr str;
12743*7c568831SAndroid Build Coastguard Worker int escape_reserved;
12744*7c568831SAndroid Build Coastguard Worker xmlBufPtr target;
12745*7c568831SAndroid Build Coastguard Worker xmlChar *cptr;
12746*7c568831SAndroid Build Coastguard Worker xmlChar escape[4];
12747*7c568831SAndroid Build Coastguard Worker
12748*7c568831SAndroid Build Coastguard Worker CHECK_ARITY(2);
12749*7c568831SAndroid Build Coastguard Worker
12750*7c568831SAndroid Build Coastguard Worker escape_reserved = xmlXPathPopBoolean(ctxt);
12751*7c568831SAndroid Build Coastguard Worker
12752*7c568831SAndroid Build Coastguard Worker CAST_TO_STRING;
12753*7c568831SAndroid Build Coastguard Worker str = valuePop(ctxt);
12754*7c568831SAndroid Build Coastguard Worker
12755*7c568831SAndroid Build Coastguard Worker target = xmlBufCreate(50);
12756*7c568831SAndroid Build Coastguard Worker
12757*7c568831SAndroid Build Coastguard Worker escape[0] = '%';
12758*7c568831SAndroid Build Coastguard Worker escape[3] = 0;
12759*7c568831SAndroid Build Coastguard Worker
12760*7c568831SAndroid Build Coastguard Worker if (target) {
12761*7c568831SAndroid Build Coastguard Worker for (cptr = str->stringval; *cptr; cptr++) {
12762*7c568831SAndroid Build Coastguard Worker if ((*cptr >= 'A' && *cptr <= 'Z') ||
12763*7c568831SAndroid Build Coastguard Worker (*cptr >= 'a' && *cptr <= 'z') ||
12764*7c568831SAndroid Build Coastguard Worker (*cptr >= '0' && *cptr <= '9') ||
12765*7c568831SAndroid Build Coastguard Worker *cptr == '-' || *cptr == '_' || *cptr == '.' ||
12766*7c568831SAndroid Build Coastguard Worker *cptr == '!' || *cptr == '~' || *cptr == '*' ||
12767*7c568831SAndroid Build Coastguard Worker *cptr == '\''|| *cptr == '(' || *cptr == ')' ||
12768*7c568831SAndroid Build Coastguard Worker (*cptr == '%' &&
12769*7c568831SAndroid Build Coastguard Worker ((cptr[1] >= 'A' && cptr[1] <= 'F') ||
12770*7c568831SAndroid Build Coastguard Worker (cptr[1] >= 'a' && cptr[1] <= 'f') ||
12771*7c568831SAndroid Build Coastguard Worker (cptr[1] >= '0' && cptr[1] <= '9')) &&
12772*7c568831SAndroid Build Coastguard Worker ((cptr[2] >= 'A' && cptr[2] <= 'F') ||
12773*7c568831SAndroid Build Coastguard Worker (cptr[2] >= 'a' && cptr[2] <= 'f') ||
12774*7c568831SAndroid Build Coastguard Worker (cptr[2] >= '0' && cptr[2] <= '9'))) ||
12775*7c568831SAndroid Build Coastguard Worker (!escape_reserved &&
12776*7c568831SAndroid Build Coastguard Worker (*cptr == ';' || *cptr == '/' || *cptr == '?' ||
12777*7c568831SAndroid Build Coastguard Worker *cptr == ':' || *cptr == '@' || *cptr == '&' ||
12778*7c568831SAndroid Build Coastguard Worker *cptr == '=' || *cptr == '+' || *cptr == '$' ||
12779*7c568831SAndroid Build Coastguard Worker *cptr == ','))) {
12780*7c568831SAndroid Build Coastguard Worker xmlBufAdd(target, cptr, 1);
12781*7c568831SAndroid Build Coastguard Worker } else {
12782*7c568831SAndroid Build Coastguard Worker if ((*cptr >> 4) < 10)
12783*7c568831SAndroid Build Coastguard Worker escape[1] = '0' + (*cptr >> 4);
12784*7c568831SAndroid Build Coastguard Worker else
12785*7c568831SAndroid Build Coastguard Worker escape[1] = 'A' - 10 + (*cptr >> 4);
12786*7c568831SAndroid Build Coastguard Worker if ((*cptr & 0xF) < 10)
12787*7c568831SAndroid Build Coastguard Worker escape[2] = '0' + (*cptr & 0xF);
12788*7c568831SAndroid Build Coastguard Worker else
12789*7c568831SAndroid Build Coastguard Worker escape[2] = 'A' - 10 + (*cptr & 0xF);
12790*7c568831SAndroid Build Coastguard Worker
12791*7c568831SAndroid Build Coastguard Worker xmlBufAdd(target, &escape[0], 3);
12792*7c568831SAndroid Build Coastguard Worker }
12793*7c568831SAndroid Build Coastguard Worker }
12794*7c568831SAndroid Build Coastguard Worker }
12795*7c568831SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewString(ctxt, xmlBufContent(target)));
12796*7c568831SAndroid Build Coastguard Worker xmlBufFree(target);
12797*7c568831SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, str);
12798*7c568831SAndroid Build Coastguard Worker }
12799*7c568831SAndroid Build Coastguard Worker
12800*7c568831SAndroid Build Coastguard Worker /**
12801*7c568831SAndroid Build Coastguard Worker * xmlXPathRegisterAllFunctions:
12802*7c568831SAndroid Build Coastguard Worker * @ctxt: the XPath context
12803*7c568831SAndroid Build Coastguard Worker *
12804*7c568831SAndroid Build Coastguard Worker * Registers all default XPath functions in this context
12805*7c568831SAndroid Build Coastguard Worker */
12806*7c568831SAndroid Build Coastguard Worker void
xmlXPathRegisterAllFunctions(xmlXPathContextPtr ctxt)12807*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterAllFunctions(xmlXPathContextPtr ctxt)
12808*7c568831SAndroid Build Coastguard Worker {
12809*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"boolean",
12810*7c568831SAndroid Build Coastguard Worker xmlXPathBooleanFunction);
12811*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"ceiling",
12812*7c568831SAndroid Build Coastguard Worker xmlXPathCeilingFunction);
12813*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"count",
12814*7c568831SAndroid Build Coastguard Worker xmlXPathCountFunction);
12815*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"concat",
12816*7c568831SAndroid Build Coastguard Worker xmlXPathConcatFunction);
12817*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"contains",
12818*7c568831SAndroid Build Coastguard Worker xmlXPathContainsFunction);
12819*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"id",
12820*7c568831SAndroid Build Coastguard Worker xmlXPathIdFunction);
12821*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"false",
12822*7c568831SAndroid Build Coastguard Worker xmlXPathFalseFunction);
12823*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"floor",
12824*7c568831SAndroid Build Coastguard Worker xmlXPathFloorFunction);
12825*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"last",
12826*7c568831SAndroid Build Coastguard Worker xmlXPathLastFunction);
12827*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"lang",
12828*7c568831SAndroid Build Coastguard Worker xmlXPathLangFunction);
12829*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"local-name",
12830*7c568831SAndroid Build Coastguard Worker xmlXPathLocalNameFunction);
12831*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"not",
12832*7c568831SAndroid Build Coastguard Worker xmlXPathNotFunction);
12833*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"name",
12834*7c568831SAndroid Build Coastguard Worker xmlXPathNameFunction);
12835*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"namespace-uri",
12836*7c568831SAndroid Build Coastguard Worker xmlXPathNamespaceURIFunction);
12837*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"normalize-space",
12838*7c568831SAndroid Build Coastguard Worker xmlXPathNormalizeFunction);
12839*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"number",
12840*7c568831SAndroid Build Coastguard Worker xmlXPathNumberFunction);
12841*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"position",
12842*7c568831SAndroid Build Coastguard Worker xmlXPathPositionFunction);
12843*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"round",
12844*7c568831SAndroid Build Coastguard Worker xmlXPathRoundFunction);
12845*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"string",
12846*7c568831SAndroid Build Coastguard Worker xmlXPathStringFunction);
12847*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"string-length",
12848*7c568831SAndroid Build Coastguard Worker xmlXPathStringLengthFunction);
12849*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"starts-with",
12850*7c568831SAndroid Build Coastguard Worker xmlXPathStartsWithFunction);
12851*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring",
12852*7c568831SAndroid Build Coastguard Worker xmlXPathSubstringFunction);
12853*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring-before",
12854*7c568831SAndroid Build Coastguard Worker xmlXPathSubstringBeforeFunction);
12855*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring-after",
12856*7c568831SAndroid Build Coastguard Worker xmlXPathSubstringAfterFunction);
12857*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"sum",
12858*7c568831SAndroid Build Coastguard Worker xmlXPathSumFunction);
12859*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"true",
12860*7c568831SAndroid Build Coastguard Worker xmlXPathTrueFunction);
12861*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"translate",
12862*7c568831SAndroid Build Coastguard Worker xmlXPathTranslateFunction);
12863*7c568831SAndroid Build Coastguard Worker
12864*7c568831SAndroid Build Coastguard Worker xmlXPathRegisterFuncNS(ctxt, (const xmlChar *)"escape-uri",
12865*7c568831SAndroid Build Coastguard Worker (const xmlChar *)"http://www.w3.org/2002/08/xquery-functions",
12866*7c568831SAndroid Build Coastguard Worker xmlXPathEscapeUriFunction);
12867*7c568831SAndroid Build Coastguard Worker }
12868*7c568831SAndroid Build Coastguard Worker
12869*7c568831SAndroid Build Coastguard Worker #endif /* LIBXML_XPATH_ENABLED */
12870