1*6777b538SAndroid Build Coastguard Worker /*
2*6777b538SAndroid Build Coastguard Worker * xpath.c: XML Path Language implementation
3*6777b538SAndroid Build Coastguard Worker * XPath is a language for addressing parts of an XML document,
4*6777b538SAndroid Build Coastguard Worker * designed to be used by both XSLT and XPointer
5*6777b538SAndroid Build Coastguard Worker *
6*6777b538SAndroid Build Coastguard Worker * Reference: W3C Recommendation 16 November 1999
7*6777b538SAndroid Build Coastguard Worker * http://www.w3.org/TR/1999/REC-xpath-19991116
8*6777b538SAndroid Build Coastguard Worker * Public reference:
9*6777b538SAndroid Build Coastguard Worker * http://www.w3.org/TR/xpath
10*6777b538SAndroid Build Coastguard Worker *
11*6777b538SAndroid Build Coastguard Worker * See Copyright for the status of this software
12*6777b538SAndroid Build Coastguard Worker *
13*6777b538SAndroid Build Coastguard Worker * Author: [email protected]
14*6777b538SAndroid Build Coastguard Worker *
15*6777b538SAndroid Build Coastguard Worker */
16*6777b538SAndroid Build Coastguard Worker
17*6777b538SAndroid Build Coastguard Worker /* To avoid EBCDIC trouble when parsing on zOS */
18*6777b538SAndroid Build Coastguard Worker #if defined(__MVS__)
19*6777b538SAndroid Build Coastguard Worker #pragma convert("ISO8859-1")
20*6777b538SAndroid Build Coastguard Worker #endif
21*6777b538SAndroid Build Coastguard Worker
22*6777b538SAndroid Build Coastguard Worker #define IN_LIBXML
23*6777b538SAndroid Build Coastguard Worker #include "libxml.h"
24*6777b538SAndroid Build Coastguard Worker
25*6777b538SAndroid Build Coastguard Worker #include <limits.h>
26*6777b538SAndroid Build Coastguard Worker #include <string.h>
27*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
28*6777b538SAndroid Build Coastguard Worker #include <math.h>
29*6777b538SAndroid Build Coastguard Worker #include <float.h>
30*6777b538SAndroid Build Coastguard Worker #include <ctype.h>
31*6777b538SAndroid Build Coastguard Worker
32*6777b538SAndroid Build Coastguard Worker #include <libxml/xmlmemory.h>
33*6777b538SAndroid Build Coastguard Worker #include <libxml/tree.h>
34*6777b538SAndroid Build Coastguard Worker #include <libxml/xpath.h>
35*6777b538SAndroid Build Coastguard Worker #include <libxml/xpathInternals.h>
36*6777b538SAndroid Build Coastguard Worker #include <libxml/parserInternals.h>
37*6777b538SAndroid Build Coastguard Worker #include <libxml/hash.h>
38*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
39*6777b538SAndroid Build Coastguard Worker #include <libxml/xpointer.h>
40*6777b538SAndroid Build Coastguard Worker #endif
41*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_DEBUG_ENABLED
42*6777b538SAndroid Build Coastguard Worker #include <libxml/debugXML.h>
43*6777b538SAndroid Build Coastguard Worker #endif
44*6777b538SAndroid Build Coastguard Worker #include <libxml/xmlerror.h>
45*6777b538SAndroid Build Coastguard Worker #include <libxml/threads.h>
46*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_PATTERN_ENABLED
47*6777b538SAndroid Build Coastguard Worker #include <libxml/pattern.h>
48*6777b538SAndroid Build Coastguard Worker #endif
49*6777b538SAndroid Build Coastguard Worker
50*6777b538SAndroid Build Coastguard Worker #include "private/buf.h"
51*6777b538SAndroid Build Coastguard Worker #include "private/error.h"
52*6777b538SAndroid Build Coastguard Worker #include "private/xpath.h"
53*6777b538SAndroid Build Coastguard Worker
54*6777b538SAndroid Build Coastguard Worker /* Disabled for now */
55*6777b538SAndroid Build Coastguard Worker #if 0
56*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_PATTERN_ENABLED
57*6777b538SAndroid Build Coastguard Worker #define XPATH_STREAMING
58*6777b538SAndroid Build Coastguard Worker #endif
59*6777b538SAndroid Build Coastguard Worker #endif
60*6777b538SAndroid Build Coastguard Worker
61*6777b538SAndroid Build Coastguard Worker /**
62*6777b538SAndroid Build Coastguard Worker * WITH_TIM_SORT:
63*6777b538SAndroid Build Coastguard Worker *
64*6777b538SAndroid Build Coastguard Worker * Use the Timsort algorithm provided in timsort.h to sort
65*6777b538SAndroid Build Coastguard Worker * nodeset as this is a great improvement over the old Shell sort
66*6777b538SAndroid Build Coastguard Worker * used in xmlXPathNodeSetSort()
67*6777b538SAndroid Build Coastguard Worker */
68*6777b538SAndroid Build Coastguard Worker #define WITH_TIM_SORT
69*6777b538SAndroid Build Coastguard Worker
70*6777b538SAndroid Build Coastguard Worker /*
71*6777b538SAndroid Build Coastguard Worker * XP_OPTIMIZED_NON_ELEM_COMPARISON:
72*6777b538SAndroid Build Coastguard Worker * If defined, this will use xmlXPathCmpNodesExt() instead of
73*6777b538SAndroid Build Coastguard Worker * xmlXPathCmpNodes(). The new function is optimized comparison of
74*6777b538SAndroid Build Coastguard Worker * non-element nodes; actually it will speed up comparison only if
75*6777b538SAndroid Build Coastguard Worker * xmlXPathOrderDocElems() was called in order to index the elements of
76*6777b538SAndroid Build Coastguard Worker * a tree in document order; Libxslt does such an indexing, thus it will
77*6777b538SAndroid Build Coastguard Worker * benefit from this optimization.
78*6777b538SAndroid Build Coastguard Worker */
79*6777b538SAndroid Build Coastguard Worker #define XP_OPTIMIZED_NON_ELEM_COMPARISON
80*6777b538SAndroid Build Coastguard Worker
81*6777b538SAndroid Build Coastguard Worker /*
82*6777b538SAndroid Build Coastguard Worker * XP_OPTIMIZED_FILTER_FIRST:
83*6777b538SAndroid Build Coastguard Worker * If defined, this will optimize expressions like "key('foo', 'val')[b][1]"
84*6777b538SAndroid Build Coastguard Worker * in a way, that it stop evaluation at the first node.
85*6777b538SAndroid Build Coastguard Worker */
86*6777b538SAndroid Build Coastguard Worker #define XP_OPTIMIZED_FILTER_FIRST
87*6777b538SAndroid Build Coastguard Worker
88*6777b538SAndroid Build Coastguard Worker /*
89*6777b538SAndroid Build Coastguard Worker * XPATH_MAX_STEPS:
90*6777b538SAndroid Build Coastguard Worker * when compiling an XPath expression we arbitrary limit the maximum
91*6777b538SAndroid Build Coastguard Worker * number of step operation in the compiled expression. 1000000 is
92*6777b538SAndroid Build Coastguard Worker * an insanely large value which should never be reached under normal
93*6777b538SAndroid Build Coastguard Worker * circumstances
94*6777b538SAndroid Build Coastguard Worker */
95*6777b538SAndroid Build Coastguard Worker #define XPATH_MAX_STEPS 1000000
96*6777b538SAndroid Build Coastguard Worker
97*6777b538SAndroid Build Coastguard Worker /*
98*6777b538SAndroid Build Coastguard Worker * XPATH_MAX_STACK_DEPTH:
99*6777b538SAndroid Build Coastguard Worker * when evaluating an XPath expression we arbitrary limit the maximum
100*6777b538SAndroid Build Coastguard Worker * number of object allowed to be pushed on the stack. 1000000 is
101*6777b538SAndroid Build Coastguard Worker * an insanely large value which should never be reached under normal
102*6777b538SAndroid Build Coastguard Worker * circumstances
103*6777b538SAndroid Build Coastguard Worker */
104*6777b538SAndroid Build Coastguard Worker #define XPATH_MAX_STACK_DEPTH 1000000
105*6777b538SAndroid Build Coastguard Worker
106*6777b538SAndroid Build Coastguard Worker /*
107*6777b538SAndroid Build Coastguard Worker * XPATH_MAX_NODESET_LENGTH:
108*6777b538SAndroid Build Coastguard Worker * when evaluating an XPath expression nodesets are created and we
109*6777b538SAndroid Build Coastguard Worker * arbitrary limit the maximum length of those node set. 10000000 is
110*6777b538SAndroid Build Coastguard Worker * an insanely large value which should never be reached under normal
111*6777b538SAndroid Build Coastguard Worker * circumstances, one would first need to construct an in memory tree
112*6777b538SAndroid Build Coastguard Worker * with more than 10 millions nodes.
113*6777b538SAndroid Build Coastguard Worker */
114*6777b538SAndroid Build Coastguard Worker #define XPATH_MAX_NODESET_LENGTH 10000000
115*6777b538SAndroid Build Coastguard Worker
116*6777b538SAndroid Build Coastguard Worker /*
117*6777b538SAndroid Build Coastguard Worker * XPATH_MAX_RECRUSION_DEPTH:
118*6777b538SAndroid Build Coastguard Worker * Maximum amount of nested functions calls when parsing or evaluating
119*6777b538SAndroid Build Coastguard Worker * expressions
120*6777b538SAndroid Build Coastguard Worker */
121*6777b538SAndroid Build Coastguard Worker #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
122*6777b538SAndroid Build Coastguard Worker #define XPATH_MAX_RECURSION_DEPTH 500
123*6777b538SAndroid Build Coastguard Worker #elif defined(_WIN32)
124*6777b538SAndroid Build Coastguard Worker /* Windows typically limits stack size to 1MB. */
125*6777b538SAndroid Build Coastguard Worker #define XPATH_MAX_RECURSION_DEPTH 1000
126*6777b538SAndroid Build Coastguard Worker #else
127*6777b538SAndroid Build Coastguard Worker #define XPATH_MAX_RECURSION_DEPTH 5000
128*6777b538SAndroid Build Coastguard Worker #endif
129*6777b538SAndroid Build Coastguard Worker
130*6777b538SAndroid Build Coastguard Worker /*
131*6777b538SAndroid Build Coastguard Worker * TODO:
132*6777b538SAndroid Build Coastguard Worker * There are a few spots where some tests are done which depend upon ascii
133*6777b538SAndroid Build Coastguard Worker * data. These should be enhanced for full UTF8 support (see particularly
134*6777b538SAndroid Build Coastguard Worker * any use of the macros IS_ASCII_CHARACTER and IS_ASCII_DIGIT)
135*6777b538SAndroid Build Coastguard Worker */
136*6777b538SAndroid Build Coastguard Worker
137*6777b538SAndroid Build Coastguard Worker #if defined(LIBXML_XPATH_ENABLED) || defined(LIBXML_SCHEMAS_ENABLED)
138*6777b538SAndroid Build Coastguard Worker
139*6777b538SAndroid Build Coastguard Worker /************************************************************************
140*6777b538SAndroid Build Coastguard Worker * *
141*6777b538SAndroid Build Coastguard Worker * Floating point stuff *
142*6777b538SAndroid Build Coastguard Worker * *
143*6777b538SAndroid Build Coastguard Worker ************************************************************************/
144*6777b538SAndroid Build Coastguard Worker
145*6777b538SAndroid Build Coastguard Worker double xmlXPathNAN = 0.0;
146*6777b538SAndroid Build Coastguard Worker double xmlXPathPINF = 0.0;
147*6777b538SAndroid Build Coastguard Worker double xmlXPathNINF = 0.0;
148*6777b538SAndroid Build Coastguard Worker
149*6777b538SAndroid Build Coastguard Worker /**
150*6777b538SAndroid Build Coastguard Worker * xmlXPathInit:
151*6777b538SAndroid Build Coastguard Worker *
152*6777b538SAndroid Build Coastguard Worker * DEPRECATED: Alias for xmlInitParser.
153*6777b538SAndroid Build Coastguard Worker */
154*6777b538SAndroid Build Coastguard Worker void
xmlXPathInit(void)155*6777b538SAndroid Build Coastguard Worker xmlXPathInit(void) {
156*6777b538SAndroid Build Coastguard Worker xmlInitParser();
157*6777b538SAndroid Build Coastguard Worker }
158*6777b538SAndroid Build Coastguard Worker
159*6777b538SAndroid Build Coastguard Worker /**
160*6777b538SAndroid Build Coastguard Worker * xmlInitXPathInternal:
161*6777b538SAndroid Build Coastguard Worker *
162*6777b538SAndroid Build Coastguard Worker * Initialize the XPath environment
163*6777b538SAndroid Build Coastguard Worker */
164*6777b538SAndroid Build Coastguard Worker ATTRIBUTE_NO_SANITIZE("float-divide-by-zero")
165*6777b538SAndroid Build Coastguard Worker void
xmlInitXPathInternal(void)166*6777b538SAndroid Build Coastguard Worker xmlInitXPathInternal(void) {
167*6777b538SAndroid Build Coastguard Worker #if defined(NAN) && defined(INFINITY)
168*6777b538SAndroid Build Coastguard Worker xmlXPathNAN = NAN;
169*6777b538SAndroid Build Coastguard Worker xmlXPathPINF = INFINITY;
170*6777b538SAndroid Build Coastguard Worker xmlXPathNINF = -INFINITY;
171*6777b538SAndroid Build Coastguard Worker #else
172*6777b538SAndroid Build Coastguard Worker /* MSVC doesn't allow division by zero in constant expressions. */
173*6777b538SAndroid Build Coastguard Worker double zero = 0.0;
174*6777b538SAndroid Build Coastguard Worker xmlXPathNAN = 0.0 / zero;
175*6777b538SAndroid Build Coastguard Worker xmlXPathPINF = 1.0 / zero;
176*6777b538SAndroid Build Coastguard Worker xmlXPathNINF = -xmlXPathPINF;
177*6777b538SAndroid Build Coastguard Worker #endif
178*6777b538SAndroid Build Coastguard Worker }
179*6777b538SAndroid Build Coastguard Worker
180*6777b538SAndroid Build Coastguard Worker /**
181*6777b538SAndroid Build Coastguard Worker * xmlXPathIsNaN:
182*6777b538SAndroid Build Coastguard Worker * @val: a double value
183*6777b538SAndroid Build Coastguard Worker *
184*6777b538SAndroid Build Coastguard Worker * Checks whether a double is a NaN.
185*6777b538SAndroid Build Coastguard Worker *
186*6777b538SAndroid Build Coastguard Worker * Returns 1 if the value is a NaN, 0 otherwise
187*6777b538SAndroid Build Coastguard Worker */
188*6777b538SAndroid Build Coastguard Worker int
xmlXPathIsNaN(double val)189*6777b538SAndroid Build Coastguard Worker xmlXPathIsNaN(double val) {
190*6777b538SAndroid Build Coastguard Worker #ifdef isnan
191*6777b538SAndroid Build Coastguard Worker return isnan(val);
192*6777b538SAndroid Build Coastguard Worker #else
193*6777b538SAndroid Build Coastguard Worker return !(val == val);
194*6777b538SAndroid Build Coastguard Worker #endif
195*6777b538SAndroid Build Coastguard Worker }
196*6777b538SAndroid Build Coastguard Worker
197*6777b538SAndroid Build Coastguard Worker /**
198*6777b538SAndroid Build Coastguard Worker * xmlXPathIsInf:
199*6777b538SAndroid Build Coastguard Worker * @val: a double value
200*6777b538SAndroid Build Coastguard Worker *
201*6777b538SAndroid Build Coastguard Worker * Checks whether a double is an infinity.
202*6777b538SAndroid Build Coastguard Worker *
203*6777b538SAndroid Build Coastguard Worker * Returns 1 if the value is +Infinite, -1 if -Infinite, 0 otherwise
204*6777b538SAndroid Build Coastguard Worker */
205*6777b538SAndroid Build Coastguard Worker int
xmlXPathIsInf(double val)206*6777b538SAndroid Build Coastguard Worker xmlXPathIsInf(double val) {
207*6777b538SAndroid Build Coastguard Worker #ifdef isinf
208*6777b538SAndroid Build Coastguard Worker return isinf(val) ? (val > 0 ? 1 : -1) : 0;
209*6777b538SAndroid Build Coastguard Worker #else
210*6777b538SAndroid Build Coastguard Worker if (val >= xmlXPathPINF)
211*6777b538SAndroid Build Coastguard Worker return 1;
212*6777b538SAndroid Build Coastguard Worker if (val <= -xmlXPathPINF)
213*6777b538SAndroid Build Coastguard Worker return -1;
214*6777b538SAndroid Build Coastguard Worker return 0;
215*6777b538SAndroid Build Coastguard Worker #endif
216*6777b538SAndroid Build Coastguard Worker }
217*6777b538SAndroid Build Coastguard Worker
218*6777b538SAndroid Build Coastguard Worker #endif /* SCHEMAS or XPATH */
219*6777b538SAndroid Build Coastguard Worker
220*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPATH_ENABLED
221*6777b538SAndroid Build Coastguard Worker
222*6777b538SAndroid Build Coastguard Worker /*
223*6777b538SAndroid Build Coastguard Worker * TODO: when compatibility allows remove all "fake node libxslt" strings
224*6777b538SAndroid Build Coastguard Worker * the test should just be name[0] = ' '
225*6777b538SAndroid Build Coastguard Worker */
226*6777b538SAndroid Build Coastguard Worker
227*6777b538SAndroid Build Coastguard Worker static xmlNs xmlXPathXMLNamespaceStruct = {
228*6777b538SAndroid Build Coastguard Worker NULL,
229*6777b538SAndroid Build Coastguard Worker XML_NAMESPACE_DECL,
230*6777b538SAndroid Build Coastguard Worker XML_XML_NAMESPACE,
231*6777b538SAndroid Build Coastguard Worker BAD_CAST "xml",
232*6777b538SAndroid Build Coastguard Worker NULL,
233*6777b538SAndroid Build Coastguard Worker NULL
234*6777b538SAndroid Build Coastguard Worker };
235*6777b538SAndroid Build Coastguard Worker static xmlNsPtr xmlXPathXMLNamespace = &xmlXPathXMLNamespaceStruct;
236*6777b538SAndroid Build Coastguard Worker #ifndef LIBXML_THREAD_ENABLED
237*6777b538SAndroid Build Coastguard Worker /*
238*6777b538SAndroid Build Coastguard Worker * Optimizer is disabled only when threaded apps are detected while
239*6777b538SAndroid Build Coastguard Worker * the library ain't compiled for thread safety.
240*6777b538SAndroid Build Coastguard Worker */
241*6777b538SAndroid Build Coastguard Worker static int xmlXPathDisableOptimizer = 0;
242*6777b538SAndroid Build Coastguard Worker #endif
243*6777b538SAndroid Build Coastguard Worker
244*6777b538SAndroid Build Coastguard Worker static void
245*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetClear(xmlNodeSetPtr set, int hasNsNodes);
246*6777b538SAndroid Build Coastguard Worker
247*6777b538SAndroid Build Coastguard Worker #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
248*6777b538SAndroid Build Coastguard Worker /**
249*6777b538SAndroid Build Coastguard Worker * xmlXPathCmpNodesExt:
250*6777b538SAndroid Build Coastguard Worker * @node1: the first node
251*6777b538SAndroid Build Coastguard Worker * @node2: the second node
252*6777b538SAndroid Build Coastguard Worker *
253*6777b538SAndroid Build Coastguard Worker * Compare two nodes w.r.t document order.
254*6777b538SAndroid Build Coastguard Worker * This one is optimized for handling of non-element nodes.
255*6777b538SAndroid Build Coastguard Worker *
256*6777b538SAndroid Build Coastguard Worker * Returns -2 in case of error 1 if first point < second point, 0 if
257*6777b538SAndroid Build Coastguard Worker * it's the same node, -1 otherwise
258*6777b538SAndroid Build Coastguard Worker */
259*6777b538SAndroid Build Coastguard Worker static int
xmlXPathCmpNodesExt(xmlNodePtr node1,xmlNodePtr node2)260*6777b538SAndroid Build Coastguard Worker xmlXPathCmpNodesExt(xmlNodePtr node1, xmlNodePtr node2) {
261*6777b538SAndroid Build Coastguard Worker int depth1, depth2;
262*6777b538SAndroid Build Coastguard Worker int misc = 0, precedence1 = 0, precedence2 = 0;
263*6777b538SAndroid Build Coastguard Worker xmlNodePtr miscNode1 = NULL, miscNode2 = NULL;
264*6777b538SAndroid Build Coastguard Worker xmlNodePtr cur, root;
265*6777b538SAndroid Build Coastguard Worker ptrdiff_t l1, l2;
266*6777b538SAndroid Build Coastguard Worker
267*6777b538SAndroid Build Coastguard Worker if ((node1 == NULL) || (node2 == NULL))
268*6777b538SAndroid Build Coastguard Worker return(-2);
269*6777b538SAndroid Build Coastguard Worker
270*6777b538SAndroid Build Coastguard Worker if (node1 == node2)
271*6777b538SAndroid Build Coastguard Worker return(0);
272*6777b538SAndroid Build Coastguard Worker
273*6777b538SAndroid Build Coastguard Worker /*
274*6777b538SAndroid Build Coastguard Worker * a couple of optimizations which will avoid computations in most cases
275*6777b538SAndroid Build Coastguard Worker */
276*6777b538SAndroid Build Coastguard Worker switch (node1->type) {
277*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
278*6777b538SAndroid Build Coastguard Worker if (node2->type == XML_ELEMENT_NODE) {
279*6777b538SAndroid Build Coastguard Worker if ((0 > (ptrdiff_t) node1->content) &&
280*6777b538SAndroid Build Coastguard Worker (0 > (ptrdiff_t) node2->content) &&
281*6777b538SAndroid Build Coastguard Worker (node1->doc == node2->doc))
282*6777b538SAndroid Build Coastguard Worker {
283*6777b538SAndroid Build Coastguard Worker l1 = -((ptrdiff_t) node1->content);
284*6777b538SAndroid Build Coastguard Worker l2 = -((ptrdiff_t) node2->content);
285*6777b538SAndroid Build Coastguard Worker if (l1 < l2)
286*6777b538SAndroid Build Coastguard Worker return(1);
287*6777b538SAndroid Build Coastguard Worker if (l1 > l2)
288*6777b538SAndroid Build Coastguard Worker return(-1);
289*6777b538SAndroid Build Coastguard Worker } else
290*6777b538SAndroid Build Coastguard Worker goto turtle_comparison;
291*6777b538SAndroid Build Coastguard Worker }
292*6777b538SAndroid Build Coastguard Worker break;
293*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE:
294*6777b538SAndroid Build Coastguard Worker precedence1 = 1; /* element is owner */
295*6777b538SAndroid Build Coastguard Worker miscNode1 = node1;
296*6777b538SAndroid Build Coastguard Worker node1 = node1->parent;
297*6777b538SAndroid Build Coastguard Worker misc = 1;
298*6777b538SAndroid Build Coastguard Worker break;
299*6777b538SAndroid Build Coastguard Worker case XML_TEXT_NODE:
300*6777b538SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
301*6777b538SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
302*6777b538SAndroid Build Coastguard Worker case XML_PI_NODE: {
303*6777b538SAndroid Build Coastguard Worker miscNode1 = node1;
304*6777b538SAndroid Build Coastguard Worker /*
305*6777b538SAndroid Build Coastguard Worker * Find nearest element node.
306*6777b538SAndroid Build Coastguard Worker */
307*6777b538SAndroid Build Coastguard Worker if (node1->prev != NULL) {
308*6777b538SAndroid Build Coastguard Worker do {
309*6777b538SAndroid Build Coastguard Worker node1 = node1->prev;
310*6777b538SAndroid Build Coastguard Worker if (node1->type == XML_ELEMENT_NODE) {
311*6777b538SAndroid Build Coastguard Worker precedence1 = 3; /* element in prev-sibl axis */
312*6777b538SAndroid Build Coastguard Worker break;
313*6777b538SAndroid Build Coastguard Worker }
314*6777b538SAndroid Build Coastguard Worker if (node1->prev == NULL) {
315*6777b538SAndroid Build Coastguard Worker precedence1 = 2; /* element is parent */
316*6777b538SAndroid Build Coastguard Worker /*
317*6777b538SAndroid Build Coastguard Worker * URGENT TODO: Are there any cases, where the
318*6777b538SAndroid Build Coastguard Worker * parent of such a node is not an element node?
319*6777b538SAndroid Build Coastguard Worker */
320*6777b538SAndroid Build Coastguard Worker node1 = node1->parent;
321*6777b538SAndroid Build Coastguard Worker break;
322*6777b538SAndroid Build Coastguard Worker }
323*6777b538SAndroid Build Coastguard Worker } while (1);
324*6777b538SAndroid Build Coastguard Worker } else {
325*6777b538SAndroid Build Coastguard Worker precedence1 = 2; /* element is parent */
326*6777b538SAndroid Build Coastguard Worker node1 = node1->parent;
327*6777b538SAndroid Build Coastguard Worker }
328*6777b538SAndroid Build Coastguard Worker if ((node1 == NULL) || (node1->type != XML_ELEMENT_NODE) ||
329*6777b538SAndroid Build Coastguard Worker (0 <= (ptrdiff_t) node1->content)) {
330*6777b538SAndroid Build Coastguard Worker /*
331*6777b538SAndroid Build Coastguard Worker * Fallback for whatever case.
332*6777b538SAndroid Build Coastguard Worker */
333*6777b538SAndroid Build Coastguard Worker node1 = miscNode1;
334*6777b538SAndroid Build Coastguard Worker precedence1 = 0;
335*6777b538SAndroid Build Coastguard Worker } else
336*6777b538SAndroid Build Coastguard Worker misc = 1;
337*6777b538SAndroid Build Coastguard Worker }
338*6777b538SAndroid Build Coastguard Worker break;
339*6777b538SAndroid Build Coastguard Worker case XML_NAMESPACE_DECL:
340*6777b538SAndroid Build Coastguard Worker /*
341*6777b538SAndroid Build Coastguard Worker * TODO: why do we return 1 for namespace nodes?
342*6777b538SAndroid Build Coastguard Worker */
343*6777b538SAndroid Build Coastguard Worker return(1);
344*6777b538SAndroid Build Coastguard Worker default:
345*6777b538SAndroid Build Coastguard Worker break;
346*6777b538SAndroid Build Coastguard Worker }
347*6777b538SAndroid Build Coastguard Worker switch (node2->type) {
348*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
349*6777b538SAndroid Build Coastguard Worker break;
350*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE:
351*6777b538SAndroid Build Coastguard Worker precedence2 = 1; /* element is owner */
352*6777b538SAndroid Build Coastguard Worker miscNode2 = node2;
353*6777b538SAndroid Build Coastguard Worker node2 = node2->parent;
354*6777b538SAndroid Build Coastguard Worker misc = 1;
355*6777b538SAndroid Build Coastguard Worker break;
356*6777b538SAndroid Build Coastguard Worker case XML_TEXT_NODE:
357*6777b538SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
358*6777b538SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
359*6777b538SAndroid Build Coastguard Worker case XML_PI_NODE: {
360*6777b538SAndroid Build Coastguard Worker miscNode2 = node2;
361*6777b538SAndroid Build Coastguard Worker if (node2->prev != NULL) {
362*6777b538SAndroid Build Coastguard Worker do {
363*6777b538SAndroid Build Coastguard Worker node2 = node2->prev;
364*6777b538SAndroid Build Coastguard Worker if (node2->type == XML_ELEMENT_NODE) {
365*6777b538SAndroid Build Coastguard Worker precedence2 = 3; /* element in prev-sibl axis */
366*6777b538SAndroid Build Coastguard Worker break;
367*6777b538SAndroid Build Coastguard Worker }
368*6777b538SAndroid Build Coastguard Worker if (node2->prev == NULL) {
369*6777b538SAndroid Build Coastguard Worker precedence2 = 2; /* element is parent */
370*6777b538SAndroid Build Coastguard Worker node2 = node2->parent;
371*6777b538SAndroid Build Coastguard Worker break;
372*6777b538SAndroid Build Coastguard Worker }
373*6777b538SAndroid Build Coastguard Worker } while (1);
374*6777b538SAndroid Build Coastguard Worker } else {
375*6777b538SAndroid Build Coastguard Worker precedence2 = 2; /* element is parent */
376*6777b538SAndroid Build Coastguard Worker node2 = node2->parent;
377*6777b538SAndroid Build Coastguard Worker }
378*6777b538SAndroid Build Coastguard Worker if ((node2 == NULL) || (node2->type != XML_ELEMENT_NODE) ||
379*6777b538SAndroid Build Coastguard Worker (0 <= (ptrdiff_t) node2->content))
380*6777b538SAndroid Build Coastguard Worker {
381*6777b538SAndroid Build Coastguard Worker node2 = miscNode2;
382*6777b538SAndroid Build Coastguard Worker precedence2 = 0;
383*6777b538SAndroid Build Coastguard Worker } else
384*6777b538SAndroid Build Coastguard Worker misc = 1;
385*6777b538SAndroid Build Coastguard Worker }
386*6777b538SAndroid Build Coastguard Worker break;
387*6777b538SAndroid Build Coastguard Worker case XML_NAMESPACE_DECL:
388*6777b538SAndroid Build Coastguard Worker return(1);
389*6777b538SAndroid Build Coastguard Worker default:
390*6777b538SAndroid Build Coastguard Worker break;
391*6777b538SAndroid Build Coastguard Worker }
392*6777b538SAndroid Build Coastguard Worker if (misc) {
393*6777b538SAndroid Build Coastguard Worker if (node1 == node2) {
394*6777b538SAndroid Build Coastguard Worker if (precedence1 == precedence2) {
395*6777b538SAndroid Build Coastguard Worker /*
396*6777b538SAndroid Build Coastguard Worker * The ugly case; but normally there aren't many
397*6777b538SAndroid Build Coastguard Worker * adjacent non-element nodes around.
398*6777b538SAndroid Build Coastguard Worker */
399*6777b538SAndroid Build Coastguard Worker cur = miscNode2->prev;
400*6777b538SAndroid Build Coastguard Worker while (cur != NULL) {
401*6777b538SAndroid Build Coastguard Worker if (cur == miscNode1)
402*6777b538SAndroid Build Coastguard Worker return(1);
403*6777b538SAndroid Build Coastguard Worker if (cur->type == XML_ELEMENT_NODE)
404*6777b538SAndroid Build Coastguard Worker return(-1);
405*6777b538SAndroid Build Coastguard Worker cur = cur->prev;
406*6777b538SAndroid Build Coastguard Worker }
407*6777b538SAndroid Build Coastguard Worker return (-1);
408*6777b538SAndroid Build Coastguard Worker } else {
409*6777b538SAndroid Build Coastguard Worker /*
410*6777b538SAndroid Build Coastguard Worker * Evaluate based on higher precedence wrt to the element.
411*6777b538SAndroid Build Coastguard Worker * TODO: This assumes attributes are sorted before content.
412*6777b538SAndroid Build Coastguard Worker * Is this 100% correct?
413*6777b538SAndroid Build Coastguard Worker */
414*6777b538SAndroid Build Coastguard Worker if (precedence1 < precedence2)
415*6777b538SAndroid Build Coastguard Worker return(1);
416*6777b538SAndroid Build Coastguard Worker else
417*6777b538SAndroid Build Coastguard Worker return(-1);
418*6777b538SAndroid Build Coastguard Worker }
419*6777b538SAndroid Build Coastguard Worker }
420*6777b538SAndroid Build Coastguard Worker /*
421*6777b538SAndroid Build Coastguard Worker * Special case: One of the helper-elements is contained by the other.
422*6777b538SAndroid Build Coastguard Worker * <foo>
423*6777b538SAndroid Build Coastguard Worker * <node2>
424*6777b538SAndroid Build Coastguard Worker * <node1>Text-1(precedence1 == 2)</node1>
425*6777b538SAndroid Build Coastguard Worker * </node2>
426*6777b538SAndroid Build Coastguard Worker * Text-6(precedence2 == 3)
427*6777b538SAndroid Build Coastguard Worker * </foo>
428*6777b538SAndroid Build Coastguard Worker */
429*6777b538SAndroid Build Coastguard Worker if ((precedence2 == 3) && (precedence1 > 1)) {
430*6777b538SAndroid Build Coastguard Worker cur = node1->parent;
431*6777b538SAndroid Build Coastguard Worker while (cur) {
432*6777b538SAndroid Build Coastguard Worker if (cur == node2)
433*6777b538SAndroid Build Coastguard Worker return(1);
434*6777b538SAndroid Build Coastguard Worker cur = cur->parent;
435*6777b538SAndroid Build Coastguard Worker }
436*6777b538SAndroid Build Coastguard Worker }
437*6777b538SAndroid Build Coastguard Worker if ((precedence1 == 3) && (precedence2 > 1)) {
438*6777b538SAndroid Build Coastguard Worker cur = node2->parent;
439*6777b538SAndroid Build Coastguard Worker while (cur) {
440*6777b538SAndroid Build Coastguard Worker if (cur == node1)
441*6777b538SAndroid Build Coastguard Worker return(-1);
442*6777b538SAndroid Build Coastguard Worker cur = cur->parent;
443*6777b538SAndroid Build Coastguard Worker }
444*6777b538SAndroid Build Coastguard Worker }
445*6777b538SAndroid Build Coastguard Worker }
446*6777b538SAndroid Build Coastguard Worker
447*6777b538SAndroid Build Coastguard Worker /*
448*6777b538SAndroid Build Coastguard Worker * Speedup using document order if available.
449*6777b538SAndroid Build Coastguard Worker */
450*6777b538SAndroid Build Coastguard Worker if ((node1->type == XML_ELEMENT_NODE) &&
451*6777b538SAndroid Build Coastguard Worker (node2->type == XML_ELEMENT_NODE) &&
452*6777b538SAndroid Build Coastguard Worker (0 > (ptrdiff_t) node1->content) &&
453*6777b538SAndroid Build Coastguard Worker (0 > (ptrdiff_t) node2->content) &&
454*6777b538SAndroid Build Coastguard Worker (node1->doc == node2->doc)) {
455*6777b538SAndroid Build Coastguard Worker
456*6777b538SAndroid Build Coastguard Worker l1 = -((ptrdiff_t) node1->content);
457*6777b538SAndroid Build Coastguard Worker l2 = -((ptrdiff_t) node2->content);
458*6777b538SAndroid Build Coastguard Worker if (l1 < l2)
459*6777b538SAndroid Build Coastguard Worker return(1);
460*6777b538SAndroid Build Coastguard Worker if (l1 > l2)
461*6777b538SAndroid Build Coastguard Worker return(-1);
462*6777b538SAndroid Build Coastguard Worker }
463*6777b538SAndroid Build Coastguard Worker
464*6777b538SAndroid Build Coastguard Worker turtle_comparison:
465*6777b538SAndroid Build Coastguard Worker
466*6777b538SAndroid Build Coastguard Worker if (node1 == node2->prev)
467*6777b538SAndroid Build Coastguard Worker return(1);
468*6777b538SAndroid Build Coastguard Worker if (node1 == node2->next)
469*6777b538SAndroid Build Coastguard Worker return(-1);
470*6777b538SAndroid Build Coastguard Worker /*
471*6777b538SAndroid Build Coastguard Worker * compute depth to root
472*6777b538SAndroid Build Coastguard Worker */
473*6777b538SAndroid Build Coastguard Worker for (depth2 = 0, cur = node2; cur->parent != NULL; cur = cur->parent) {
474*6777b538SAndroid Build Coastguard Worker if (cur->parent == node1)
475*6777b538SAndroid Build Coastguard Worker return(1);
476*6777b538SAndroid Build Coastguard Worker depth2++;
477*6777b538SAndroid Build Coastguard Worker }
478*6777b538SAndroid Build Coastguard Worker root = cur;
479*6777b538SAndroid Build Coastguard Worker for (depth1 = 0, cur = node1; cur->parent != NULL; cur = cur->parent) {
480*6777b538SAndroid Build Coastguard Worker if (cur->parent == node2)
481*6777b538SAndroid Build Coastguard Worker return(-1);
482*6777b538SAndroid Build Coastguard Worker depth1++;
483*6777b538SAndroid Build Coastguard Worker }
484*6777b538SAndroid Build Coastguard Worker /*
485*6777b538SAndroid Build Coastguard Worker * Distinct document (or distinct entities :-( ) case.
486*6777b538SAndroid Build Coastguard Worker */
487*6777b538SAndroid Build Coastguard Worker if (root != cur) {
488*6777b538SAndroid Build Coastguard Worker return(-2);
489*6777b538SAndroid Build Coastguard Worker }
490*6777b538SAndroid Build Coastguard Worker /*
491*6777b538SAndroid Build Coastguard Worker * get the nearest common ancestor.
492*6777b538SAndroid Build Coastguard Worker */
493*6777b538SAndroid Build Coastguard Worker while (depth1 > depth2) {
494*6777b538SAndroid Build Coastguard Worker depth1--;
495*6777b538SAndroid Build Coastguard Worker node1 = node1->parent;
496*6777b538SAndroid Build Coastguard Worker }
497*6777b538SAndroid Build Coastguard Worker while (depth2 > depth1) {
498*6777b538SAndroid Build Coastguard Worker depth2--;
499*6777b538SAndroid Build Coastguard Worker node2 = node2->parent;
500*6777b538SAndroid Build Coastguard Worker }
501*6777b538SAndroid Build Coastguard Worker while (node1->parent != node2->parent) {
502*6777b538SAndroid Build Coastguard Worker node1 = node1->parent;
503*6777b538SAndroid Build Coastguard Worker node2 = node2->parent;
504*6777b538SAndroid Build Coastguard Worker /* should not happen but just in case ... */
505*6777b538SAndroid Build Coastguard Worker if ((node1 == NULL) || (node2 == NULL))
506*6777b538SAndroid Build Coastguard Worker return(-2);
507*6777b538SAndroid Build Coastguard Worker }
508*6777b538SAndroid Build Coastguard Worker /*
509*6777b538SAndroid Build Coastguard Worker * Find who's first.
510*6777b538SAndroid Build Coastguard Worker */
511*6777b538SAndroid Build Coastguard Worker if (node1 == node2->prev)
512*6777b538SAndroid Build Coastguard Worker return(1);
513*6777b538SAndroid Build Coastguard Worker if (node1 == node2->next)
514*6777b538SAndroid Build Coastguard Worker return(-1);
515*6777b538SAndroid Build Coastguard Worker /*
516*6777b538SAndroid Build Coastguard Worker * Speedup using document order if available.
517*6777b538SAndroid Build Coastguard Worker */
518*6777b538SAndroid Build Coastguard Worker if ((node1->type == XML_ELEMENT_NODE) &&
519*6777b538SAndroid Build Coastguard Worker (node2->type == XML_ELEMENT_NODE) &&
520*6777b538SAndroid Build Coastguard Worker (0 > (ptrdiff_t) node1->content) &&
521*6777b538SAndroid Build Coastguard Worker (0 > (ptrdiff_t) node2->content) &&
522*6777b538SAndroid Build Coastguard Worker (node1->doc == node2->doc)) {
523*6777b538SAndroid Build Coastguard Worker
524*6777b538SAndroid Build Coastguard Worker l1 = -((ptrdiff_t) node1->content);
525*6777b538SAndroid Build Coastguard Worker l2 = -((ptrdiff_t) node2->content);
526*6777b538SAndroid Build Coastguard Worker if (l1 < l2)
527*6777b538SAndroid Build Coastguard Worker return(1);
528*6777b538SAndroid Build Coastguard Worker if (l1 > l2)
529*6777b538SAndroid Build Coastguard Worker return(-1);
530*6777b538SAndroid Build Coastguard Worker }
531*6777b538SAndroid Build Coastguard Worker
532*6777b538SAndroid Build Coastguard Worker for (cur = node1->next;cur != NULL;cur = cur->next)
533*6777b538SAndroid Build Coastguard Worker if (cur == node2)
534*6777b538SAndroid Build Coastguard Worker return(1);
535*6777b538SAndroid Build Coastguard Worker return(-1); /* assume there is no sibling list corruption */
536*6777b538SAndroid Build Coastguard Worker }
537*6777b538SAndroid Build Coastguard Worker #endif /* XP_OPTIMIZED_NON_ELEM_COMPARISON */
538*6777b538SAndroid Build Coastguard Worker
539*6777b538SAndroid Build Coastguard Worker /*
540*6777b538SAndroid Build Coastguard Worker * Wrapper for the Timsort algorithm from timsort.h
541*6777b538SAndroid Build Coastguard Worker */
542*6777b538SAndroid Build Coastguard Worker #ifdef WITH_TIM_SORT
543*6777b538SAndroid Build Coastguard Worker #define SORT_NAME libxml_domnode
544*6777b538SAndroid Build Coastguard Worker #define SORT_TYPE xmlNodePtr
545*6777b538SAndroid Build Coastguard Worker /**
546*6777b538SAndroid Build Coastguard Worker * wrap_cmp:
547*6777b538SAndroid Build Coastguard Worker * @x: a node
548*6777b538SAndroid Build Coastguard Worker * @y: another node
549*6777b538SAndroid Build Coastguard Worker *
550*6777b538SAndroid Build Coastguard Worker * Comparison function for the Timsort implementation
551*6777b538SAndroid Build Coastguard Worker *
552*6777b538SAndroid Build Coastguard Worker * Returns -2 in case of error -1 if first point < second point, 0 if
553*6777b538SAndroid Build Coastguard Worker * it's the same node, +1 otherwise
554*6777b538SAndroid Build Coastguard Worker */
555*6777b538SAndroid Build Coastguard Worker static
556*6777b538SAndroid Build Coastguard Worker int wrap_cmp( xmlNodePtr x, xmlNodePtr y );
557*6777b538SAndroid Build Coastguard Worker #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
wrap_cmp(xmlNodePtr x,xmlNodePtr y)558*6777b538SAndroid Build Coastguard Worker static int wrap_cmp( xmlNodePtr x, xmlNodePtr y )
559*6777b538SAndroid Build Coastguard Worker {
560*6777b538SAndroid Build Coastguard Worker int res = xmlXPathCmpNodesExt(x, y);
561*6777b538SAndroid Build Coastguard Worker return res == -2 ? res : -res;
562*6777b538SAndroid Build Coastguard Worker }
563*6777b538SAndroid Build Coastguard Worker #else
wrap_cmp(xmlNodePtr x,xmlNodePtr y)564*6777b538SAndroid Build Coastguard Worker static int wrap_cmp( xmlNodePtr x, xmlNodePtr y )
565*6777b538SAndroid Build Coastguard Worker {
566*6777b538SAndroid Build Coastguard Worker int res = xmlXPathCmpNodes(x, y);
567*6777b538SAndroid Build Coastguard Worker return res == -2 ? res : -res;
568*6777b538SAndroid Build Coastguard Worker }
569*6777b538SAndroid Build Coastguard Worker #endif
570*6777b538SAndroid Build Coastguard Worker #define SORT_CMP(x, y) (wrap_cmp(x, y))
571*6777b538SAndroid Build Coastguard Worker #include "timsort.h"
572*6777b538SAndroid Build Coastguard Worker #endif /* WITH_TIM_SORT */
573*6777b538SAndroid Build Coastguard Worker
574*6777b538SAndroid Build Coastguard Worker /************************************************************************
575*6777b538SAndroid Build Coastguard Worker * *
576*6777b538SAndroid Build Coastguard Worker * Error handling routines *
577*6777b538SAndroid Build Coastguard Worker * *
578*6777b538SAndroid Build Coastguard Worker ************************************************************************/
579*6777b538SAndroid Build Coastguard Worker
580*6777b538SAndroid Build Coastguard Worker /**
581*6777b538SAndroid Build Coastguard Worker * XP_ERRORNULL:
582*6777b538SAndroid Build Coastguard Worker * @X: the error code
583*6777b538SAndroid Build Coastguard Worker *
584*6777b538SAndroid Build Coastguard Worker * Macro to raise an XPath error and return NULL.
585*6777b538SAndroid Build Coastguard Worker */
586*6777b538SAndroid Build Coastguard Worker #define XP_ERRORNULL(X) \
587*6777b538SAndroid Build Coastguard Worker { xmlXPathErr(ctxt, X); return(NULL); }
588*6777b538SAndroid Build Coastguard Worker
589*6777b538SAndroid Build Coastguard Worker /*
590*6777b538SAndroid Build Coastguard Worker * The array xmlXPathErrorMessages corresponds to the enum xmlXPathError
591*6777b538SAndroid Build Coastguard Worker */
592*6777b538SAndroid Build Coastguard Worker static const char* const xmlXPathErrorMessages[] = {
593*6777b538SAndroid Build Coastguard Worker "Ok\n",
594*6777b538SAndroid Build Coastguard Worker "Number encoding\n",
595*6777b538SAndroid Build Coastguard Worker "Unfinished literal\n",
596*6777b538SAndroid Build Coastguard Worker "Start of literal\n",
597*6777b538SAndroid Build Coastguard Worker "Expected $ for variable reference\n",
598*6777b538SAndroid Build Coastguard Worker "Undefined variable\n",
599*6777b538SAndroid Build Coastguard Worker "Invalid predicate\n",
600*6777b538SAndroid Build Coastguard Worker "Invalid expression\n",
601*6777b538SAndroid Build Coastguard Worker "Missing closing curly brace\n",
602*6777b538SAndroid Build Coastguard Worker "Unregistered function\n",
603*6777b538SAndroid Build Coastguard Worker "Invalid operand\n",
604*6777b538SAndroid Build Coastguard Worker "Invalid type\n",
605*6777b538SAndroid Build Coastguard Worker "Invalid number of arguments\n",
606*6777b538SAndroid Build Coastguard Worker "Invalid context size\n",
607*6777b538SAndroid Build Coastguard Worker "Invalid context position\n",
608*6777b538SAndroid Build Coastguard Worker "Memory allocation error\n",
609*6777b538SAndroid Build Coastguard Worker "Syntax error\n",
610*6777b538SAndroid Build Coastguard Worker "Resource error\n",
611*6777b538SAndroid Build Coastguard Worker "Sub resource error\n",
612*6777b538SAndroid Build Coastguard Worker "Undefined namespace prefix\n",
613*6777b538SAndroid Build Coastguard Worker "Encoding error\n",
614*6777b538SAndroid Build Coastguard Worker "Char out of XML range\n",
615*6777b538SAndroid Build Coastguard Worker "Invalid or incomplete context\n",
616*6777b538SAndroid Build Coastguard Worker "Stack usage error\n",
617*6777b538SAndroid Build Coastguard Worker "Forbidden variable\n",
618*6777b538SAndroid Build Coastguard Worker "Operation limit exceeded\n",
619*6777b538SAndroid Build Coastguard Worker "Recursion limit exceeded\n",
620*6777b538SAndroid Build Coastguard Worker "?? Unknown error ??\n" /* Must be last in the list! */
621*6777b538SAndroid Build Coastguard Worker };
622*6777b538SAndroid Build Coastguard Worker #define MAXERRNO ((int)(sizeof(xmlXPathErrorMessages) / \
623*6777b538SAndroid Build Coastguard Worker sizeof(xmlXPathErrorMessages[0])) - 1)
624*6777b538SAndroid Build Coastguard Worker /**
625*6777b538SAndroid Build Coastguard Worker * xmlXPathErrMemory:
626*6777b538SAndroid Build Coastguard Worker * @ctxt: an XPath context
627*6777b538SAndroid Build Coastguard Worker * @extra: extra information
628*6777b538SAndroid Build Coastguard Worker *
629*6777b538SAndroid Build Coastguard Worker * Handle a memory allocation failure.
630*6777b538SAndroid Build Coastguard Worker */
631*6777b538SAndroid Build Coastguard Worker void
xmlXPathErrMemory(xmlXPathContextPtr ctxt)632*6777b538SAndroid Build Coastguard Worker xmlXPathErrMemory(xmlXPathContextPtr ctxt)
633*6777b538SAndroid Build Coastguard Worker {
634*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
635*6777b538SAndroid Build Coastguard Worker return;
636*6777b538SAndroid Build Coastguard Worker xmlRaiseMemoryError(ctxt->error, NULL, ctxt->userData, XML_FROM_XPATH,
637*6777b538SAndroid Build Coastguard Worker &ctxt->lastError);
638*6777b538SAndroid Build Coastguard Worker }
639*6777b538SAndroid Build Coastguard Worker
640*6777b538SAndroid Build Coastguard Worker /**
641*6777b538SAndroid Build Coastguard Worker * xmlXPathPErrMemory:
642*6777b538SAndroid Build Coastguard Worker * @ctxt: an XPath parser context
643*6777b538SAndroid Build Coastguard Worker * @extra: extra information
644*6777b538SAndroid Build Coastguard Worker *
645*6777b538SAndroid Build Coastguard Worker * Handle a memory allocation failure.
646*6777b538SAndroid Build Coastguard Worker */
647*6777b538SAndroid Build Coastguard Worker void
xmlXPathPErrMemory(xmlXPathParserContextPtr ctxt)648*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(xmlXPathParserContextPtr ctxt)
649*6777b538SAndroid Build Coastguard Worker {
650*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
651*6777b538SAndroid Build Coastguard Worker return;
652*6777b538SAndroid Build Coastguard Worker ctxt->error = XPATH_MEMORY_ERROR;
653*6777b538SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt->context);
654*6777b538SAndroid Build Coastguard Worker }
655*6777b538SAndroid Build Coastguard Worker
656*6777b538SAndroid Build Coastguard Worker /**
657*6777b538SAndroid Build Coastguard Worker * xmlXPathErr:
658*6777b538SAndroid Build Coastguard Worker * @ctxt: a XPath parser context
659*6777b538SAndroid Build Coastguard Worker * @error: the error code
660*6777b538SAndroid Build Coastguard Worker *
661*6777b538SAndroid Build Coastguard Worker * Handle an XPath error
662*6777b538SAndroid Build Coastguard Worker */
663*6777b538SAndroid Build Coastguard Worker void
xmlXPathErr(xmlXPathParserContextPtr ctxt,int code)664*6777b538SAndroid Build Coastguard Worker xmlXPathErr(xmlXPathParserContextPtr ctxt, int code)
665*6777b538SAndroid Build Coastguard Worker {
666*6777b538SAndroid Build Coastguard Worker xmlStructuredErrorFunc schannel = NULL;
667*6777b538SAndroid Build Coastguard Worker xmlGenericErrorFunc channel = NULL;
668*6777b538SAndroid Build Coastguard Worker void *data = NULL;
669*6777b538SAndroid Build Coastguard Worker xmlNodePtr node = NULL;
670*6777b538SAndroid Build Coastguard Worker int res;
671*6777b538SAndroid Build Coastguard Worker
672*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
673*6777b538SAndroid Build Coastguard Worker return;
674*6777b538SAndroid Build Coastguard Worker if ((code < 0) || (code > MAXERRNO))
675*6777b538SAndroid Build Coastguard Worker code = MAXERRNO;
676*6777b538SAndroid Build Coastguard Worker /* Only report the first error */
677*6777b538SAndroid Build Coastguard Worker if (ctxt->error != 0)
678*6777b538SAndroid Build Coastguard Worker return;
679*6777b538SAndroid Build Coastguard Worker
680*6777b538SAndroid Build Coastguard Worker ctxt->error = code;
681*6777b538SAndroid Build Coastguard Worker
682*6777b538SAndroid Build Coastguard Worker if (ctxt->context != NULL) {
683*6777b538SAndroid Build Coastguard Worker xmlErrorPtr err = &ctxt->context->lastError;
684*6777b538SAndroid Build Coastguard Worker
685*6777b538SAndroid Build Coastguard Worker /* Don't overwrite memory error. */
686*6777b538SAndroid Build Coastguard Worker if (err->code == XML_ERR_NO_MEMORY)
687*6777b538SAndroid Build Coastguard Worker return;
688*6777b538SAndroid Build Coastguard Worker
689*6777b538SAndroid Build Coastguard Worker /* cleanup current last error */
690*6777b538SAndroid Build Coastguard Worker xmlResetError(err);
691*6777b538SAndroid Build Coastguard Worker
692*6777b538SAndroid Build Coastguard Worker err->domain = XML_FROM_XPATH;
693*6777b538SAndroid Build Coastguard Worker err->code = code + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK;
694*6777b538SAndroid Build Coastguard Worker err->level = XML_ERR_ERROR;
695*6777b538SAndroid Build Coastguard Worker if (ctxt->base != NULL) {
696*6777b538SAndroid Build Coastguard Worker err->str1 = (char *) xmlStrdup(ctxt->base);
697*6777b538SAndroid Build Coastguard Worker if (err->str1 == NULL) {
698*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
699*6777b538SAndroid Build Coastguard Worker return;
700*6777b538SAndroid Build Coastguard Worker }
701*6777b538SAndroid Build Coastguard Worker }
702*6777b538SAndroid Build Coastguard Worker err->int1 = ctxt->cur - ctxt->base;
703*6777b538SAndroid Build Coastguard Worker err->node = ctxt->context->debugNode;
704*6777b538SAndroid Build Coastguard Worker
705*6777b538SAndroid Build Coastguard Worker schannel = ctxt->context->error;
706*6777b538SAndroid Build Coastguard Worker data = ctxt->context->userData;
707*6777b538SAndroid Build Coastguard Worker node = ctxt->context->debugNode;
708*6777b538SAndroid Build Coastguard Worker }
709*6777b538SAndroid Build Coastguard Worker
710*6777b538SAndroid Build Coastguard Worker if (schannel == NULL) {
711*6777b538SAndroid Build Coastguard Worker channel = xmlGenericError;
712*6777b538SAndroid Build Coastguard Worker data = xmlGenericErrorContext;
713*6777b538SAndroid Build Coastguard Worker }
714*6777b538SAndroid Build Coastguard Worker
715*6777b538SAndroid Build Coastguard Worker res = __xmlRaiseError(schannel, channel, data, NULL, node, XML_FROM_XPATH,
716*6777b538SAndroid Build Coastguard Worker code + XML_XPATH_EXPRESSION_OK - XPATH_EXPRESSION_OK,
717*6777b538SAndroid Build Coastguard Worker XML_ERR_ERROR, NULL, 0,
718*6777b538SAndroid Build Coastguard Worker (const char *) ctxt->base, NULL, NULL,
719*6777b538SAndroid Build Coastguard Worker ctxt->cur - ctxt->base, 0,
720*6777b538SAndroid Build Coastguard Worker "%s", xmlXPathErrorMessages[code]);
721*6777b538SAndroid Build Coastguard Worker if (res < 0)
722*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
723*6777b538SAndroid Build Coastguard Worker }
724*6777b538SAndroid Build Coastguard Worker
725*6777b538SAndroid Build Coastguard Worker /**
726*6777b538SAndroid Build Coastguard Worker * xmlXPatherror:
727*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
728*6777b538SAndroid Build Coastguard Worker * @file: the file name
729*6777b538SAndroid Build Coastguard Worker * @line: the line number
730*6777b538SAndroid Build Coastguard Worker * @no: the error number
731*6777b538SAndroid Build Coastguard Worker *
732*6777b538SAndroid Build Coastguard Worker * Formats an error message.
733*6777b538SAndroid Build Coastguard Worker */
734*6777b538SAndroid Build Coastguard Worker void
xmlXPatherror(xmlXPathParserContextPtr ctxt,const char * file ATTRIBUTE_UNUSED,int line ATTRIBUTE_UNUSED,int no)735*6777b538SAndroid Build Coastguard Worker xmlXPatherror(xmlXPathParserContextPtr ctxt, const char *file ATTRIBUTE_UNUSED,
736*6777b538SAndroid Build Coastguard Worker int line ATTRIBUTE_UNUSED, int no) {
737*6777b538SAndroid Build Coastguard Worker xmlXPathErr(ctxt, no);
738*6777b538SAndroid Build Coastguard Worker }
739*6777b538SAndroid Build Coastguard Worker
740*6777b538SAndroid Build Coastguard Worker /**
741*6777b538SAndroid Build Coastguard Worker * xmlXPathCheckOpLimit:
742*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
743*6777b538SAndroid Build Coastguard Worker * @opCount: the number of operations to be added
744*6777b538SAndroid Build Coastguard Worker *
745*6777b538SAndroid Build Coastguard Worker * Adds opCount to the running total of operations and returns -1 if the
746*6777b538SAndroid Build Coastguard Worker * operation limit is exceeded. Returns 0 otherwise.
747*6777b538SAndroid Build Coastguard Worker */
748*6777b538SAndroid Build Coastguard Worker static int
xmlXPathCheckOpLimit(xmlXPathParserContextPtr ctxt,unsigned long opCount)749*6777b538SAndroid Build Coastguard Worker xmlXPathCheckOpLimit(xmlXPathParserContextPtr ctxt, unsigned long opCount) {
750*6777b538SAndroid Build Coastguard Worker xmlXPathContextPtr xpctxt = ctxt->context;
751*6777b538SAndroid Build Coastguard Worker
752*6777b538SAndroid Build Coastguard Worker if ((opCount > xpctxt->opLimit) ||
753*6777b538SAndroid Build Coastguard Worker (xpctxt->opCount > xpctxt->opLimit - opCount)) {
754*6777b538SAndroid Build Coastguard Worker xpctxt->opCount = xpctxt->opLimit;
755*6777b538SAndroid Build Coastguard Worker xmlXPathErr(ctxt, XPATH_OP_LIMIT_EXCEEDED);
756*6777b538SAndroid Build Coastguard Worker return(-1);
757*6777b538SAndroid Build Coastguard Worker }
758*6777b538SAndroid Build Coastguard Worker
759*6777b538SAndroid Build Coastguard Worker xpctxt->opCount += opCount;
760*6777b538SAndroid Build Coastguard Worker return(0);
761*6777b538SAndroid Build Coastguard Worker }
762*6777b538SAndroid Build Coastguard Worker
763*6777b538SAndroid Build Coastguard Worker #define OP_LIMIT_EXCEEDED(ctxt, n) \
764*6777b538SAndroid Build Coastguard Worker ((ctxt->context->opLimit != 0) && (xmlXPathCheckOpLimit(ctxt, n) < 0))
765*6777b538SAndroid Build Coastguard Worker
766*6777b538SAndroid Build Coastguard Worker /************************************************************************
767*6777b538SAndroid Build Coastguard Worker * *
768*6777b538SAndroid Build Coastguard Worker * Parser Types *
769*6777b538SAndroid Build Coastguard Worker * *
770*6777b538SAndroid Build Coastguard Worker ************************************************************************/
771*6777b538SAndroid Build Coastguard Worker
772*6777b538SAndroid Build Coastguard Worker /*
773*6777b538SAndroid Build Coastguard Worker * Types are private:
774*6777b538SAndroid Build Coastguard Worker */
775*6777b538SAndroid Build Coastguard Worker
776*6777b538SAndroid Build Coastguard Worker typedef enum {
777*6777b538SAndroid Build Coastguard Worker XPATH_OP_END=0,
778*6777b538SAndroid Build Coastguard Worker XPATH_OP_AND,
779*6777b538SAndroid Build Coastguard Worker XPATH_OP_OR,
780*6777b538SAndroid Build Coastguard Worker XPATH_OP_EQUAL,
781*6777b538SAndroid Build Coastguard Worker XPATH_OP_CMP,
782*6777b538SAndroid Build Coastguard Worker XPATH_OP_PLUS,
783*6777b538SAndroid Build Coastguard Worker XPATH_OP_MULT,
784*6777b538SAndroid Build Coastguard Worker XPATH_OP_UNION,
785*6777b538SAndroid Build Coastguard Worker XPATH_OP_ROOT,
786*6777b538SAndroid Build Coastguard Worker XPATH_OP_NODE,
787*6777b538SAndroid Build Coastguard Worker XPATH_OP_COLLECT,
788*6777b538SAndroid Build Coastguard Worker XPATH_OP_VALUE, /* 11 */
789*6777b538SAndroid Build Coastguard Worker XPATH_OP_VARIABLE,
790*6777b538SAndroid Build Coastguard Worker XPATH_OP_FUNCTION,
791*6777b538SAndroid Build Coastguard Worker XPATH_OP_ARG,
792*6777b538SAndroid Build Coastguard Worker XPATH_OP_PREDICATE,
793*6777b538SAndroid Build Coastguard Worker XPATH_OP_FILTER, /* 16 */
794*6777b538SAndroid Build Coastguard Worker XPATH_OP_SORT /* 17 */
795*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
796*6777b538SAndroid Build Coastguard Worker ,XPATH_OP_RANGETO
797*6777b538SAndroid Build Coastguard Worker #endif
798*6777b538SAndroid Build Coastguard Worker } xmlXPathOp;
799*6777b538SAndroid Build Coastguard Worker
800*6777b538SAndroid Build Coastguard Worker typedef enum {
801*6777b538SAndroid Build Coastguard Worker AXIS_ANCESTOR = 1,
802*6777b538SAndroid Build Coastguard Worker AXIS_ANCESTOR_OR_SELF,
803*6777b538SAndroid Build Coastguard Worker AXIS_ATTRIBUTE,
804*6777b538SAndroid Build Coastguard Worker AXIS_CHILD,
805*6777b538SAndroid Build Coastguard Worker AXIS_DESCENDANT,
806*6777b538SAndroid Build Coastguard Worker AXIS_DESCENDANT_OR_SELF,
807*6777b538SAndroid Build Coastguard Worker AXIS_FOLLOWING,
808*6777b538SAndroid Build Coastguard Worker AXIS_FOLLOWING_SIBLING,
809*6777b538SAndroid Build Coastguard Worker AXIS_NAMESPACE,
810*6777b538SAndroid Build Coastguard Worker AXIS_PARENT,
811*6777b538SAndroid Build Coastguard Worker AXIS_PRECEDING,
812*6777b538SAndroid Build Coastguard Worker AXIS_PRECEDING_SIBLING,
813*6777b538SAndroid Build Coastguard Worker AXIS_SELF
814*6777b538SAndroid Build Coastguard Worker } xmlXPathAxisVal;
815*6777b538SAndroid Build Coastguard Worker
816*6777b538SAndroid Build Coastguard Worker typedef enum {
817*6777b538SAndroid Build Coastguard Worker NODE_TEST_NONE = 0,
818*6777b538SAndroid Build Coastguard Worker NODE_TEST_TYPE = 1,
819*6777b538SAndroid Build Coastguard Worker NODE_TEST_PI = 2,
820*6777b538SAndroid Build Coastguard Worker NODE_TEST_ALL = 3,
821*6777b538SAndroid Build Coastguard Worker NODE_TEST_NS = 4,
822*6777b538SAndroid Build Coastguard Worker NODE_TEST_NAME = 5
823*6777b538SAndroid Build Coastguard Worker } xmlXPathTestVal;
824*6777b538SAndroid Build Coastguard Worker
825*6777b538SAndroid Build Coastguard Worker typedef enum {
826*6777b538SAndroid Build Coastguard Worker NODE_TYPE_NODE = 0,
827*6777b538SAndroid Build Coastguard Worker NODE_TYPE_COMMENT = XML_COMMENT_NODE,
828*6777b538SAndroid Build Coastguard Worker NODE_TYPE_TEXT = XML_TEXT_NODE,
829*6777b538SAndroid Build Coastguard Worker NODE_TYPE_PI = XML_PI_NODE
830*6777b538SAndroid Build Coastguard Worker } xmlXPathTypeVal;
831*6777b538SAndroid Build Coastguard Worker
832*6777b538SAndroid Build Coastguard Worker typedef struct _xmlXPathStepOp xmlXPathStepOp;
833*6777b538SAndroid Build Coastguard Worker typedef xmlXPathStepOp *xmlXPathStepOpPtr;
834*6777b538SAndroid Build Coastguard Worker struct _xmlXPathStepOp {
835*6777b538SAndroid Build Coastguard Worker xmlXPathOp op; /* The identifier of the operation */
836*6777b538SAndroid Build Coastguard Worker int ch1; /* First child */
837*6777b538SAndroid Build Coastguard Worker int ch2; /* Second child */
838*6777b538SAndroid Build Coastguard Worker int value;
839*6777b538SAndroid Build Coastguard Worker int value2;
840*6777b538SAndroid Build Coastguard Worker int value3;
841*6777b538SAndroid Build Coastguard Worker void *value4;
842*6777b538SAndroid Build Coastguard Worker void *value5;
843*6777b538SAndroid Build Coastguard Worker xmlXPathFunction cache;
844*6777b538SAndroid Build Coastguard Worker void *cacheURI;
845*6777b538SAndroid Build Coastguard Worker };
846*6777b538SAndroid Build Coastguard Worker
847*6777b538SAndroid Build Coastguard Worker struct _xmlXPathCompExpr {
848*6777b538SAndroid Build Coastguard Worker int nbStep; /* Number of steps in this expression */
849*6777b538SAndroid Build Coastguard Worker int maxStep; /* Maximum number of steps allocated */
850*6777b538SAndroid Build Coastguard Worker xmlXPathStepOp *steps; /* ops for computation of this expression */
851*6777b538SAndroid Build Coastguard Worker int last; /* index of last step in expression */
852*6777b538SAndroid Build Coastguard Worker xmlChar *expr; /* the expression being computed */
853*6777b538SAndroid Build Coastguard Worker xmlDictPtr dict; /* the dictionary to use if any */
854*6777b538SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
855*6777b538SAndroid Build Coastguard Worker xmlPatternPtr stream;
856*6777b538SAndroid Build Coastguard Worker #endif
857*6777b538SAndroid Build Coastguard Worker };
858*6777b538SAndroid Build Coastguard Worker
859*6777b538SAndroid Build Coastguard Worker /************************************************************************
860*6777b538SAndroid Build Coastguard Worker * *
861*6777b538SAndroid Build Coastguard Worker * Forward declarations *
862*6777b538SAndroid Build Coastguard Worker * *
863*6777b538SAndroid Build Coastguard Worker ************************************************************************/
864*6777b538SAndroid Build Coastguard Worker
865*6777b538SAndroid Build Coastguard Worker static void
866*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj);
867*6777b538SAndroid Build Coastguard Worker static int
868*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt,
869*6777b538SAndroid Build Coastguard Worker xmlXPathStepOpPtr op, xmlNodePtr *first);
870*6777b538SAndroid Build Coastguard Worker static int
871*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEvalToBoolean(xmlXPathParserContextPtr ctxt,
872*6777b538SAndroid Build Coastguard Worker xmlXPathStepOpPtr op,
873*6777b538SAndroid Build Coastguard Worker int isPredicate);
874*6777b538SAndroid Build Coastguard Worker static void
875*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObjectEntry(void *obj, const xmlChar *name);
876*6777b538SAndroid Build Coastguard Worker
877*6777b538SAndroid Build Coastguard Worker /************************************************************************
878*6777b538SAndroid Build Coastguard Worker * *
879*6777b538SAndroid Build Coastguard Worker * Parser Type functions *
880*6777b538SAndroid Build Coastguard Worker * *
881*6777b538SAndroid Build Coastguard Worker ************************************************************************/
882*6777b538SAndroid Build Coastguard Worker
883*6777b538SAndroid Build Coastguard Worker /**
884*6777b538SAndroid Build Coastguard Worker * xmlXPathNewCompExpr:
885*6777b538SAndroid Build Coastguard Worker *
886*6777b538SAndroid Build Coastguard Worker * Create a new Xpath component
887*6777b538SAndroid Build Coastguard Worker *
888*6777b538SAndroid Build Coastguard Worker * Returns the newly allocated xmlXPathCompExprPtr or NULL in case of error
889*6777b538SAndroid Build Coastguard Worker */
890*6777b538SAndroid Build Coastguard Worker static xmlXPathCompExprPtr
xmlXPathNewCompExpr(void)891*6777b538SAndroid Build Coastguard Worker xmlXPathNewCompExpr(void) {
892*6777b538SAndroid Build Coastguard Worker xmlXPathCompExprPtr cur;
893*6777b538SAndroid Build Coastguard Worker
894*6777b538SAndroid Build Coastguard Worker cur = (xmlXPathCompExprPtr) xmlMalloc(sizeof(xmlXPathCompExpr));
895*6777b538SAndroid Build Coastguard Worker if (cur == NULL)
896*6777b538SAndroid Build Coastguard Worker return(NULL);
897*6777b538SAndroid Build Coastguard Worker memset(cur, 0, sizeof(xmlXPathCompExpr));
898*6777b538SAndroid Build Coastguard Worker cur->maxStep = 10;
899*6777b538SAndroid Build Coastguard Worker cur->nbStep = 0;
900*6777b538SAndroid Build Coastguard Worker cur->steps = (xmlXPathStepOp *) xmlMalloc(cur->maxStep *
901*6777b538SAndroid Build Coastguard Worker sizeof(xmlXPathStepOp));
902*6777b538SAndroid Build Coastguard Worker if (cur->steps == NULL) {
903*6777b538SAndroid Build Coastguard Worker xmlFree(cur);
904*6777b538SAndroid Build Coastguard Worker return(NULL);
905*6777b538SAndroid Build Coastguard Worker }
906*6777b538SAndroid Build Coastguard Worker memset(cur->steps, 0, cur->maxStep * sizeof(xmlXPathStepOp));
907*6777b538SAndroid Build Coastguard Worker cur->last = -1;
908*6777b538SAndroid Build Coastguard Worker return(cur);
909*6777b538SAndroid Build Coastguard Worker }
910*6777b538SAndroid Build Coastguard Worker
911*6777b538SAndroid Build Coastguard Worker /**
912*6777b538SAndroid Build Coastguard Worker * xmlXPathFreeCompExpr:
913*6777b538SAndroid Build Coastguard Worker * @comp: an XPATH comp
914*6777b538SAndroid Build Coastguard Worker *
915*6777b538SAndroid Build Coastguard Worker * Free up the memory allocated by @comp
916*6777b538SAndroid Build Coastguard Worker */
917*6777b538SAndroid Build Coastguard Worker void
xmlXPathFreeCompExpr(xmlXPathCompExprPtr comp)918*6777b538SAndroid Build Coastguard Worker xmlXPathFreeCompExpr(xmlXPathCompExprPtr comp)
919*6777b538SAndroid Build Coastguard Worker {
920*6777b538SAndroid Build Coastguard Worker xmlXPathStepOpPtr op;
921*6777b538SAndroid Build Coastguard Worker int i;
922*6777b538SAndroid Build Coastguard Worker
923*6777b538SAndroid Build Coastguard Worker if (comp == NULL)
924*6777b538SAndroid Build Coastguard Worker return;
925*6777b538SAndroid Build Coastguard Worker if (comp->dict == NULL) {
926*6777b538SAndroid Build Coastguard Worker for (i = 0; i < comp->nbStep; i++) {
927*6777b538SAndroid Build Coastguard Worker op = &comp->steps[i];
928*6777b538SAndroid Build Coastguard Worker if (op->value4 != NULL) {
929*6777b538SAndroid Build Coastguard Worker if (op->op == XPATH_OP_VALUE)
930*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject(op->value4);
931*6777b538SAndroid Build Coastguard Worker else
932*6777b538SAndroid Build Coastguard Worker xmlFree(op->value4);
933*6777b538SAndroid Build Coastguard Worker }
934*6777b538SAndroid Build Coastguard Worker if (op->value5 != NULL)
935*6777b538SAndroid Build Coastguard Worker xmlFree(op->value5);
936*6777b538SAndroid Build Coastguard Worker }
937*6777b538SAndroid Build Coastguard Worker } else {
938*6777b538SAndroid Build Coastguard Worker for (i = 0; i < comp->nbStep; i++) {
939*6777b538SAndroid Build Coastguard Worker op = &comp->steps[i];
940*6777b538SAndroid Build Coastguard Worker if (op->value4 != NULL) {
941*6777b538SAndroid Build Coastguard Worker if (op->op == XPATH_OP_VALUE)
942*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject(op->value4);
943*6777b538SAndroid Build Coastguard Worker }
944*6777b538SAndroid Build Coastguard Worker }
945*6777b538SAndroid Build Coastguard Worker xmlDictFree(comp->dict);
946*6777b538SAndroid Build Coastguard Worker }
947*6777b538SAndroid Build Coastguard Worker if (comp->steps != NULL) {
948*6777b538SAndroid Build Coastguard Worker xmlFree(comp->steps);
949*6777b538SAndroid Build Coastguard Worker }
950*6777b538SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
951*6777b538SAndroid Build Coastguard Worker if (comp->stream != NULL) {
952*6777b538SAndroid Build Coastguard Worker xmlFreePatternList(comp->stream);
953*6777b538SAndroid Build Coastguard Worker }
954*6777b538SAndroid Build Coastguard Worker #endif
955*6777b538SAndroid Build Coastguard Worker if (comp->expr != NULL) {
956*6777b538SAndroid Build Coastguard Worker xmlFree(comp->expr);
957*6777b538SAndroid Build Coastguard Worker }
958*6777b538SAndroid Build Coastguard Worker
959*6777b538SAndroid Build Coastguard Worker xmlFree(comp);
960*6777b538SAndroid Build Coastguard Worker }
961*6777b538SAndroid Build Coastguard Worker
962*6777b538SAndroid Build Coastguard Worker /**
963*6777b538SAndroid Build Coastguard Worker * xmlXPathCompExprAdd:
964*6777b538SAndroid Build Coastguard Worker * @comp: the compiled expression
965*6777b538SAndroid Build Coastguard Worker * @ch1: first child index
966*6777b538SAndroid Build Coastguard Worker * @ch2: second child index
967*6777b538SAndroid Build Coastguard Worker * @op: an op
968*6777b538SAndroid Build Coastguard Worker * @value: the first int value
969*6777b538SAndroid Build Coastguard Worker * @value2: the second int value
970*6777b538SAndroid Build Coastguard Worker * @value3: the third int value
971*6777b538SAndroid Build Coastguard Worker * @value4: the first string value
972*6777b538SAndroid Build Coastguard Worker * @value5: the second string value
973*6777b538SAndroid Build Coastguard Worker *
974*6777b538SAndroid Build Coastguard Worker * Add a step to an XPath Compiled Expression
975*6777b538SAndroid Build Coastguard Worker *
976*6777b538SAndroid Build Coastguard Worker * Returns -1 in case of failure, the index otherwise
977*6777b538SAndroid Build Coastguard Worker */
978*6777b538SAndroid Build Coastguard Worker static int
xmlXPathCompExprAdd(xmlXPathParserContextPtr ctxt,int ch1,int ch2,xmlXPathOp op,int value,int value2,int value3,void * value4,void * value5)979*6777b538SAndroid Build Coastguard Worker xmlXPathCompExprAdd(xmlXPathParserContextPtr ctxt, int ch1, int ch2,
980*6777b538SAndroid Build Coastguard Worker xmlXPathOp op, int value,
981*6777b538SAndroid Build Coastguard Worker int value2, int value3, void *value4, void *value5) {
982*6777b538SAndroid Build Coastguard Worker xmlXPathCompExprPtr comp = ctxt->comp;
983*6777b538SAndroid Build Coastguard Worker if (comp->nbStep >= comp->maxStep) {
984*6777b538SAndroid Build Coastguard Worker xmlXPathStepOp *real;
985*6777b538SAndroid Build Coastguard Worker
986*6777b538SAndroid Build Coastguard Worker if (comp->maxStep >= XPATH_MAX_STEPS) {
987*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
988*6777b538SAndroid Build Coastguard Worker return(-1);
989*6777b538SAndroid Build Coastguard Worker }
990*6777b538SAndroid Build Coastguard Worker comp->maxStep *= 2;
991*6777b538SAndroid Build Coastguard Worker real = (xmlXPathStepOp *) xmlRealloc(comp->steps,
992*6777b538SAndroid Build Coastguard Worker comp->maxStep * sizeof(xmlXPathStepOp));
993*6777b538SAndroid Build Coastguard Worker if (real == NULL) {
994*6777b538SAndroid Build Coastguard Worker comp->maxStep /= 2;
995*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
996*6777b538SAndroid Build Coastguard Worker return(-1);
997*6777b538SAndroid Build Coastguard Worker }
998*6777b538SAndroid Build Coastguard Worker comp->steps = real;
999*6777b538SAndroid Build Coastguard Worker }
1000*6777b538SAndroid Build Coastguard Worker comp->last = comp->nbStep;
1001*6777b538SAndroid Build Coastguard Worker comp->steps[comp->nbStep].ch1 = ch1;
1002*6777b538SAndroid Build Coastguard Worker comp->steps[comp->nbStep].ch2 = ch2;
1003*6777b538SAndroid Build Coastguard Worker comp->steps[comp->nbStep].op = op;
1004*6777b538SAndroid Build Coastguard Worker comp->steps[comp->nbStep].value = value;
1005*6777b538SAndroid Build Coastguard Worker comp->steps[comp->nbStep].value2 = value2;
1006*6777b538SAndroid Build Coastguard Worker comp->steps[comp->nbStep].value3 = value3;
1007*6777b538SAndroid Build Coastguard Worker if ((comp->dict != NULL) &&
1008*6777b538SAndroid Build Coastguard Worker ((op == XPATH_OP_FUNCTION) || (op == XPATH_OP_VARIABLE) ||
1009*6777b538SAndroid Build Coastguard Worker (op == XPATH_OP_COLLECT))) {
1010*6777b538SAndroid Build Coastguard Worker if (value4 != NULL) {
1011*6777b538SAndroid Build Coastguard Worker comp->steps[comp->nbStep].value4 = (xmlChar *)
1012*6777b538SAndroid Build Coastguard Worker (void *)xmlDictLookup(comp->dict, value4, -1);
1013*6777b538SAndroid Build Coastguard Worker xmlFree(value4);
1014*6777b538SAndroid Build Coastguard Worker } else
1015*6777b538SAndroid Build Coastguard Worker comp->steps[comp->nbStep].value4 = NULL;
1016*6777b538SAndroid Build Coastguard Worker if (value5 != NULL) {
1017*6777b538SAndroid Build Coastguard Worker comp->steps[comp->nbStep].value5 = (xmlChar *)
1018*6777b538SAndroid Build Coastguard Worker (void *)xmlDictLookup(comp->dict, value5, -1);
1019*6777b538SAndroid Build Coastguard Worker xmlFree(value5);
1020*6777b538SAndroid Build Coastguard Worker } else
1021*6777b538SAndroid Build Coastguard Worker comp->steps[comp->nbStep].value5 = NULL;
1022*6777b538SAndroid Build Coastguard Worker } else {
1023*6777b538SAndroid Build Coastguard Worker comp->steps[comp->nbStep].value4 = value4;
1024*6777b538SAndroid Build Coastguard Worker comp->steps[comp->nbStep].value5 = value5;
1025*6777b538SAndroid Build Coastguard Worker }
1026*6777b538SAndroid Build Coastguard Worker comp->steps[comp->nbStep].cache = NULL;
1027*6777b538SAndroid Build Coastguard Worker return(comp->nbStep++);
1028*6777b538SAndroid Build Coastguard Worker }
1029*6777b538SAndroid Build Coastguard Worker
1030*6777b538SAndroid Build Coastguard Worker /**
1031*6777b538SAndroid Build Coastguard Worker * xmlXPathCompSwap:
1032*6777b538SAndroid Build Coastguard Worker * @comp: the compiled expression
1033*6777b538SAndroid Build Coastguard Worker * @op: operation index
1034*6777b538SAndroid Build Coastguard Worker *
1035*6777b538SAndroid Build Coastguard Worker * Swaps 2 operations in the compiled expression
1036*6777b538SAndroid Build Coastguard Worker */
1037*6777b538SAndroid Build Coastguard Worker static void
xmlXPathCompSwap(xmlXPathStepOpPtr op)1038*6777b538SAndroid Build Coastguard Worker xmlXPathCompSwap(xmlXPathStepOpPtr op) {
1039*6777b538SAndroid Build Coastguard Worker int tmp;
1040*6777b538SAndroid Build Coastguard Worker
1041*6777b538SAndroid Build Coastguard Worker #ifndef LIBXML_THREAD_ENABLED
1042*6777b538SAndroid Build Coastguard Worker /*
1043*6777b538SAndroid Build Coastguard Worker * Since this manipulates possibly shared variables, this is
1044*6777b538SAndroid Build Coastguard Worker * disabled if one detects that the library is used in a multithreaded
1045*6777b538SAndroid Build Coastguard Worker * application
1046*6777b538SAndroid Build Coastguard Worker */
1047*6777b538SAndroid Build Coastguard Worker if (xmlXPathDisableOptimizer)
1048*6777b538SAndroid Build Coastguard Worker return;
1049*6777b538SAndroid Build Coastguard Worker #endif
1050*6777b538SAndroid Build Coastguard Worker
1051*6777b538SAndroid Build Coastguard Worker tmp = op->ch1;
1052*6777b538SAndroid Build Coastguard Worker op->ch1 = op->ch2;
1053*6777b538SAndroid Build Coastguard Worker op->ch2 = tmp;
1054*6777b538SAndroid Build Coastguard Worker }
1055*6777b538SAndroid Build Coastguard Worker
1056*6777b538SAndroid Build Coastguard Worker #define PUSH_FULL_EXPR(op, op1, op2, val, val2, val3, val4, val5) \
1057*6777b538SAndroid Build Coastguard Worker xmlXPathCompExprAdd(ctxt, (op1), (op2), \
1058*6777b538SAndroid Build Coastguard Worker (op), (val), (val2), (val3), (val4), (val5))
1059*6777b538SAndroid Build Coastguard Worker #define PUSH_LONG_EXPR(op, val, val2, val3, val4, val5) \
1060*6777b538SAndroid Build Coastguard Worker xmlXPathCompExprAdd(ctxt, ctxt->comp->last, -1, \
1061*6777b538SAndroid Build Coastguard Worker (op), (val), (val2), (val3), (val4), (val5))
1062*6777b538SAndroid Build Coastguard Worker
1063*6777b538SAndroid Build Coastguard Worker #define PUSH_LEAVE_EXPR(op, val, val2) \
1064*6777b538SAndroid Build Coastguard Worker xmlXPathCompExprAdd(ctxt, -1, -1, (op), (val), (val2), 0 ,NULL ,NULL)
1065*6777b538SAndroid Build Coastguard Worker
1066*6777b538SAndroid Build Coastguard Worker #define PUSH_UNARY_EXPR(op, ch, val, val2) \
1067*6777b538SAndroid Build Coastguard Worker xmlXPathCompExprAdd(ctxt, (ch), -1, (op), (val), (val2), 0 ,NULL ,NULL)
1068*6777b538SAndroid Build Coastguard Worker
1069*6777b538SAndroid Build Coastguard Worker #define PUSH_BINARY_EXPR(op, ch1, ch2, val, val2) \
1070*6777b538SAndroid Build Coastguard Worker xmlXPathCompExprAdd(ctxt, (ch1), (ch2), (op), \
1071*6777b538SAndroid Build Coastguard Worker (val), (val2), 0 ,NULL ,NULL)
1072*6777b538SAndroid Build Coastguard Worker
1073*6777b538SAndroid Build Coastguard Worker /************************************************************************
1074*6777b538SAndroid Build Coastguard Worker * *
1075*6777b538SAndroid Build Coastguard Worker * XPath object cache structures *
1076*6777b538SAndroid Build Coastguard Worker * *
1077*6777b538SAndroid Build Coastguard Worker ************************************************************************/
1078*6777b538SAndroid Build Coastguard Worker
1079*6777b538SAndroid Build Coastguard Worker /* #define XP_DEFAULT_CACHE_ON */
1080*6777b538SAndroid Build Coastguard Worker
1081*6777b538SAndroid Build Coastguard Worker typedef struct _xmlXPathContextCache xmlXPathContextCache;
1082*6777b538SAndroid Build Coastguard Worker typedef xmlXPathContextCache *xmlXPathContextCachePtr;
1083*6777b538SAndroid Build Coastguard Worker struct _xmlXPathContextCache {
1084*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr nodesetObjs; /* stringval points to next */
1085*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr miscObjs; /* stringval points to next */
1086*6777b538SAndroid Build Coastguard Worker int numNodeset;
1087*6777b538SAndroid Build Coastguard Worker int maxNodeset;
1088*6777b538SAndroid Build Coastguard Worker int numMisc;
1089*6777b538SAndroid Build Coastguard Worker int maxMisc;
1090*6777b538SAndroid Build Coastguard Worker };
1091*6777b538SAndroid Build Coastguard Worker
1092*6777b538SAndroid Build Coastguard Worker /************************************************************************
1093*6777b538SAndroid Build Coastguard Worker * *
1094*6777b538SAndroid Build Coastguard Worker * Debugging related functions *
1095*6777b538SAndroid Build Coastguard Worker * *
1096*6777b538SAndroid Build Coastguard Worker ************************************************************************/
1097*6777b538SAndroid Build Coastguard Worker
1098*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_DEBUG_ENABLED
1099*6777b538SAndroid Build Coastguard Worker static void
xmlXPathDebugDumpNode(FILE * output,xmlNodePtr cur,int depth)1100*6777b538SAndroid Build Coastguard Worker xmlXPathDebugDumpNode(FILE *output, xmlNodePtr cur, int depth) {
1101*6777b538SAndroid Build Coastguard Worker int i;
1102*6777b538SAndroid Build Coastguard Worker char shift[100];
1103*6777b538SAndroid Build Coastguard Worker
1104*6777b538SAndroid Build Coastguard Worker for (i = 0;((i < depth) && (i < 25));i++)
1105*6777b538SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = ' ';
1106*6777b538SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = 0;
1107*6777b538SAndroid Build Coastguard Worker if (cur == NULL) {
1108*6777b538SAndroid Build Coastguard Worker fprintf(output, "%s", shift);
1109*6777b538SAndroid Build Coastguard Worker fprintf(output, "Node is NULL !\n");
1110*6777b538SAndroid Build Coastguard Worker return;
1111*6777b538SAndroid Build Coastguard Worker
1112*6777b538SAndroid Build Coastguard Worker }
1113*6777b538SAndroid Build Coastguard Worker
1114*6777b538SAndroid Build Coastguard Worker if ((cur->type == XML_DOCUMENT_NODE) ||
1115*6777b538SAndroid Build Coastguard Worker (cur->type == XML_HTML_DOCUMENT_NODE)) {
1116*6777b538SAndroid Build Coastguard Worker fprintf(output, "%s", shift);
1117*6777b538SAndroid Build Coastguard Worker fprintf(output, " /\n");
1118*6777b538SAndroid Build Coastguard Worker } else if (cur->type == XML_ATTRIBUTE_NODE)
1119*6777b538SAndroid Build Coastguard Worker xmlDebugDumpAttr(output, (xmlAttrPtr)cur, depth);
1120*6777b538SAndroid Build Coastguard Worker else
1121*6777b538SAndroid Build Coastguard Worker xmlDebugDumpOneNode(output, cur, depth);
1122*6777b538SAndroid Build Coastguard Worker }
1123*6777b538SAndroid Build Coastguard Worker static void
xmlXPathDebugDumpNodeList(FILE * output,xmlNodePtr cur,int depth)1124*6777b538SAndroid Build Coastguard Worker xmlXPathDebugDumpNodeList(FILE *output, xmlNodePtr cur, int depth) {
1125*6777b538SAndroid Build Coastguard Worker xmlNodePtr tmp;
1126*6777b538SAndroid Build Coastguard Worker int i;
1127*6777b538SAndroid Build Coastguard Worker char shift[100];
1128*6777b538SAndroid Build Coastguard Worker
1129*6777b538SAndroid Build Coastguard Worker for (i = 0;((i < depth) && (i < 25));i++)
1130*6777b538SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = ' ';
1131*6777b538SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = 0;
1132*6777b538SAndroid Build Coastguard Worker if (cur == NULL) {
1133*6777b538SAndroid Build Coastguard Worker fprintf(output, "%s", shift);
1134*6777b538SAndroid Build Coastguard Worker fprintf(output, "Node is NULL !\n");
1135*6777b538SAndroid Build Coastguard Worker return;
1136*6777b538SAndroid Build Coastguard Worker
1137*6777b538SAndroid Build Coastguard Worker }
1138*6777b538SAndroid Build Coastguard Worker
1139*6777b538SAndroid Build Coastguard Worker while (cur != NULL) {
1140*6777b538SAndroid Build Coastguard Worker tmp = cur;
1141*6777b538SAndroid Build Coastguard Worker cur = cur->next;
1142*6777b538SAndroid Build Coastguard Worker xmlDebugDumpOneNode(output, tmp, depth);
1143*6777b538SAndroid Build Coastguard Worker }
1144*6777b538SAndroid Build Coastguard Worker }
1145*6777b538SAndroid Build Coastguard Worker
1146*6777b538SAndroid Build Coastguard Worker static void
xmlXPathDebugDumpNodeSet(FILE * output,xmlNodeSetPtr cur,int depth)1147*6777b538SAndroid Build Coastguard Worker xmlXPathDebugDumpNodeSet(FILE *output, xmlNodeSetPtr cur, int depth) {
1148*6777b538SAndroid Build Coastguard Worker int i;
1149*6777b538SAndroid Build Coastguard Worker char shift[100];
1150*6777b538SAndroid Build Coastguard Worker
1151*6777b538SAndroid Build Coastguard Worker for (i = 0;((i < depth) && (i < 25));i++)
1152*6777b538SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = ' ';
1153*6777b538SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = 0;
1154*6777b538SAndroid Build Coastguard Worker
1155*6777b538SAndroid Build Coastguard Worker if (cur == NULL) {
1156*6777b538SAndroid Build Coastguard Worker fprintf(output, "%s", shift);
1157*6777b538SAndroid Build Coastguard Worker fprintf(output, "NodeSet is NULL !\n");
1158*6777b538SAndroid Build Coastguard Worker return;
1159*6777b538SAndroid Build Coastguard Worker
1160*6777b538SAndroid Build Coastguard Worker }
1161*6777b538SAndroid Build Coastguard Worker
1162*6777b538SAndroid Build Coastguard Worker if (cur != NULL) {
1163*6777b538SAndroid Build Coastguard Worker fprintf(output, "Set contains %d nodes:\n", cur->nodeNr);
1164*6777b538SAndroid Build Coastguard Worker for (i = 0;i < cur->nodeNr;i++) {
1165*6777b538SAndroid Build Coastguard Worker fprintf(output, "%s", shift);
1166*6777b538SAndroid Build Coastguard Worker fprintf(output, "%d", i + 1);
1167*6777b538SAndroid Build Coastguard Worker xmlXPathDebugDumpNode(output, cur->nodeTab[i], depth + 1);
1168*6777b538SAndroid Build Coastguard Worker }
1169*6777b538SAndroid Build Coastguard Worker }
1170*6777b538SAndroid Build Coastguard Worker }
1171*6777b538SAndroid Build Coastguard Worker
1172*6777b538SAndroid Build Coastguard Worker static void
xmlXPathDebugDumpValueTree(FILE * output,xmlNodeSetPtr cur,int depth)1173*6777b538SAndroid Build Coastguard Worker xmlXPathDebugDumpValueTree(FILE *output, xmlNodeSetPtr cur, int depth) {
1174*6777b538SAndroid Build Coastguard Worker int i;
1175*6777b538SAndroid Build Coastguard Worker char shift[100];
1176*6777b538SAndroid Build Coastguard Worker
1177*6777b538SAndroid Build Coastguard Worker for (i = 0;((i < depth) && (i < 25));i++)
1178*6777b538SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = ' ';
1179*6777b538SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = 0;
1180*6777b538SAndroid Build Coastguard Worker
1181*6777b538SAndroid Build Coastguard Worker if ((cur == NULL) || (cur->nodeNr == 0) || (cur->nodeTab[0] == NULL)) {
1182*6777b538SAndroid Build Coastguard Worker fprintf(output, "%s", shift);
1183*6777b538SAndroid Build Coastguard Worker fprintf(output, "Value Tree is NULL !\n");
1184*6777b538SAndroid Build Coastguard Worker return;
1185*6777b538SAndroid Build Coastguard Worker
1186*6777b538SAndroid Build Coastguard Worker }
1187*6777b538SAndroid Build Coastguard Worker
1188*6777b538SAndroid Build Coastguard Worker fprintf(output, "%s", shift);
1189*6777b538SAndroid Build Coastguard Worker fprintf(output, "%d", i + 1);
1190*6777b538SAndroid Build Coastguard Worker xmlXPathDebugDumpNodeList(output, cur->nodeTab[0]->children, depth + 1);
1191*6777b538SAndroid Build Coastguard Worker }
1192*6777b538SAndroid Build Coastguard Worker #if defined(LIBXML_XPTR_LOCS_ENABLED)
1193*6777b538SAndroid Build Coastguard Worker static void
xmlXPathDebugDumpLocationSet(FILE * output,xmlLocationSetPtr cur,int depth)1194*6777b538SAndroid Build Coastguard Worker xmlXPathDebugDumpLocationSet(FILE *output, xmlLocationSetPtr cur, int depth) {
1195*6777b538SAndroid Build Coastguard Worker int i;
1196*6777b538SAndroid Build Coastguard Worker char shift[100];
1197*6777b538SAndroid Build Coastguard Worker
1198*6777b538SAndroid Build Coastguard Worker for (i = 0;((i < depth) && (i < 25));i++)
1199*6777b538SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = ' ';
1200*6777b538SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = 0;
1201*6777b538SAndroid Build Coastguard Worker
1202*6777b538SAndroid Build Coastguard Worker if (cur == NULL) {
1203*6777b538SAndroid Build Coastguard Worker fprintf(output, "%s", shift);
1204*6777b538SAndroid Build Coastguard Worker fprintf(output, "LocationSet is NULL !\n");
1205*6777b538SAndroid Build Coastguard Worker return;
1206*6777b538SAndroid Build Coastguard Worker
1207*6777b538SAndroid Build Coastguard Worker }
1208*6777b538SAndroid Build Coastguard Worker
1209*6777b538SAndroid Build Coastguard Worker for (i = 0;i < cur->locNr;i++) {
1210*6777b538SAndroid Build Coastguard Worker fprintf(output, "%s", shift);
1211*6777b538SAndroid Build Coastguard Worker fprintf(output, "%d : ", i + 1);
1212*6777b538SAndroid Build Coastguard Worker xmlXPathDebugDumpObject(output, cur->locTab[i], depth + 1);
1213*6777b538SAndroid Build Coastguard Worker }
1214*6777b538SAndroid Build Coastguard Worker }
1215*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_XPTR_LOCS_ENABLED */
1216*6777b538SAndroid Build Coastguard Worker
1217*6777b538SAndroid Build Coastguard Worker /**
1218*6777b538SAndroid Build Coastguard Worker * xmlXPathDebugDumpObject:
1219*6777b538SAndroid Build Coastguard Worker * @output: the FILE * to dump the output
1220*6777b538SAndroid Build Coastguard Worker * @cur: the object to inspect
1221*6777b538SAndroid Build Coastguard Worker * @depth: indentation level
1222*6777b538SAndroid Build Coastguard Worker *
1223*6777b538SAndroid Build Coastguard Worker * Dump the content of the object for debugging purposes
1224*6777b538SAndroid Build Coastguard Worker */
1225*6777b538SAndroid Build Coastguard Worker void
xmlXPathDebugDumpObject(FILE * output,xmlXPathObjectPtr cur,int depth)1226*6777b538SAndroid Build Coastguard Worker xmlXPathDebugDumpObject(FILE *output, xmlXPathObjectPtr cur, int depth) {
1227*6777b538SAndroid Build Coastguard Worker int i;
1228*6777b538SAndroid Build Coastguard Worker char shift[100];
1229*6777b538SAndroid Build Coastguard Worker
1230*6777b538SAndroid Build Coastguard Worker if (output == NULL) return;
1231*6777b538SAndroid Build Coastguard Worker
1232*6777b538SAndroid Build Coastguard Worker for (i = 0;((i < depth) && (i < 25));i++)
1233*6777b538SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = ' ';
1234*6777b538SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = 0;
1235*6777b538SAndroid Build Coastguard Worker
1236*6777b538SAndroid Build Coastguard Worker
1237*6777b538SAndroid Build Coastguard Worker fprintf(output, "%s", shift);
1238*6777b538SAndroid Build Coastguard Worker
1239*6777b538SAndroid Build Coastguard Worker if (cur == NULL) {
1240*6777b538SAndroid Build Coastguard Worker fprintf(output, "Object is empty (NULL)\n");
1241*6777b538SAndroid Build Coastguard Worker return;
1242*6777b538SAndroid Build Coastguard Worker }
1243*6777b538SAndroid Build Coastguard Worker switch(cur->type) {
1244*6777b538SAndroid Build Coastguard Worker case XPATH_UNDEFINED:
1245*6777b538SAndroid Build Coastguard Worker fprintf(output, "Object is uninitialized\n");
1246*6777b538SAndroid Build Coastguard Worker break;
1247*6777b538SAndroid Build Coastguard Worker case XPATH_NODESET:
1248*6777b538SAndroid Build Coastguard Worker fprintf(output, "Object is a Node Set :\n");
1249*6777b538SAndroid Build Coastguard Worker xmlXPathDebugDumpNodeSet(output, cur->nodesetval, depth);
1250*6777b538SAndroid Build Coastguard Worker break;
1251*6777b538SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
1252*6777b538SAndroid Build Coastguard Worker fprintf(output, "Object is an XSLT value tree :\n");
1253*6777b538SAndroid Build Coastguard Worker xmlXPathDebugDumpValueTree(output, cur->nodesetval, depth);
1254*6777b538SAndroid Build Coastguard Worker break;
1255*6777b538SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
1256*6777b538SAndroid Build Coastguard Worker fprintf(output, "Object is a Boolean : ");
1257*6777b538SAndroid Build Coastguard Worker if (cur->boolval) fprintf(output, "true\n");
1258*6777b538SAndroid Build Coastguard Worker else fprintf(output, "false\n");
1259*6777b538SAndroid Build Coastguard Worker break;
1260*6777b538SAndroid Build Coastguard Worker case XPATH_NUMBER:
1261*6777b538SAndroid Build Coastguard Worker switch (xmlXPathIsInf(cur->floatval)) {
1262*6777b538SAndroid Build Coastguard Worker case 1:
1263*6777b538SAndroid Build Coastguard Worker fprintf(output, "Object is a number : Infinity\n");
1264*6777b538SAndroid Build Coastguard Worker break;
1265*6777b538SAndroid Build Coastguard Worker case -1:
1266*6777b538SAndroid Build Coastguard Worker fprintf(output, "Object is a number : -Infinity\n");
1267*6777b538SAndroid Build Coastguard Worker break;
1268*6777b538SAndroid Build Coastguard Worker default:
1269*6777b538SAndroid Build Coastguard Worker if (xmlXPathIsNaN(cur->floatval)) {
1270*6777b538SAndroid Build Coastguard Worker fprintf(output, "Object is a number : NaN\n");
1271*6777b538SAndroid Build Coastguard Worker } else if (cur->floatval == 0) {
1272*6777b538SAndroid Build Coastguard Worker /* Omit sign for negative zero. */
1273*6777b538SAndroid Build Coastguard Worker fprintf(output, "Object is a number : 0\n");
1274*6777b538SAndroid Build Coastguard Worker } else {
1275*6777b538SAndroid Build Coastguard Worker fprintf(output, "Object is a number : %0g\n", cur->floatval);
1276*6777b538SAndroid Build Coastguard Worker }
1277*6777b538SAndroid Build Coastguard Worker }
1278*6777b538SAndroid Build Coastguard Worker break;
1279*6777b538SAndroid Build Coastguard Worker case XPATH_STRING:
1280*6777b538SAndroid Build Coastguard Worker fprintf(output, "Object is a string : ");
1281*6777b538SAndroid Build Coastguard Worker xmlDebugDumpString(output, cur->stringval);
1282*6777b538SAndroid Build Coastguard Worker fprintf(output, "\n");
1283*6777b538SAndroid Build Coastguard Worker break;
1284*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
1285*6777b538SAndroid Build Coastguard Worker case XPATH_POINT:
1286*6777b538SAndroid Build Coastguard Worker fprintf(output, "Object is a point : index %d in node", cur->index);
1287*6777b538SAndroid Build Coastguard Worker xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user, depth + 1);
1288*6777b538SAndroid Build Coastguard Worker fprintf(output, "\n");
1289*6777b538SAndroid Build Coastguard Worker break;
1290*6777b538SAndroid Build Coastguard Worker case XPATH_RANGE:
1291*6777b538SAndroid Build Coastguard Worker if ((cur->user2 == NULL) ||
1292*6777b538SAndroid Build Coastguard Worker ((cur->user2 == cur->user) && (cur->index == cur->index2))) {
1293*6777b538SAndroid Build Coastguard Worker fprintf(output, "Object is a collapsed range :\n");
1294*6777b538SAndroid Build Coastguard Worker fprintf(output, "%s", shift);
1295*6777b538SAndroid Build Coastguard Worker if (cur->index >= 0)
1296*6777b538SAndroid Build Coastguard Worker fprintf(output, "index %d in ", cur->index);
1297*6777b538SAndroid Build Coastguard Worker fprintf(output, "node\n");
1298*6777b538SAndroid Build Coastguard Worker xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user,
1299*6777b538SAndroid Build Coastguard Worker depth + 1);
1300*6777b538SAndroid Build Coastguard Worker } else {
1301*6777b538SAndroid Build Coastguard Worker fprintf(output, "Object is a range :\n");
1302*6777b538SAndroid Build Coastguard Worker fprintf(output, "%s", shift);
1303*6777b538SAndroid Build Coastguard Worker fprintf(output, "From ");
1304*6777b538SAndroid Build Coastguard Worker if (cur->index >= 0)
1305*6777b538SAndroid Build Coastguard Worker fprintf(output, "index %d in ", cur->index);
1306*6777b538SAndroid Build Coastguard Worker fprintf(output, "node\n");
1307*6777b538SAndroid Build Coastguard Worker xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user,
1308*6777b538SAndroid Build Coastguard Worker depth + 1);
1309*6777b538SAndroid Build Coastguard Worker fprintf(output, "%s", shift);
1310*6777b538SAndroid Build Coastguard Worker fprintf(output, "To ");
1311*6777b538SAndroid Build Coastguard Worker if (cur->index2 >= 0)
1312*6777b538SAndroid Build Coastguard Worker fprintf(output, "index %d in ", cur->index2);
1313*6777b538SAndroid Build Coastguard Worker fprintf(output, "node\n");
1314*6777b538SAndroid Build Coastguard Worker xmlXPathDebugDumpNode(output, (xmlNodePtr) cur->user2,
1315*6777b538SAndroid Build Coastguard Worker depth + 1);
1316*6777b538SAndroid Build Coastguard Worker fprintf(output, "\n");
1317*6777b538SAndroid Build Coastguard Worker }
1318*6777b538SAndroid Build Coastguard Worker break;
1319*6777b538SAndroid Build Coastguard Worker case XPATH_LOCATIONSET:
1320*6777b538SAndroid Build Coastguard Worker fprintf(output, "Object is a Location Set:\n");
1321*6777b538SAndroid Build Coastguard Worker xmlXPathDebugDumpLocationSet(output,
1322*6777b538SAndroid Build Coastguard Worker (xmlLocationSetPtr) cur->user, depth);
1323*6777b538SAndroid Build Coastguard Worker break;
1324*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_XPTR_LOCS_ENABLED */
1325*6777b538SAndroid Build Coastguard Worker case XPATH_USERS:
1326*6777b538SAndroid Build Coastguard Worker fprintf(output, "Object is user defined\n");
1327*6777b538SAndroid Build Coastguard Worker break;
1328*6777b538SAndroid Build Coastguard Worker }
1329*6777b538SAndroid Build Coastguard Worker }
1330*6777b538SAndroid Build Coastguard Worker
1331*6777b538SAndroid Build Coastguard Worker static void
xmlXPathDebugDumpStepOp(FILE * output,xmlXPathCompExprPtr comp,xmlXPathStepOpPtr op,int depth)1332*6777b538SAndroid Build Coastguard Worker xmlXPathDebugDumpStepOp(FILE *output, xmlXPathCompExprPtr comp,
1333*6777b538SAndroid Build Coastguard Worker xmlXPathStepOpPtr op, int depth) {
1334*6777b538SAndroid Build Coastguard Worker int i;
1335*6777b538SAndroid Build Coastguard Worker char shift[100];
1336*6777b538SAndroid Build Coastguard Worker
1337*6777b538SAndroid Build Coastguard Worker for (i = 0;((i < depth) && (i < 25));i++)
1338*6777b538SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = ' ';
1339*6777b538SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = 0;
1340*6777b538SAndroid Build Coastguard Worker
1341*6777b538SAndroid Build Coastguard Worker fprintf(output, "%s", shift);
1342*6777b538SAndroid Build Coastguard Worker if (op == NULL) {
1343*6777b538SAndroid Build Coastguard Worker fprintf(output, "Step is NULL\n");
1344*6777b538SAndroid Build Coastguard Worker return;
1345*6777b538SAndroid Build Coastguard Worker }
1346*6777b538SAndroid Build Coastguard Worker switch (op->op) {
1347*6777b538SAndroid Build Coastguard Worker case XPATH_OP_END:
1348*6777b538SAndroid Build Coastguard Worker fprintf(output, "END"); break;
1349*6777b538SAndroid Build Coastguard Worker case XPATH_OP_AND:
1350*6777b538SAndroid Build Coastguard Worker fprintf(output, "AND"); break;
1351*6777b538SAndroid Build Coastguard Worker case XPATH_OP_OR:
1352*6777b538SAndroid Build Coastguard Worker fprintf(output, "OR"); break;
1353*6777b538SAndroid Build Coastguard Worker case XPATH_OP_EQUAL:
1354*6777b538SAndroid Build Coastguard Worker if (op->value)
1355*6777b538SAndroid Build Coastguard Worker fprintf(output, "EQUAL =");
1356*6777b538SAndroid Build Coastguard Worker else
1357*6777b538SAndroid Build Coastguard Worker fprintf(output, "EQUAL !=");
1358*6777b538SAndroid Build Coastguard Worker break;
1359*6777b538SAndroid Build Coastguard Worker case XPATH_OP_CMP:
1360*6777b538SAndroid Build Coastguard Worker if (op->value)
1361*6777b538SAndroid Build Coastguard Worker fprintf(output, "CMP <");
1362*6777b538SAndroid Build Coastguard Worker else
1363*6777b538SAndroid Build Coastguard Worker fprintf(output, "CMP >");
1364*6777b538SAndroid Build Coastguard Worker if (!op->value2)
1365*6777b538SAndroid Build Coastguard Worker fprintf(output, "=");
1366*6777b538SAndroid Build Coastguard Worker break;
1367*6777b538SAndroid Build Coastguard Worker case XPATH_OP_PLUS:
1368*6777b538SAndroid Build Coastguard Worker if (op->value == 0)
1369*6777b538SAndroid Build Coastguard Worker fprintf(output, "PLUS -");
1370*6777b538SAndroid Build Coastguard Worker else if (op->value == 1)
1371*6777b538SAndroid Build Coastguard Worker fprintf(output, "PLUS +");
1372*6777b538SAndroid Build Coastguard Worker else if (op->value == 2)
1373*6777b538SAndroid Build Coastguard Worker fprintf(output, "PLUS unary -");
1374*6777b538SAndroid Build Coastguard Worker else if (op->value == 3)
1375*6777b538SAndroid Build Coastguard Worker fprintf(output, "PLUS unary - -");
1376*6777b538SAndroid Build Coastguard Worker break;
1377*6777b538SAndroid Build Coastguard Worker case XPATH_OP_MULT:
1378*6777b538SAndroid Build Coastguard Worker if (op->value == 0)
1379*6777b538SAndroid Build Coastguard Worker fprintf(output, "MULT *");
1380*6777b538SAndroid Build Coastguard Worker else if (op->value == 1)
1381*6777b538SAndroid Build Coastguard Worker fprintf(output, "MULT div");
1382*6777b538SAndroid Build Coastguard Worker else
1383*6777b538SAndroid Build Coastguard Worker fprintf(output, "MULT mod");
1384*6777b538SAndroid Build Coastguard Worker break;
1385*6777b538SAndroid Build Coastguard Worker case XPATH_OP_UNION:
1386*6777b538SAndroid Build Coastguard Worker fprintf(output, "UNION"); break;
1387*6777b538SAndroid Build Coastguard Worker case XPATH_OP_ROOT:
1388*6777b538SAndroid Build Coastguard Worker fprintf(output, "ROOT"); break;
1389*6777b538SAndroid Build Coastguard Worker case XPATH_OP_NODE:
1390*6777b538SAndroid Build Coastguard Worker fprintf(output, "NODE"); break;
1391*6777b538SAndroid Build Coastguard Worker case XPATH_OP_SORT:
1392*6777b538SAndroid Build Coastguard Worker fprintf(output, "SORT"); break;
1393*6777b538SAndroid Build Coastguard Worker case XPATH_OP_COLLECT: {
1394*6777b538SAndroid Build Coastguard Worker xmlXPathAxisVal axis = (xmlXPathAxisVal)op->value;
1395*6777b538SAndroid Build Coastguard Worker xmlXPathTestVal test = (xmlXPathTestVal)op->value2;
1396*6777b538SAndroid Build Coastguard Worker xmlXPathTypeVal type = (xmlXPathTypeVal)op->value3;
1397*6777b538SAndroid Build Coastguard Worker const xmlChar *prefix = op->value4;
1398*6777b538SAndroid Build Coastguard Worker const xmlChar *name = op->value5;
1399*6777b538SAndroid Build Coastguard Worker
1400*6777b538SAndroid Build Coastguard Worker fprintf(output, "COLLECT ");
1401*6777b538SAndroid Build Coastguard Worker switch (axis) {
1402*6777b538SAndroid Build Coastguard Worker case AXIS_ANCESTOR:
1403*6777b538SAndroid Build Coastguard Worker fprintf(output, " 'ancestors' "); break;
1404*6777b538SAndroid Build Coastguard Worker case AXIS_ANCESTOR_OR_SELF:
1405*6777b538SAndroid Build Coastguard Worker fprintf(output, " 'ancestors-or-self' "); break;
1406*6777b538SAndroid Build Coastguard Worker case AXIS_ATTRIBUTE:
1407*6777b538SAndroid Build Coastguard Worker fprintf(output, " 'attributes' "); break;
1408*6777b538SAndroid Build Coastguard Worker case AXIS_CHILD:
1409*6777b538SAndroid Build Coastguard Worker fprintf(output, " 'child' "); break;
1410*6777b538SAndroid Build Coastguard Worker case AXIS_DESCENDANT:
1411*6777b538SAndroid Build Coastguard Worker fprintf(output, " 'descendant' "); break;
1412*6777b538SAndroid Build Coastguard Worker case AXIS_DESCENDANT_OR_SELF:
1413*6777b538SAndroid Build Coastguard Worker fprintf(output, " 'descendant-or-self' "); break;
1414*6777b538SAndroid Build Coastguard Worker case AXIS_FOLLOWING:
1415*6777b538SAndroid Build Coastguard Worker fprintf(output, " 'following' "); break;
1416*6777b538SAndroid Build Coastguard Worker case AXIS_FOLLOWING_SIBLING:
1417*6777b538SAndroid Build Coastguard Worker fprintf(output, " 'following-siblings' "); break;
1418*6777b538SAndroid Build Coastguard Worker case AXIS_NAMESPACE:
1419*6777b538SAndroid Build Coastguard Worker fprintf(output, " 'namespace' "); break;
1420*6777b538SAndroid Build Coastguard Worker case AXIS_PARENT:
1421*6777b538SAndroid Build Coastguard Worker fprintf(output, " 'parent' "); break;
1422*6777b538SAndroid Build Coastguard Worker case AXIS_PRECEDING:
1423*6777b538SAndroid Build Coastguard Worker fprintf(output, " 'preceding' "); break;
1424*6777b538SAndroid Build Coastguard Worker case AXIS_PRECEDING_SIBLING:
1425*6777b538SAndroid Build Coastguard Worker fprintf(output, " 'preceding-sibling' "); break;
1426*6777b538SAndroid Build Coastguard Worker case AXIS_SELF:
1427*6777b538SAndroid Build Coastguard Worker fprintf(output, " 'self' "); break;
1428*6777b538SAndroid Build Coastguard Worker }
1429*6777b538SAndroid Build Coastguard Worker switch (test) {
1430*6777b538SAndroid Build Coastguard Worker case NODE_TEST_NONE:
1431*6777b538SAndroid Build Coastguard Worker fprintf(output, "'none' "); break;
1432*6777b538SAndroid Build Coastguard Worker case NODE_TEST_TYPE:
1433*6777b538SAndroid Build Coastguard Worker fprintf(output, "'type' "); break;
1434*6777b538SAndroid Build Coastguard Worker case NODE_TEST_PI:
1435*6777b538SAndroid Build Coastguard Worker fprintf(output, "'PI' "); break;
1436*6777b538SAndroid Build Coastguard Worker case NODE_TEST_ALL:
1437*6777b538SAndroid Build Coastguard Worker fprintf(output, "'all' "); break;
1438*6777b538SAndroid Build Coastguard Worker case NODE_TEST_NS:
1439*6777b538SAndroid Build Coastguard Worker fprintf(output, "'namespace' "); break;
1440*6777b538SAndroid Build Coastguard Worker case NODE_TEST_NAME:
1441*6777b538SAndroid Build Coastguard Worker fprintf(output, "'name' "); break;
1442*6777b538SAndroid Build Coastguard Worker }
1443*6777b538SAndroid Build Coastguard Worker switch (type) {
1444*6777b538SAndroid Build Coastguard Worker case NODE_TYPE_NODE:
1445*6777b538SAndroid Build Coastguard Worker fprintf(output, "'node' "); break;
1446*6777b538SAndroid Build Coastguard Worker case NODE_TYPE_COMMENT:
1447*6777b538SAndroid Build Coastguard Worker fprintf(output, "'comment' "); break;
1448*6777b538SAndroid Build Coastguard Worker case NODE_TYPE_TEXT:
1449*6777b538SAndroid Build Coastguard Worker fprintf(output, "'text' "); break;
1450*6777b538SAndroid Build Coastguard Worker case NODE_TYPE_PI:
1451*6777b538SAndroid Build Coastguard Worker fprintf(output, "'PI' "); break;
1452*6777b538SAndroid Build Coastguard Worker }
1453*6777b538SAndroid Build Coastguard Worker if (prefix != NULL)
1454*6777b538SAndroid Build Coastguard Worker fprintf(output, "%s:", prefix);
1455*6777b538SAndroid Build Coastguard Worker if (name != NULL)
1456*6777b538SAndroid Build Coastguard Worker fprintf(output, "%s", (const char *) name);
1457*6777b538SAndroid Build Coastguard Worker break;
1458*6777b538SAndroid Build Coastguard Worker
1459*6777b538SAndroid Build Coastguard Worker }
1460*6777b538SAndroid Build Coastguard Worker case XPATH_OP_VALUE: {
1461*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr object = (xmlXPathObjectPtr) op->value4;
1462*6777b538SAndroid Build Coastguard Worker
1463*6777b538SAndroid Build Coastguard Worker fprintf(output, "ELEM ");
1464*6777b538SAndroid Build Coastguard Worker xmlXPathDebugDumpObject(output, object, 0);
1465*6777b538SAndroid Build Coastguard Worker goto finish;
1466*6777b538SAndroid Build Coastguard Worker }
1467*6777b538SAndroid Build Coastguard Worker case XPATH_OP_VARIABLE: {
1468*6777b538SAndroid Build Coastguard Worker const xmlChar *prefix = op->value5;
1469*6777b538SAndroid Build Coastguard Worker const xmlChar *name = op->value4;
1470*6777b538SAndroid Build Coastguard Worker
1471*6777b538SAndroid Build Coastguard Worker if (prefix != NULL)
1472*6777b538SAndroid Build Coastguard Worker fprintf(output, "VARIABLE %s:%s", prefix, name);
1473*6777b538SAndroid Build Coastguard Worker else
1474*6777b538SAndroid Build Coastguard Worker fprintf(output, "VARIABLE %s", name);
1475*6777b538SAndroid Build Coastguard Worker break;
1476*6777b538SAndroid Build Coastguard Worker }
1477*6777b538SAndroid Build Coastguard Worker case XPATH_OP_FUNCTION: {
1478*6777b538SAndroid Build Coastguard Worker int nbargs = op->value;
1479*6777b538SAndroid Build Coastguard Worker const xmlChar *prefix = op->value5;
1480*6777b538SAndroid Build Coastguard Worker const xmlChar *name = op->value4;
1481*6777b538SAndroid Build Coastguard Worker
1482*6777b538SAndroid Build Coastguard Worker if (prefix != NULL)
1483*6777b538SAndroid Build Coastguard Worker fprintf(output, "FUNCTION %s:%s(%d args)",
1484*6777b538SAndroid Build Coastguard Worker prefix, name, nbargs);
1485*6777b538SAndroid Build Coastguard Worker else
1486*6777b538SAndroid Build Coastguard Worker fprintf(output, "FUNCTION %s(%d args)", name, nbargs);
1487*6777b538SAndroid Build Coastguard Worker break;
1488*6777b538SAndroid Build Coastguard Worker }
1489*6777b538SAndroid Build Coastguard Worker case XPATH_OP_ARG: fprintf(output, "ARG"); break;
1490*6777b538SAndroid Build Coastguard Worker case XPATH_OP_PREDICATE: fprintf(output, "PREDICATE"); break;
1491*6777b538SAndroid Build Coastguard Worker case XPATH_OP_FILTER: fprintf(output, "FILTER"); break;
1492*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
1493*6777b538SAndroid Build Coastguard Worker case XPATH_OP_RANGETO: fprintf(output, "RANGETO"); break;
1494*6777b538SAndroid Build Coastguard Worker #endif
1495*6777b538SAndroid Build Coastguard Worker default:
1496*6777b538SAndroid Build Coastguard Worker fprintf(output, "UNKNOWN %d\n", op->op); return;
1497*6777b538SAndroid Build Coastguard Worker }
1498*6777b538SAndroid Build Coastguard Worker fprintf(output, "\n");
1499*6777b538SAndroid Build Coastguard Worker finish:
1500*6777b538SAndroid Build Coastguard Worker if (op->ch1 >= 0)
1501*6777b538SAndroid Build Coastguard Worker xmlXPathDebugDumpStepOp(output, comp, &comp->steps[op->ch1], depth + 1);
1502*6777b538SAndroid Build Coastguard Worker if (op->ch2 >= 0)
1503*6777b538SAndroid Build Coastguard Worker xmlXPathDebugDumpStepOp(output, comp, &comp->steps[op->ch2], depth + 1);
1504*6777b538SAndroid Build Coastguard Worker }
1505*6777b538SAndroid Build Coastguard Worker
1506*6777b538SAndroid Build Coastguard Worker /**
1507*6777b538SAndroid Build Coastguard Worker * xmlXPathDebugDumpCompExpr:
1508*6777b538SAndroid Build Coastguard Worker * @output: the FILE * for the output
1509*6777b538SAndroid Build Coastguard Worker * @comp: the precompiled XPath expression
1510*6777b538SAndroid Build Coastguard Worker * @depth: the indentation level.
1511*6777b538SAndroid Build Coastguard Worker *
1512*6777b538SAndroid Build Coastguard Worker * Dumps the tree of the compiled XPath expression.
1513*6777b538SAndroid Build Coastguard Worker */
1514*6777b538SAndroid Build Coastguard Worker void
xmlXPathDebugDumpCompExpr(FILE * output,xmlXPathCompExprPtr comp,int depth)1515*6777b538SAndroid Build Coastguard Worker xmlXPathDebugDumpCompExpr(FILE *output, xmlXPathCompExprPtr comp,
1516*6777b538SAndroid Build Coastguard Worker int depth) {
1517*6777b538SAndroid Build Coastguard Worker int i;
1518*6777b538SAndroid Build Coastguard Worker char shift[100];
1519*6777b538SAndroid Build Coastguard Worker
1520*6777b538SAndroid Build Coastguard Worker if ((output == NULL) || (comp == NULL)) return;
1521*6777b538SAndroid Build Coastguard Worker
1522*6777b538SAndroid Build Coastguard Worker for (i = 0;((i < depth) && (i < 25));i++)
1523*6777b538SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = ' ';
1524*6777b538SAndroid Build Coastguard Worker shift[2 * i] = shift[2 * i + 1] = 0;
1525*6777b538SAndroid Build Coastguard Worker
1526*6777b538SAndroid Build Coastguard Worker fprintf(output, "%s", shift);
1527*6777b538SAndroid Build Coastguard Worker
1528*6777b538SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
1529*6777b538SAndroid Build Coastguard Worker if (comp->stream) {
1530*6777b538SAndroid Build Coastguard Worker fprintf(output, "Streaming Expression\n");
1531*6777b538SAndroid Build Coastguard Worker } else
1532*6777b538SAndroid Build Coastguard Worker #endif
1533*6777b538SAndroid Build Coastguard Worker {
1534*6777b538SAndroid Build Coastguard Worker fprintf(output, "Compiled Expression : %d elements\n",
1535*6777b538SAndroid Build Coastguard Worker comp->nbStep);
1536*6777b538SAndroid Build Coastguard Worker i = comp->last;
1537*6777b538SAndroid Build Coastguard Worker xmlXPathDebugDumpStepOp(output, comp, &comp->steps[i], depth + 1);
1538*6777b538SAndroid Build Coastguard Worker }
1539*6777b538SAndroid Build Coastguard Worker }
1540*6777b538SAndroid Build Coastguard Worker
1541*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_DEBUG_ENABLED */
1542*6777b538SAndroid Build Coastguard Worker
1543*6777b538SAndroid Build Coastguard Worker /************************************************************************
1544*6777b538SAndroid Build Coastguard Worker * *
1545*6777b538SAndroid Build Coastguard Worker * XPath object caching *
1546*6777b538SAndroid Build Coastguard Worker * *
1547*6777b538SAndroid Build Coastguard Worker ************************************************************************/
1548*6777b538SAndroid Build Coastguard Worker
1549*6777b538SAndroid Build Coastguard Worker /**
1550*6777b538SAndroid Build Coastguard Worker * xmlXPathNewCache:
1551*6777b538SAndroid Build Coastguard Worker *
1552*6777b538SAndroid Build Coastguard Worker * Create a new object cache
1553*6777b538SAndroid Build Coastguard Worker *
1554*6777b538SAndroid Build Coastguard Worker * Returns the xmlXPathCache just allocated.
1555*6777b538SAndroid Build Coastguard Worker */
1556*6777b538SAndroid Build Coastguard Worker static xmlXPathContextCachePtr
xmlXPathNewCache(void)1557*6777b538SAndroid Build Coastguard Worker xmlXPathNewCache(void)
1558*6777b538SAndroid Build Coastguard Worker {
1559*6777b538SAndroid Build Coastguard Worker xmlXPathContextCachePtr ret;
1560*6777b538SAndroid Build Coastguard Worker
1561*6777b538SAndroid Build Coastguard Worker ret = (xmlXPathContextCachePtr) xmlMalloc(sizeof(xmlXPathContextCache));
1562*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
1563*6777b538SAndroid Build Coastguard Worker return(NULL);
1564*6777b538SAndroid Build Coastguard Worker memset(ret, 0 , sizeof(xmlXPathContextCache));
1565*6777b538SAndroid Build Coastguard Worker ret->maxNodeset = 100;
1566*6777b538SAndroid Build Coastguard Worker ret->maxMisc = 100;
1567*6777b538SAndroid Build Coastguard Worker return(ret);
1568*6777b538SAndroid Build Coastguard Worker }
1569*6777b538SAndroid Build Coastguard Worker
1570*6777b538SAndroid Build Coastguard Worker static void
xmlXPathCacheFreeObjectList(xmlXPathObjectPtr list)1571*6777b538SAndroid Build Coastguard Worker xmlXPathCacheFreeObjectList(xmlXPathObjectPtr list)
1572*6777b538SAndroid Build Coastguard Worker {
1573*6777b538SAndroid Build Coastguard Worker while (list != NULL) {
1574*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr next;
1575*6777b538SAndroid Build Coastguard Worker
1576*6777b538SAndroid Build Coastguard Worker next = (void *) list->stringval;
1577*6777b538SAndroid Build Coastguard Worker
1578*6777b538SAndroid Build Coastguard Worker if (list->nodesetval != NULL) {
1579*6777b538SAndroid Build Coastguard Worker if (list->nodesetval->nodeTab != NULL)
1580*6777b538SAndroid Build Coastguard Worker xmlFree(list->nodesetval->nodeTab);
1581*6777b538SAndroid Build Coastguard Worker xmlFree(list->nodesetval);
1582*6777b538SAndroid Build Coastguard Worker }
1583*6777b538SAndroid Build Coastguard Worker xmlFree(list);
1584*6777b538SAndroid Build Coastguard Worker
1585*6777b538SAndroid Build Coastguard Worker list = next;
1586*6777b538SAndroid Build Coastguard Worker }
1587*6777b538SAndroid Build Coastguard Worker }
1588*6777b538SAndroid Build Coastguard Worker
1589*6777b538SAndroid Build Coastguard Worker static void
xmlXPathFreeCache(xmlXPathContextCachePtr cache)1590*6777b538SAndroid Build Coastguard Worker xmlXPathFreeCache(xmlXPathContextCachePtr cache)
1591*6777b538SAndroid Build Coastguard Worker {
1592*6777b538SAndroid Build Coastguard Worker if (cache == NULL)
1593*6777b538SAndroid Build Coastguard Worker return;
1594*6777b538SAndroid Build Coastguard Worker if (cache->nodesetObjs)
1595*6777b538SAndroid Build Coastguard Worker xmlXPathCacheFreeObjectList(cache->nodesetObjs);
1596*6777b538SAndroid Build Coastguard Worker if (cache->miscObjs)
1597*6777b538SAndroid Build Coastguard Worker xmlXPathCacheFreeObjectList(cache->miscObjs);
1598*6777b538SAndroid Build Coastguard Worker xmlFree(cache);
1599*6777b538SAndroid Build Coastguard Worker }
1600*6777b538SAndroid Build Coastguard Worker
1601*6777b538SAndroid Build Coastguard Worker /**
1602*6777b538SAndroid Build Coastguard Worker * xmlXPathContextSetCache:
1603*6777b538SAndroid Build Coastguard Worker *
1604*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath context
1605*6777b538SAndroid Build Coastguard Worker * @active: enables/disables (creates/frees) the cache
1606*6777b538SAndroid Build Coastguard Worker * @value: a value with semantics dependent on @options
1607*6777b538SAndroid Build Coastguard Worker * @options: options (currently only the value 0 is used)
1608*6777b538SAndroid Build Coastguard Worker *
1609*6777b538SAndroid Build Coastguard Worker * Creates/frees an object cache on the XPath context.
1610*6777b538SAndroid Build Coastguard Worker * If activates XPath objects (xmlXPathObject) will be cached internally
1611*6777b538SAndroid Build Coastguard Worker * to be reused.
1612*6777b538SAndroid Build Coastguard Worker * @options:
1613*6777b538SAndroid Build Coastguard Worker * 0: This will set the XPath object caching:
1614*6777b538SAndroid Build Coastguard Worker * @value:
1615*6777b538SAndroid Build Coastguard Worker * This will set the maximum number of XPath objects
1616*6777b538SAndroid Build Coastguard Worker * to be cached per slot
1617*6777b538SAndroid Build Coastguard Worker * There are two slots for node-set and misc objects.
1618*6777b538SAndroid Build Coastguard Worker * Use <0 for the default number (100).
1619*6777b538SAndroid Build Coastguard Worker * Other values for @options have currently no effect.
1620*6777b538SAndroid Build Coastguard Worker *
1621*6777b538SAndroid Build Coastguard Worker * Returns 0 if the setting succeeded, and -1 on API or internal errors.
1622*6777b538SAndroid Build Coastguard Worker */
1623*6777b538SAndroid Build Coastguard Worker int
xmlXPathContextSetCache(xmlXPathContextPtr ctxt,int active,int value,int options)1624*6777b538SAndroid Build Coastguard Worker xmlXPathContextSetCache(xmlXPathContextPtr ctxt,
1625*6777b538SAndroid Build Coastguard Worker int active,
1626*6777b538SAndroid Build Coastguard Worker int value,
1627*6777b538SAndroid Build Coastguard Worker int options)
1628*6777b538SAndroid Build Coastguard Worker {
1629*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
1630*6777b538SAndroid Build Coastguard Worker return(-1);
1631*6777b538SAndroid Build Coastguard Worker if (active) {
1632*6777b538SAndroid Build Coastguard Worker xmlXPathContextCachePtr cache;
1633*6777b538SAndroid Build Coastguard Worker
1634*6777b538SAndroid Build Coastguard Worker if (ctxt->cache == NULL) {
1635*6777b538SAndroid Build Coastguard Worker ctxt->cache = xmlXPathNewCache();
1636*6777b538SAndroid Build Coastguard Worker if (ctxt->cache == NULL) {
1637*6777b538SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt);
1638*6777b538SAndroid Build Coastguard Worker return(-1);
1639*6777b538SAndroid Build Coastguard Worker }
1640*6777b538SAndroid Build Coastguard Worker }
1641*6777b538SAndroid Build Coastguard Worker cache = (xmlXPathContextCachePtr) ctxt->cache;
1642*6777b538SAndroid Build Coastguard Worker if (options == 0) {
1643*6777b538SAndroid Build Coastguard Worker if (value < 0)
1644*6777b538SAndroid Build Coastguard Worker value = 100;
1645*6777b538SAndroid Build Coastguard Worker cache->maxNodeset = value;
1646*6777b538SAndroid Build Coastguard Worker cache->maxMisc = value;
1647*6777b538SAndroid Build Coastguard Worker }
1648*6777b538SAndroid Build Coastguard Worker } else if (ctxt->cache != NULL) {
1649*6777b538SAndroid Build Coastguard Worker xmlXPathFreeCache((xmlXPathContextCachePtr) ctxt->cache);
1650*6777b538SAndroid Build Coastguard Worker ctxt->cache = NULL;
1651*6777b538SAndroid Build Coastguard Worker }
1652*6777b538SAndroid Build Coastguard Worker return(0);
1653*6777b538SAndroid Build Coastguard Worker }
1654*6777b538SAndroid Build Coastguard Worker
1655*6777b538SAndroid Build Coastguard Worker /**
1656*6777b538SAndroid Build Coastguard Worker * xmlXPathCacheWrapNodeSet:
1657*6777b538SAndroid Build Coastguard Worker * @pctxt: the XPath context
1658*6777b538SAndroid Build Coastguard Worker * @val: the NodePtr value
1659*6777b538SAndroid Build Coastguard Worker *
1660*6777b538SAndroid Build Coastguard Worker * This is the cached version of xmlXPathWrapNodeSet().
1661*6777b538SAndroid Build Coastguard Worker * Wrap the Nodeset @val in a new xmlXPathObjectPtr
1662*6777b538SAndroid Build Coastguard Worker *
1663*6777b538SAndroid Build Coastguard Worker * Returns the created or reused object.
1664*6777b538SAndroid Build Coastguard Worker *
1665*6777b538SAndroid Build Coastguard Worker * In case of error the node set is destroyed and NULL is returned.
1666*6777b538SAndroid Build Coastguard Worker */
1667*6777b538SAndroid Build Coastguard Worker static xmlXPathObjectPtr
xmlXPathCacheWrapNodeSet(xmlXPathParserContextPtr pctxt,xmlNodeSetPtr val)1668*6777b538SAndroid Build Coastguard Worker xmlXPathCacheWrapNodeSet(xmlXPathParserContextPtr pctxt, xmlNodeSetPtr val)
1669*6777b538SAndroid Build Coastguard Worker {
1670*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
1671*6777b538SAndroid Build Coastguard Worker xmlXPathContextPtr ctxt = pctxt->context;
1672*6777b538SAndroid Build Coastguard Worker
1673*6777b538SAndroid Build Coastguard Worker if ((ctxt != NULL) && (ctxt->cache != NULL)) {
1674*6777b538SAndroid Build Coastguard Worker xmlXPathContextCachePtr cache =
1675*6777b538SAndroid Build Coastguard Worker (xmlXPathContextCachePtr) ctxt->cache;
1676*6777b538SAndroid Build Coastguard Worker
1677*6777b538SAndroid Build Coastguard Worker if (cache->miscObjs != NULL) {
1678*6777b538SAndroid Build Coastguard Worker ret = cache->miscObjs;
1679*6777b538SAndroid Build Coastguard Worker cache->miscObjs = (void *) ret->stringval;
1680*6777b538SAndroid Build Coastguard Worker cache->numMisc -= 1;
1681*6777b538SAndroid Build Coastguard Worker ret->stringval = NULL;
1682*6777b538SAndroid Build Coastguard Worker ret->type = XPATH_NODESET;
1683*6777b538SAndroid Build Coastguard Worker ret->nodesetval = val;
1684*6777b538SAndroid Build Coastguard Worker return(ret);
1685*6777b538SAndroid Build Coastguard Worker }
1686*6777b538SAndroid Build Coastguard Worker }
1687*6777b538SAndroid Build Coastguard Worker
1688*6777b538SAndroid Build Coastguard Worker ret = xmlXPathWrapNodeSet(val);
1689*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
1690*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
1691*6777b538SAndroid Build Coastguard Worker return(ret);
1692*6777b538SAndroid Build Coastguard Worker }
1693*6777b538SAndroid Build Coastguard Worker
1694*6777b538SAndroid Build Coastguard Worker /**
1695*6777b538SAndroid Build Coastguard Worker * xmlXPathCacheWrapString:
1696*6777b538SAndroid Build Coastguard Worker * @pctxt the XPath context
1697*6777b538SAndroid Build Coastguard Worker * @val: the xmlChar * value
1698*6777b538SAndroid Build Coastguard Worker *
1699*6777b538SAndroid Build Coastguard Worker * This is the cached version of xmlXPathWrapString().
1700*6777b538SAndroid Build Coastguard Worker * Wraps the @val string into an XPath object.
1701*6777b538SAndroid Build Coastguard Worker *
1702*6777b538SAndroid Build Coastguard Worker * Returns the created or reused object.
1703*6777b538SAndroid Build Coastguard Worker */
1704*6777b538SAndroid Build Coastguard Worker static xmlXPathObjectPtr
xmlXPathCacheWrapString(xmlXPathParserContextPtr pctxt,xmlChar * val)1705*6777b538SAndroid Build Coastguard Worker xmlXPathCacheWrapString(xmlXPathParserContextPtr pctxt, xmlChar *val)
1706*6777b538SAndroid Build Coastguard Worker {
1707*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
1708*6777b538SAndroid Build Coastguard Worker xmlXPathContextPtr ctxt = pctxt->context;
1709*6777b538SAndroid Build Coastguard Worker
1710*6777b538SAndroid Build Coastguard Worker if ((ctxt != NULL) && (ctxt->cache != NULL)) {
1711*6777b538SAndroid Build Coastguard Worker xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
1712*6777b538SAndroid Build Coastguard Worker
1713*6777b538SAndroid Build Coastguard Worker if (cache->miscObjs != NULL) {
1714*6777b538SAndroid Build Coastguard Worker ret = cache->miscObjs;
1715*6777b538SAndroid Build Coastguard Worker cache->miscObjs = (void *) ret->stringval;
1716*6777b538SAndroid Build Coastguard Worker cache->numMisc -= 1;
1717*6777b538SAndroid Build Coastguard Worker ret->type = XPATH_STRING;
1718*6777b538SAndroid Build Coastguard Worker ret->stringval = val;
1719*6777b538SAndroid Build Coastguard Worker return(ret);
1720*6777b538SAndroid Build Coastguard Worker }
1721*6777b538SAndroid Build Coastguard Worker }
1722*6777b538SAndroid Build Coastguard Worker
1723*6777b538SAndroid Build Coastguard Worker ret = xmlXPathWrapString(val);
1724*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
1725*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
1726*6777b538SAndroid Build Coastguard Worker return(ret);
1727*6777b538SAndroid Build Coastguard Worker }
1728*6777b538SAndroid Build Coastguard Worker
1729*6777b538SAndroid Build Coastguard Worker /**
1730*6777b538SAndroid Build Coastguard Worker * xmlXPathCacheNewNodeSet:
1731*6777b538SAndroid Build Coastguard Worker * @pctxt the XPath context
1732*6777b538SAndroid Build Coastguard Worker * @val: the NodePtr value
1733*6777b538SAndroid Build Coastguard Worker *
1734*6777b538SAndroid Build Coastguard Worker * This is the cached version of xmlXPathNewNodeSet().
1735*6777b538SAndroid Build Coastguard Worker * Acquire an xmlXPathObjectPtr of type NodeSet and initialize
1736*6777b538SAndroid Build Coastguard Worker * it with the single Node @val
1737*6777b538SAndroid Build Coastguard Worker *
1738*6777b538SAndroid Build Coastguard Worker * Returns the created or reused object.
1739*6777b538SAndroid Build Coastguard Worker */
1740*6777b538SAndroid Build Coastguard Worker static xmlXPathObjectPtr
xmlXPathCacheNewNodeSet(xmlXPathParserContextPtr pctxt,xmlNodePtr val)1741*6777b538SAndroid Build Coastguard Worker xmlXPathCacheNewNodeSet(xmlXPathParserContextPtr pctxt, xmlNodePtr val)
1742*6777b538SAndroid Build Coastguard Worker {
1743*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
1744*6777b538SAndroid Build Coastguard Worker xmlXPathContextPtr ctxt = pctxt->context;
1745*6777b538SAndroid Build Coastguard Worker
1746*6777b538SAndroid Build Coastguard Worker if ((ctxt != NULL) && (ctxt->cache != NULL)) {
1747*6777b538SAndroid Build Coastguard Worker xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
1748*6777b538SAndroid Build Coastguard Worker
1749*6777b538SAndroid Build Coastguard Worker if (cache->nodesetObjs != NULL) {
1750*6777b538SAndroid Build Coastguard Worker /*
1751*6777b538SAndroid Build Coastguard Worker * Use the nodeset-cache.
1752*6777b538SAndroid Build Coastguard Worker */
1753*6777b538SAndroid Build Coastguard Worker ret = cache->nodesetObjs;
1754*6777b538SAndroid Build Coastguard Worker cache->nodesetObjs = (void *) ret->stringval;
1755*6777b538SAndroid Build Coastguard Worker cache->numNodeset -= 1;
1756*6777b538SAndroid Build Coastguard Worker ret->stringval = NULL;
1757*6777b538SAndroid Build Coastguard Worker ret->type = XPATH_NODESET;
1758*6777b538SAndroid Build Coastguard Worker ret->boolval = 0;
1759*6777b538SAndroid Build Coastguard Worker if (val) {
1760*6777b538SAndroid Build Coastguard Worker if ((ret->nodesetval->nodeMax == 0) ||
1761*6777b538SAndroid Build Coastguard Worker (val->type == XML_NAMESPACE_DECL))
1762*6777b538SAndroid Build Coastguard Worker {
1763*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetAddUnique(ret->nodesetval, val) < 0)
1764*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
1765*6777b538SAndroid Build Coastguard Worker } else {
1766*6777b538SAndroid Build Coastguard Worker ret->nodesetval->nodeTab[0] = val;
1767*6777b538SAndroid Build Coastguard Worker ret->nodesetval->nodeNr = 1;
1768*6777b538SAndroid Build Coastguard Worker }
1769*6777b538SAndroid Build Coastguard Worker }
1770*6777b538SAndroid Build Coastguard Worker return(ret);
1771*6777b538SAndroid Build Coastguard Worker } else if (cache->miscObjs != NULL) {
1772*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr set;
1773*6777b538SAndroid Build Coastguard Worker /*
1774*6777b538SAndroid Build Coastguard Worker * Fallback to misc-cache.
1775*6777b538SAndroid Build Coastguard Worker */
1776*6777b538SAndroid Build Coastguard Worker
1777*6777b538SAndroid Build Coastguard Worker set = xmlXPathNodeSetCreate(val);
1778*6777b538SAndroid Build Coastguard Worker if (set == NULL) {
1779*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
1780*6777b538SAndroid Build Coastguard Worker return(NULL);
1781*6777b538SAndroid Build Coastguard Worker }
1782*6777b538SAndroid Build Coastguard Worker
1783*6777b538SAndroid Build Coastguard Worker ret = cache->miscObjs;
1784*6777b538SAndroid Build Coastguard Worker cache->miscObjs = (void *) ret->stringval;
1785*6777b538SAndroid Build Coastguard Worker cache->numMisc -= 1;
1786*6777b538SAndroid Build Coastguard Worker ret->stringval = NULL;
1787*6777b538SAndroid Build Coastguard Worker ret->type = XPATH_NODESET;
1788*6777b538SAndroid Build Coastguard Worker ret->boolval = 0;
1789*6777b538SAndroid Build Coastguard Worker ret->nodesetval = set;
1790*6777b538SAndroid Build Coastguard Worker return(ret);
1791*6777b538SAndroid Build Coastguard Worker }
1792*6777b538SAndroid Build Coastguard Worker }
1793*6777b538SAndroid Build Coastguard Worker ret = xmlXPathNewNodeSet(val);
1794*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
1795*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
1796*6777b538SAndroid Build Coastguard Worker return(ret);
1797*6777b538SAndroid Build Coastguard Worker }
1798*6777b538SAndroid Build Coastguard Worker
1799*6777b538SAndroid Build Coastguard Worker /**
1800*6777b538SAndroid Build Coastguard Worker * xmlXPathCacheNewString:
1801*6777b538SAndroid Build Coastguard Worker * @pctxt the XPath context
1802*6777b538SAndroid Build Coastguard Worker * @val: the xmlChar * value
1803*6777b538SAndroid Build Coastguard Worker *
1804*6777b538SAndroid Build Coastguard Worker * This is the cached version of xmlXPathNewString().
1805*6777b538SAndroid Build Coastguard Worker * Acquire an xmlXPathObjectPtr of type string and of value @val
1806*6777b538SAndroid Build Coastguard Worker *
1807*6777b538SAndroid Build Coastguard Worker * Returns the created or reused object.
1808*6777b538SAndroid Build Coastguard Worker */
1809*6777b538SAndroid Build Coastguard Worker static xmlXPathObjectPtr
xmlXPathCacheNewString(xmlXPathParserContextPtr pctxt,const xmlChar * val)1810*6777b538SAndroid Build Coastguard Worker xmlXPathCacheNewString(xmlXPathParserContextPtr pctxt, const xmlChar *val)
1811*6777b538SAndroid Build Coastguard Worker {
1812*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
1813*6777b538SAndroid Build Coastguard Worker xmlXPathContextPtr ctxt = pctxt->context;
1814*6777b538SAndroid Build Coastguard Worker
1815*6777b538SAndroid Build Coastguard Worker if ((ctxt != NULL) && (ctxt->cache != NULL)) {
1816*6777b538SAndroid Build Coastguard Worker xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
1817*6777b538SAndroid Build Coastguard Worker
1818*6777b538SAndroid Build Coastguard Worker if (cache->miscObjs != NULL) {
1819*6777b538SAndroid Build Coastguard Worker xmlChar *copy;
1820*6777b538SAndroid Build Coastguard Worker
1821*6777b538SAndroid Build Coastguard Worker if (val == NULL)
1822*6777b538SAndroid Build Coastguard Worker val = BAD_CAST "";
1823*6777b538SAndroid Build Coastguard Worker copy = xmlStrdup(val);
1824*6777b538SAndroid Build Coastguard Worker if (copy == NULL) {
1825*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
1826*6777b538SAndroid Build Coastguard Worker return(NULL);
1827*6777b538SAndroid Build Coastguard Worker }
1828*6777b538SAndroid Build Coastguard Worker
1829*6777b538SAndroid Build Coastguard Worker ret = cache->miscObjs;
1830*6777b538SAndroid Build Coastguard Worker cache->miscObjs = (void *) ret->stringval;
1831*6777b538SAndroid Build Coastguard Worker cache->numMisc -= 1;
1832*6777b538SAndroid Build Coastguard Worker ret->type = XPATH_STRING;
1833*6777b538SAndroid Build Coastguard Worker ret->stringval = copy;
1834*6777b538SAndroid Build Coastguard Worker return(ret);
1835*6777b538SAndroid Build Coastguard Worker }
1836*6777b538SAndroid Build Coastguard Worker }
1837*6777b538SAndroid Build Coastguard Worker
1838*6777b538SAndroid Build Coastguard Worker ret = xmlXPathNewString(val);
1839*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
1840*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
1841*6777b538SAndroid Build Coastguard Worker return(ret);
1842*6777b538SAndroid Build Coastguard Worker }
1843*6777b538SAndroid Build Coastguard Worker
1844*6777b538SAndroid Build Coastguard Worker /**
1845*6777b538SAndroid Build Coastguard Worker * xmlXPathCacheNewCString:
1846*6777b538SAndroid Build Coastguard Worker * @pctxt the XPath context
1847*6777b538SAndroid Build Coastguard Worker * @val: the char * value
1848*6777b538SAndroid Build Coastguard Worker *
1849*6777b538SAndroid Build Coastguard Worker * This is the cached version of xmlXPathNewCString().
1850*6777b538SAndroid Build Coastguard Worker * Acquire an xmlXPathObjectPtr of type string and of value @val
1851*6777b538SAndroid Build Coastguard Worker *
1852*6777b538SAndroid Build Coastguard Worker * Returns the created or reused object.
1853*6777b538SAndroid Build Coastguard Worker */
1854*6777b538SAndroid Build Coastguard Worker static xmlXPathObjectPtr
xmlXPathCacheNewCString(xmlXPathParserContextPtr pctxt,const char * val)1855*6777b538SAndroid Build Coastguard Worker xmlXPathCacheNewCString(xmlXPathParserContextPtr pctxt, const char *val)
1856*6777b538SAndroid Build Coastguard Worker {
1857*6777b538SAndroid Build Coastguard Worker return xmlXPathCacheNewString(pctxt, BAD_CAST val);
1858*6777b538SAndroid Build Coastguard Worker }
1859*6777b538SAndroid Build Coastguard Worker
1860*6777b538SAndroid Build Coastguard Worker /**
1861*6777b538SAndroid Build Coastguard Worker * xmlXPathCacheNewBoolean:
1862*6777b538SAndroid Build Coastguard Worker * @pctxt the XPath context
1863*6777b538SAndroid Build Coastguard Worker * @val: the boolean value
1864*6777b538SAndroid Build Coastguard Worker *
1865*6777b538SAndroid Build Coastguard Worker * This is the cached version of xmlXPathNewBoolean().
1866*6777b538SAndroid Build Coastguard Worker * Acquires an xmlXPathObjectPtr of type boolean and of value @val
1867*6777b538SAndroid Build Coastguard Worker *
1868*6777b538SAndroid Build Coastguard Worker * Returns the created or reused object.
1869*6777b538SAndroid Build Coastguard Worker */
1870*6777b538SAndroid Build Coastguard Worker static xmlXPathObjectPtr
xmlXPathCacheNewBoolean(xmlXPathParserContextPtr pctxt,int val)1871*6777b538SAndroid Build Coastguard Worker xmlXPathCacheNewBoolean(xmlXPathParserContextPtr pctxt, int val)
1872*6777b538SAndroid Build Coastguard Worker {
1873*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
1874*6777b538SAndroid Build Coastguard Worker xmlXPathContextPtr ctxt = pctxt->context;
1875*6777b538SAndroid Build Coastguard Worker
1876*6777b538SAndroid Build Coastguard Worker if ((ctxt != NULL) && (ctxt->cache != NULL)) {
1877*6777b538SAndroid Build Coastguard Worker xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
1878*6777b538SAndroid Build Coastguard Worker
1879*6777b538SAndroid Build Coastguard Worker if (cache->miscObjs != NULL) {
1880*6777b538SAndroid Build Coastguard Worker ret = cache->miscObjs;
1881*6777b538SAndroid Build Coastguard Worker cache->miscObjs = (void *) ret->stringval;
1882*6777b538SAndroid Build Coastguard Worker cache->numMisc -= 1;
1883*6777b538SAndroid Build Coastguard Worker ret->stringval = NULL;
1884*6777b538SAndroid Build Coastguard Worker ret->type = XPATH_BOOLEAN;
1885*6777b538SAndroid Build Coastguard Worker ret->boolval = (val != 0);
1886*6777b538SAndroid Build Coastguard Worker return(ret);
1887*6777b538SAndroid Build Coastguard Worker }
1888*6777b538SAndroid Build Coastguard Worker }
1889*6777b538SAndroid Build Coastguard Worker
1890*6777b538SAndroid Build Coastguard Worker ret = xmlXPathNewBoolean(val);
1891*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
1892*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
1893*6777b538SAndroid Build Coastguard Worker return(ret);
1894*6777b538SAndroid Build Coastguard Worker }
1895*6777b538SAndroid Build Coastguard Worker
1896*6777b538SAndroid Build Coastguard Worker /**
1897*6777b538SAndroid Build Coastguard Worker * xmlXPathCacheNewFloat:
1898*6777b538SAndroid Build Coastguard Worker * @pctxt the XPath context
1899*6777b538SAndroid Build Coastguard Worker * @val: the double value
1900*6777b538SAndroid Build Coastguard Worker *
1901*6777b538SAndroid Build Coastguard Worker * This is the cached version of xmlXPathNewFloat().
1902*6777b538SAndroid Build Coastguard Worker * Acquires an xmlXPathObjectPtr of type double and of value @val
1903*6777b538SAndroid Build Coastguard Worker *
1904*6777b538SAndroid Build Coastguard Worker * Returns the created or reused object.
1905*6777b538SAndroid Build Coastguard Worker */
1906*6777b538SAndroid Build Coastguard Worker static xmlXPathObjectPtr
xmlXPathCacheNewFloat(xmlXPathParserContextPtr pctxt,double val)1907*6777b538SAndroid Build Coastguard Worker xmlXPathCacheNewFloat(xmlXPathParserContextPtr pctxt, double val)
1908*6777b538SAndroid Build Coastguard Worker {
1909*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
1910*6777b538SAndroid Build Coastguard Worker xmlXPathContextPtr ctxt = pctxt->context;
1911*6777b538SAndroid Build Coastguard Worker
1912*6777b538SAndroid Build Coastguard Worker if ((ctxt != NULL) && (ctxt->cache != NULL)) {
1913*6777b538SAndroid Build Coastguard Worker xmlXPathContextCachePtr cache = (xmlXPathContextCachePtr) ctxt->cache;
1914*6777b538SAndroid Build Coastguard Worker
1915*6777b538SAndroid Build Coastguard Worker if (cache->miscObjs != NULL) {
1916*6777b538SAndroid Build Coastguard Worker ret = cache->miscObjs;
1917*6777b538SAndroid Build Coastguard Worker cache->miscObjs = (void *) ret->stringval;
1918*6777b538SAndroid Build Coastguard Worker cache->numMisc -= 1;
1919*6777b538SAndroid Build Coastguard Worker ret->stringval = NULL;
1920*6777b538SAndroid Build Coastguard Worker ret->type = XPATH_NUMBER;
1921*6777b538SAndroid Build Coastguard Worker ret->floatval = val;
1922*6777b538SAndroid Build Coastguard Worker return(ret);
1923*6777b538SAndroid Build Coastguard Worker }
1924*6777b538SAndroid Build Coastguard Worker }
1925*6777b538SAndroid Build Coastguard Worker
1926*6777b538SAndroid Build Coastguard Worker ret = xmlXPathNewFloat(val);
1927*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
1928*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
1929*6777b538SAndroid Build Coastguard Worker return(ret);
1930*6777b538SAndroid Build Coastguard Worker }
1931*6777b538SAndroid Build Coastguard Worker
1932*6777b538SAndroid Build Coastguard Worker /**
1933*6777b538SAndroid Build Coastguard Worker * xmlXPathCacheObjectCopy:
1934*6777b538SAndroid Build Coastguard Worker * @pctxt the XPath context
1935*6777b538SAndroid Build Coastguard Worker * @val: the original object
1936*6777b538SAndroid Build Coastguard Worker *
1937*6777b538SAndroid Build Coastguard Worker * This is the cached version of xmlXPathObjectCopy().
1938*6777b538SAndroid Build Coastguard Worker * Acquire a copy of a given object
1939*6777b538SAndroid Build Coastguard Worker *
1940*6777b538SAndroid Build Coastguard Worker * Returns a created or reused created object.
1941*6777b538SAndroid Build Coastguard Worker */
1942*6777b538SAndroid Build Coastguard Worker static xmlXPathObjectPtr
xmlXPathCacheObjectCopy(xmlXPathParserContextPtr pctxt,xmlXPathObjectPtr val)1943*6777b538SAndroid Build Coastguard Worker xmlXPathCacheObjectCopy(xmlXPathParserContextPtr pctxt, xmlXPathObjectPtr val)
1944*6777b538SAndroid Build Coastguard Worker {
1945*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
1946*6777b538SAndroid Build Coastguard Worker xmlXPathContextPtr ctxt = pctxt->context;
1947*6777b538SAndroid Build Coastguard Worker
1948*6777b538SAndroid Build Coastguard Worker if (val == NULL)
1949*6777b538SAndroid Build Coastguard Worker return(NULL);
1950*6777b538SAndroid Build Coastguard Worker
1951*6777b538SAndroid Build Coastguard Worker if ((ctxt != NULL) && (ctxt->cache != NULL)) {
1952*6777b538SAndroid Build Coastguard Worker switch (val->type) {
1953*6777b538SAndroid Build Coastguard Worker case XPATH_NODESET: {
1954*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr set;
1955*6777b538SAndroid Build Coastguard Worker
1956*6777b538SAndroid Build Coastguard Worker set = xmlXPathNodeSetMerge(NULL, val->nodesetval);
1957*6777b538SAndroid Build Coastguard Worker if (set == NULL) {
1958*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
1959*6777b538SAndroid Build Coastguard Worker return(NULL);
1960*6777b538SAndroid Build Coastguard Worker }
1961*6777b538SAndroid Build Coastguard Worker return(xmlXPathCacheWrapNodeSet(pctxt, set));
1962*6777b538SAndroid Build Coastguard Worker }
1963*6777b538SAndroid Build Coastguard Worker case XPATH_STRING:
1964*6777b538SAndroid Build Coastguard Worker return(xmlXPathCacheNewString(pctxt, val->stringval));
1965*6777b538SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
1966*6777b538SAndroid Build Coastguard Worker return(xmlXPathCacheNewBoolean(pctxt, val->boolval));
1967*6777b538SAndroid Build Coastguard Worker case XPATH_NUMBER:
1968*6777b538SAndroid Build Coastguard Worker return(xmlXPathCacheNewFloat(pctxt, val->floatval));
1969*6777b538SAndroid Build Coastguard Worker default:
1970*6777b538SAndroid Build Coastguard Worker break;
1971*6777b538SAndroid Build Coastguard Worker }
1972*6777b538SAndroid Build Coastguard Worker }
1973*6777b538SAndroid Build Coastguard Worker ret = xmlXPathObjectCopy(val);
1974*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
1975*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
1976*6777b538SAndroid Build Coastguard Worker return(ret);
1977*6777b538SAndroid Build Coastguard Worker }
1978*6777b538SAndroid Build Coastguard Worker
1979*6777b538SAndroid Build Coastguard Worker /************************************************************************
1980*6777b538SAndroid Build Coastguard Worker * *
1981*6777b538SAndroid Build Coastguard Worker * Parser stacks related functions and macros *
1982*6777b538SAndroid Build Coastguard Worker * *
1983*6777b538SAndroid Build Coastguard Worker ************************************************************************/
1984*6777b538SAndroid Build Coastguard Worker
1985*6777b538SAndroid Build Coastguard Worker /**
1986*6777b538SAndroid Build Coastguard Worker * xmlXPathCastToNumberInternal:
1987*6777b538SAndroid Build Coastguard Worker * @ctxt: parser context
1988*6777b538SAndroid Build Coastguard Worker * @val: an XPath object
1989*6777b538SAndroid Build Coastguard Worker *
1990*6777b538SAndroid Build Coastguard Worker * Converts an XPath object to its number value
1991*6777b538SAndroid Build Coastguard Worker *
1992*6777b538SAndroid Build Coastguard Worker * Returns the number value
1993*6777b538SAndroid Build Coastguard Worker */
1994*6777b538SAndroid Build Coastguard Worker static double
xmlXPathCastToNumberInternal(xmlXPathParserContextPtr ctxt,xmlXPathObjectPtr val)1995*6777b538SAndroid Build Coastguard Worker xmlXPathCastToNumberInternal(xmlXPathParserContextPtr ctxt,
1996*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr val) {
1997*6777b538SAndroid Build Coastguard Worker double ret = 0.0;
1998*6777b538SAndroid Build Coastguard Worker
1999*6777b538SAndroid Build Coastguard Worker if (val == NULL)
2000*6777b538SAndroid Build Coastguard Worker return(xmlXPathNAN);
2001*6777b538SAndroid Build Coastguard Worker switch (val->type) {
2002*6777b538SAndroid Build Coastguard Worker case XPATH_UNDEFINED:
2003*6777b538SAndroid Build Coastguard Worker ret = xmlXPathNAN;
2004*6777b538SAndroid Build Coastguard Worker break;
2005*6777b538SAndroid Build Coastguard Worker case XPATH_NODESET:
2006*6777b538SAndroid Build Coastguard Worker case XPATH_XSLT_TREE: {
2007*6777b538SAndroid Build Coastguard Worker xmlChar *str;
2008*6777b538SAndroid Build Coastguard Worker
2009*6777b538SAndroid Build Coastguard Worker str = xmlXPathCastNodeSetToString(val->nodesetval);
2010*6777b538SAndroid Build Coastguard Worker if (str == NULL) {
2011*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
2012*6777b538SAndroid Build Coastguard Worker ret = xmlXPathNAN;
2013*6777b538SAndroid Build Coastguard Worker } else {
2014*6777b538SAndroid Build Coastguard Worker ret = xmlXPathCastStringToNumber(str);
2015*6777b538SAndroid Build Coastguard Worker xmlFree(str);
2016*6777b538SAndroid Build Coastguard Worker }
2017*6777b538SAndroid Build Coastguard Worker break;
2018*6777b538SAndroid Build Coastguard Worker }
2019*6777b538SAndroid Build Coastguard Worker case XPATH_STRING:
2020*6777b538SAndroid Build Coastguard Worker ret = xmlXPathCastStringToNumber(val->stringval);
2021*6777b538SAndroid Build Coastguard Worker break;
2022*6777b538SAndroid Build Coastguard Worker case XPATH_NUMBER:
2023*6777b538SAndroid Build Coastguard Worker ret = val->floatval;
2024*6777b538SAndroid Build Coastguard Worker break;
2025*6777b538SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
2026*6777b538SAndroid Build Coastguard Worker ret = xmlXPathCastBooleanToNumber(val->boolval);
2027*6777b538SAndroid Build Coastguard Worker break;
2028*6777b538SAndroid Build Coastguard Worker case XPATH_USERS:
2029*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
2030*6777b538SAndroid Build Coastguard Worker case XPATH_POINT:
2031*6777b538SAndroid Build Coastguard Worker case XPATH_RANGE:
2032*6777b538SAndroid Build Coastguard Worker case XPATH_LOCATIONSET:
2033*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_XPTR_LOCS_ENABLED */
2034*6777b538SAndroid Build Coastguard Worker /* TODO */
2035*6777b538SAndroid Build Coastguard Worker ret = xmlXPathNAN;
2036*6777b538SAndroid Build Coastguard Worker break;
2037*6777b538SAndroid Build Coastguard Worker }
2038*6777b538SAndroid Build Coastguard Worker return(ret);
2039*6777b538SAndroid Build Coastguard Worker }
2040*6777b538SAndroid Build Coastguard Worker
2041*6777b538SAndroid Build Coastguard Worker /**
2042*6777b538SAndroid Build Coastguard Worker * valuePop:
2043*6777b538SAndroid Build Coastguard Worker * @ctxt: an XPath evaluation context
2044*6777b538SAndroid Build Coastguard Worker *
2045*6777b538SAndroid Build Coastguard Worker * Pops the top XPath object from the value stack
2046*6777b538SAndroid Build Coastguard Worker *
2047*6777b538SAndroid Build Coastguard Worker * Returns the XPath object just removed
2048*6777b538SAndroid Build Coastguard Worker */
2049*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr
valuePop(xmlXPathParserContextPtr ctxt)2050*6777b538SAndroid Build Coastguard Worker valuePop(xmlXPathParserContextPtr ctxt)
2051*6777b538SAndroid Build Coastguard Worker {
2052*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
2053*6777b538SAndroid Build Coastguard Worker
2054*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->valueNr <= 0))
2055*6777b538SAndroid Build Coastguard Worker return (NULL);
2056*6777b538SAndroid Build Coastguard Worker
2057*6777b538SAndroid Build Coastguard Worker ctxt->valueNr--;
2058*6777b538SAndroid Build Coastguard Worker if (ctxt->valueNr > 0)
2059*6777b538SAndroid Build Coastguard Worker ctxt->value = ctxt->valueTab[ctxt->valueNr - 1];
2060*6777b538SAndroid Build Coastguard Worker else
2061*6777b538SAndroid Build Coastguard Worker ctxt->value = NULL;
2062*6777b538SAndroid Build Coastguard Worker ret = ctxt->valueTab[ctxt->valueNr];
2063*6777b538SAndroid Build Coastguard Worker ctxt->valueTab[ctxt->valueNr] = NULL;
2064*6777b538SAndroid Build Coastguard Worker return (ret);
2065*6777b538SAndroid Build Coastguard Worker }
2066*6777b538SAndroid Build Coastguard Worker /**
2067*6777b538SAndroid Build Coastguard Worker * valuePush:
2068*6777b538SAndroid Build Coastguard Worker * @ctxt: an XPath evaluation context
2069*6777b538SAndroid Build Coastguard Worker * @value: the XPath object
2070*6777b538SAndroid Build Coastguard Worker *
2071*6777b538SAndroid Build Coastguard Worker * Pushes a new XPath object on top of the value stack. If value is NULL,
2072*6777b538SAndroid Build Coastguard Worker * a memory error is recorded in the parser context.
2073*6777b538SAndroid Build Coastguard Worker *
2074*6777b538SAndroid Build Coastguard Worker * Returns the number of items on the value stack, or -1 in case of error.
2075*6777b538SAndroid Build Coastguard Worker *
2076*6777b538SAndroid Build Coastguard Worker * The object is destroyed in case of error.
2077*6777b538SAndroid Build Coastguard Worker */
2078*6777b538SAndroid Build Coastguard Worker int
valuePush(xmlXPathParserContextPtr ctxt,xmlXPathObjectPtr value)2079*6777b538SAndroid Build Coastguard Worker valuePush(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr value)
2080*6777b538SAndroid Build Coastguard Worker {
2081*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL) return(-1);
2082*6777b538SAndroid Build Coastguard Worker if (value == NULL) {
2083*6777b538SAndroid Build Coastguard Worker /*
2084*6777b538SAndroid Build Coastguard Worker * A NULL value typically indicates that a memory allocation failed.
2085*6777b538SAndroid Build Coastguard Worker */
2086*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
2087*6777b538SAndroid Build Coastguard Worker return(-1);
2088*6777b538SAndroid Build Coastguard Worker }
2089*6777b538SAndroid Build Coastguard Worker if (ctxt->valueNr >= ctxt->valueMax) {
2090*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr *tmp;
2091*6777b538SAndroid Build Coastguard Worker
2092*6777b538SAndroid Build Coastguard Worker if (ctxt->valueMax >= XPATH_MAX_STACK_DEPTH) {
2093*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
2094*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject(value);
2095*6777b538SAndroid Build Coastguard Worker return (-1);
2096*6777b538SAndroid Build Coastguard Worker }
2097*6777b538SAndroid Build Coastguard Worker tmp = (xmlXPathObjectPtr *) xmlRealloc(ctxt->valueTab,
2098*6777b538SAndroid Build Coastguard Worker 2 * ctxt->valueMax *
2099*6777b538SAndroid Build Coastguard Worker sizeof(ctxt->valueTab[0]));
2100*6777b538SAndroid Build Coastguard Worker if (tmp == NULL) {
2101*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
2102*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject(value);
2103*6777b538SAndroid Build Coastguard Worker return (-1);
2104*6777b538SAndroid Build Coastguard Worker }
2105*6777b538SAndroid Build Coastguard Worker ctxt->valueMax *= 2;
2106*6777b538SAndroid Build Coastguard Worker ctxt->valueTab = tmp;
2107*6777b538SAndroid Build Coastguard Worker }
2108*6777b538SAndroid Build Coastguard Worker ctxt->valueTab[ctxt->valueNr] = value;
2109*6777b538SAndroid Build Coastguard Worker ctxt->value = value;
2110*6777b538SAndroid Build Coastguard Worker return (ctxt->valueNr++);
2111*6777b538SAndroid Build Coastguard Worker }
2112*6777b538SAndroid Build Coastguard Worker
2113*6777b538SAndroid Build Coastguard Worker /**
2114*6777b538SAndroid Build Coastguard Worker * xmlXPathPopBoolean:
2115*6777b538SAndroid Build Coastguard Worker * @ctxt: an XPath parser context
2116*6777b538SAndroid Build Coastguard Worker *
2117*6777b538SAndroid Build Coastguard Worker * Pops a boolean from the stack, handling conversion if needed.
2118*6777b538SAndroid Build Coastguard Worker * Check error with #xmlXPathCheckError.
2119*6777b538SAndroid Build Coastguard Worker *
2120*6777b538SAndroid Build Coastguard Worker * Returns the boolean
2121*6777b538SAndroid Build Coastguard Worker */
2122*6777b538SAndroid Build Coastguard Worker int
xmlXPathPopBoolean(xmlXPathParserContextPtr ctxt)2123*6777b538SAndroid Build Coastguard Worker xmlXPathPopBoolean (xmlXPathParserContextPtr ctxt) {
2124*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr obj;
2125*6777b538SAndroid Build Coastguard Worker int ret;
2126*6777b538SAndroid Build Coastguard Worker
2127*6777b538SAndroid Build Coastguard Worker obj = valuePop(ctxt);
2128*6777b538SAndroid Build Coastguard Worker if (obj == NULL) {
2129*6777b538SAndroid Build Coastguard Worker xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
2130*6777b538SAndroid Build Coastguard Worker return(0);
2131*6777b538SAndroid Build Coastguard Worker }
2132*6777b538SAndroid Build Coastguard Worker if (obj->type != XPATH_BOOLEAN)
2133*6777b538SAndroid Build Coastguard Worker ret = xmlXPathCastToBoolean(obj);
2134*6777b538SAndroid Build Coastguard Worker else
2135*6777b538SAndroid Build Coastguard Worker ret = obj->boolval;
2136*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, obj);
2137*6777b538SAndroid Build Coastguard Worker return(ret);
2138*6777b538SAndroid Build Coastguard Worker }
2139*6777b538SAndroid Build Coastguard Worker
2140*6777b538SAndroid Build Coastguard Worker /**
2141*6777b538SAndroid Build Coastguard Worker * xmlXPathPopNumber:
2142*6777b538SAndroid Build Coastguard Worker * @ctxt: an XPath parser context
2143*6777b538SAndroid Build Coastguard Worker *
2144*6777b538SAndroid Build Coastguard Worker * Pops a number from the stack, handling conversion if needed.
2145*6777b538SAndroid Build Coastguard Worker * Check error with #xmlXPathCheckError.
2146*6777b538SAndroid Build Coastguard Worker *
2147*6777b538SAndroid Build Coastguard Worker * Returns the number
2148*6777b538SAndroid Build Coastguard Worker */
2149*6777b538SAndroid Build Coastguard Worker double
xmlXPathPopNumber(xmlXPathParserContextPtr ctxt)2150*6777b538SAndroid Build Coastguard Worker xmlXPathPopNumber (xmlXPathParserContextPtr ctxt) {
2151*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr obj;
2152*6777b538SAndroid Build Coastguard Worker double ret;
2153*6777b538SAndroid Build Coastguard Worker
2154*6777b538SAndroid Build Coastguard Worker obj = valuePop(ctxt);
2155*6777b538SAndroid Build Coastguard Worker if (obj == NULL) {
2156*6777b538SAndroid Build Coastguard Worker xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
2157*6777b538SAndroid Build Coastguard Worker return(0);
2158*6777b538SAndroid Build Coastguard Worker }
2159*6777b538SAndroid Build Coastguard Worker if (obj->type != XPATH_NUMBER)
2160*6777b538SAndroid Build Coastguard Worker ret = xmlXPathCastToNumberInternal(ctxt, obj);
2161*6777b538SAndroid Build Coastguard Worker else
2162*6777b538SAndroid Build Coastguard Worker ret = obj->floatval;
2163*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, obj);
2164*6777b538SAndroid Build Coastguard Worker return(ret);
2165*6777b538SAndroid Build Coastguard Worker }
2166*6777b538SAndroid Build Coastguard Worker
2167*6777b538SAndroid Build Coastguard Worker /**
2168*6777b538SAndroid Build Coastguard Worker * xmlXPathPopString:
2169*6777b538SAndroid Build Coastguard Worker * @ctxt: an XPath parser context
2170*6777b538SAndroid Build Coastguard Worker *
2171*6777b538SAndroid Build Coastguard Worker * Pops a string from the stack, handling conversion if needed.
2172*6777b538SAndroid Build Coastguard Worker * Check error with #xmlXPathCheckError.
2173*6777b538SAndroid Build Coastguard Worker *
2174*6777b538SAndroid Build Coastguard Worker * Returns the string
2175*6777b538SAndroid Build Coastguard Worker */
2176*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlXPathPopString(xmlXPathParserContextPtr ctxt)2177*6777b538SAndroid Build Coastguard Worker xmlXPathPopString (xmlXPathParserContextPtr ctxt) {
2178*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr obj;
2179*6777b538SAndroid Build Coastguard Worker xmlChar * ret;
2180*6777b538SAndroid Build Coastguard Worker
2181*6777b538SAndroid Build Coastguard Worker obj = valuePop(ctxt);
2182*6777b538SAndroid Build Coastguard Worker if (obj == NULL) {
2183*6777b538SAndroid Build Coastguard Worker xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
2184*6777b538SAndroid Build Coastguard Worker return(NULL);
2185*6777b538SAndroid Build Coastguard Worker }
2186*6777b538SAndroid Build Coastguard Worker ret = xmlXPathCastToString(obj);
2187*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
2188*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
2189*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, obj);
2190*6777b538SAndroid Build Coastguard Worker return(ret);
2191*6777b538SAndroid Build Coastguard Worker }
2192*6777b538SAndroid Build Coastguard Worker
2193*6777b538SAndroid Build Coastguard Worker /**
2194*6777b538SAndroid Build Coastguard Worker * xmlXPathPopNodeSet:
2195*6777b538SAndroid Build Coastguard Worker * @ctxt: an XPath parser context
2196*6777b538SAndroid Build Coastguard Worker *
2197*6777b538SAndroid Build Coastguard Worker * Pops a node-set from the stack, handling conversion if needed.
2198*6777b538SAndroid Build Coastguard Worker * Check error with #xmlXPathCheckError.
2199*6777b538SAndroid Build Coastguard Worker *
2200*6777b538SAndroid Build Coastguard Worker * Returns the node-set
2201*6777b538SAndroid Build Coastguard Worker */
2202*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathPopNodeSet(xmlXPathParserContextPtr ctxt)2203*6777b538SAndroid Build Coastguard Worker xmlXPathPopNodeSet (xmlXPathParserContextPtr ctxt) {
2204*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr obj;
2205*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr ret;
2206*6777b538SAndroid Build Coastguard Worker
2207*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL) return(NULL);
2208*6777b538SAndroid Build Coastguard Worker if (ctxt->value == NULL) {
2209*6777b538SAndroid Build Coastguard Worker xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
2210*6777b538SAndroid Build Coastguard Worker return(NULL);
2211*6777b538SAndroid Build Coastguard Worker }
2212*6777b538SAndroid Build Coastguard Worker if (!xmlXPathStackIsNodeSet(ctxt)) {
2213*6777b538SAndroid Build Coastguard Worker xmlXPathSetTypeError(ctxt);
2214*6777b538SAndroid Build Coastguard Worker return(NULL);
2215*6777b538SAndroid Build Coastguard Worker }
2216*6777b538SAndroid Build Coastguard Worker obj = valuePop(ctxt);
2217*6777b538SAndroid Build Coastguard Worker ret = obj->nodesetval;
2218*6777b538SAndroid Build Coastguard Worker #if 0
2219*6777b538SAndroid Build Coastguard Worker /* to fix memory leak of not clearing obj->user */
2220*6777b538SAndroid Build Coastguard Worker if (obj->boolval && obj->user != NULL)
2221*6777b538SAndroid Build Coastguard Worker xmlFreeNodeList((xmlNodePtr) obj->user);
2222*6777b538SAndroid Build Coastguard Worker #endif
2223*6777b538SAndroid Build Coastguard Worker obj->nodesetval = NULL;
2224*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, obj);
2225*6777b538SAndroid Build Coastguard Worker return(ret);
2226*6777b538SAndroid Build Coastguard Worker }
2227*6777b538SAndroid Build Coastguard Worker
2228*6777b538SAndroid Build Coastguard Worker /**
2229*6777b538SAndroid Build Coastguard Worker * xmlXPathPopExternal:
2230*6777b538SAndroid Build Coastguard Worker * @ctxt: an XPath parser context
2231*6777b538SAndroid Build Coastguard Worker *
2232*6777b538SAndroid Build Coastguard Worker * Pops an external object from the stack, handling conversion if needed.
2233*6777b538SAndroid Build Coastguard Worker * Check error with #xmlXPathCheckError.
2234*6777b538SAndroid Build Coastguard Worker *
2235*6777b538SAndroid Build Coastguard Worker * Returns the object
2236*6777b538SAndroid Build Coastguard Worker */
2237*6777b538SAndroid Build Coastguard Worker void *
xmlXPathPopExternal(xmlXPathParserContextPtr ctxt)2238*6777b538SAndroid Build Coastguard Worker xmlXPathPopExternal (xmlXPathParserContextPtr ctxt) {
2239*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr obj;
2240*6777b538SAndroid Build Coastguard Worker void * ret;
2241*6777b538SAndroid Build Coastguard Worker
2242*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->value == NULL)) {
2243*6777b538SAndroid Build Coastguard Worker xmlXPathSetError(ctxt, XPATH_INVALID_OPERAND);
2244*6777b538SAndroid Build Coastguard Worker return(NULL);
2245*6777b538SAndroid Build Coastguard Worker }
2246*6777b538SAndroid Build Coastguard Worker if (ctxt->value->type != XPATH_USERS) {
2247*6777b538SAndroid Build Coastguard Worker xmlXPathSetTypeError(ctxt);
2248*6777b538SAndroid Build Coastguard Worker return(NULL);
2249*6777b538SAndroid Build Coastguard Worker }
2250*6777b538SAndroid Build Coastguard Worker obj = valuePop(ctxt);
2251*6777b538SAndroid Build Coastguard Worker ret = obj->user;
2252*6777b538SAndroid Build Coastguard Worker obj->user = NULL;
2253*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, obj);
2254*6777b538SAndroid Build Coastguard Worker return(ret);
2255*6777b538SAndroid Build Coastguard Worker }
2256*6777b538SAndroid Build Coastguard Worker
2257*6777b538SAndroid Build Coastguard Worker /*
2258*6777b538SAndroid Build Coastguard Worker * Macros for accessing the content. Those should be used only by the parser,
2259*6777b538SAndroid Build Coastguard Worker * and not exported.
2260*6777b538SAndroid Build Coastguard Worker *
2261*6777b538SAndroid Build Coastguard Worker * Dirty macros, i.e. one need to make assumption on the context to use them
2262*6777b538SAndroid Build Coastguard Worker *
2263*6777b538SAndroid Build Coastguard Worker * CUR_PTR return the current pointer to the xmlChar to be parsed.
2264*6777b538SAndroid Build Coastguard Worker * CUR returns the current xmlChar value, i.e. a 8 bit value
2265*6777b538SAndroid Build Coastguard Worker * in ISO-Latin or UTF-8.
2266*6777b538SAndroid Build Coastguard Worker * This should be used internally by the parser
2267*6777b538SAndroid Build Coastguard Worker * only to compare to ASCII values otherwise it would break when
2268*6777b538SAndroid Build Coastguard Worker * running with UTF-8 encoding.
2269*6777b538SAndroid Build Coastguard Worker * NXT(n) returns the n'th next xmlChar. Same as CUR is should be used only
2270*6777b538SAndroid Build Coastguard Worker * to compare on ASCII based substring.
2271*6777b538SAndroid Build Coastguard Worker * SKIP(n) Skip n xmlChar, and must also be used only to skip ASCII defined
2272*6777b538SAndroid Build Coastguard Worker * strings within the parser.
2273*6777b538SAndroid Build Coastguard Worker * CURRENT Returns the current char value, with the full decoding of
2274*6777b538SAndroid Build Coastguard Worker * UTF-8 if we are using this mode. It returns an int.
2275*6777b538SAndroid Build Coastguard Worker * NEXT Skip to the next character, this does the proper decoding
2276*6777b538SAndroid Build Coastguard Worker * in UTF-8 mode. It also pop-up unfinished entities on the fly.
2277*6777b538SAndroid Build Coastguard Worker * It returns the pointer to the current xmlChar.
2278*6777b538SAndroid Build Coastguard Worker */
2279*6777b538SAndroid Build Coastguard Worker
2280*6777b538SAndroid Build Coastguard Worker #define CUR (*ctxt->cur)
2281*6777b538SAndroid Build Coastguard Worker #define SKIP(val) ctxt->cur += (val)
2282*6777b538SAndroid Build Coastguard Worker #define NXT(val) ctxt->cur[(val)]
2283*6777b538SAndroid Build Coastguard Worker #define CUR_PTR ctxt->cur
2284*6777b538SAndroid Build Coastguard Worker #define CUR_CHAR(l) xmlXPathCurrentChar(ctxt, &l)
2285*6777b538SAndroid Build Coastguard Worker
2286*6777b538SAndroid Build Coastguard Worker #define COPY_BUF(l,b,i,v) \
2287*6777b538SAndroid Build Coastguard Worker if (l == 1) b[i++] = v; \
2288*6777b538SAndroid Build Coastguard Worker else i += xmlCopyChar(l,&b[i],v)
2289*6777b538SAndroid Build Coastguard Worker
2290*6777b538SAndroid Build Coastguard Worker #define NEXTL(l) ctxt->cur += l
2291*6777b538SAndroid Build Coastguard Worker
2292*6777b538SAndroid Build Coastguard Worker #define SKIP_BLANKS \
2293*6777b538SAndroid Build Coastguard Worker while (IS_BLANK_CH(*(ctxt->cur))) NEXT
2294*6777b538SAndroid Build Coastguard Worker
2295*6777b538SAndroid Build Coastguard Worker #define CURRENT (*ctxt->cur)
2296*6777b538SAndroid Build Coastguard Worker #define NEXT ((*ctxt->cur) ? ctxt->cur++: ctxt->cur)
2297*6777b538SAndroid Build Coastguard Worker
2298*6777b538SAndroid Build Coastguard Worker
2299*6777b538SAndroid Build Coastguard Worker #ifndef DBL_DIG
2300*6777b538SAndroid Build Coastguard Worker #define DBL_DIG 16
2301*6777b538SAndroid Build Coastguard Worker #endif
2302*6777b538SAndroid Build Coastguard Worker #ifndef DBL_EPSILON
2303*6777b538SAndroid Build Coastguard Worker #define DBL_EPSILON 1E-9
2304*6777b538SAndroid Build Coastguard Worker #endif
2305*6777b538SAndroid Build Coastguard Worker
2306*6777b538SAndroid Build Coastguard Worker #define UPPER_DOUBLE 1E9
2307*6777b538SAndroid Build Coastguard Worker #define LOWER_DOUBLE 1E-5
2308*6777b538SAndroid Build Coastguard Worker #define LOWER_DOUBLE_EXP 5
2309*6777b538SAndroid Build Coastguard Worker
2310*6777b538SAndroid Build Coastguard Worker #define INTEGER_DIGITS DBL_DIG
2311*6777b538SAndroid Build Coastguard Worker #define FRACTION_DIGITS (DBL_DIG + 1 + (LOWER_DOUBLE_EXP))
2312*6777b538SAndroid Build Coastguard Worker #define EXPONENT_DIGITS (3 + 2)
2313*6777b538SAndroid Build Coastguard Worker
2314*6777b538SAndroid Build Coastguard Worker /**
2315*6777b538SAndroid Build Coastguard Worker * xmlXPathFormatNumber:
2316*6777b538SAndroid Build Coastguard Worker * @number: number to format
2317*6777b538SAndroid Build Coastguard Worker * @buffer: output buffer
2318*6777b538SAndroid Build Coastguard Worker * @buffersize: size of output buffer
2319*6777b538SAndroid Build Coastguard Worker *
2320*6777b538SAndroid Build Coastguard Worker * Convert the number into a string representation.
2321*6777b538SAndroid Build Coastguard Worker */
2322*6777b538SAndroid Build Coastguard Worker static void
xmlXPathFormatNumber(double number,char buffer[],int buffersize)2323*6777b538SAndroid Build Coastguard Worker xmlXPathFormatNumber(double number, char buffer[], int buffersize)
2324*6777b538SAndroid Build Coastguard Worker {
2325*6777b538SAndroid Build Coastguard Worker switch (xmlXPathIsInf(number)) {
2326*6777b538SAndroid Build Coastguard Worker case 1:
2327*6777b538SAndroid Build Coastguard Worker if (buffersize > (int)sizeof("Infinity"))
2328*6777b538SAndroid Build Coastguard Worker snprintf(buffer, buffersize, "Infinity");
2329*6777b538SAndroid Build Coastguard Worker break;
2330*6777b538SAndroid Build Coastguard Worker case -1:
2331*6777b538SAndroid Build Coastguard Worker if (buffersize > (int)sizeof("-Infinity"))
2332*6777b538SAndroid Build Coastguard Worker snprintf(buffer, buffersize, "-Infinity");
2333*6777b538SAndroid Build Coastguard Worker break;
2334*6777b538SAndroid Build Coastguard Worker default:
2335*6777b538SAndroid Build Coastguard Worker if (xmlXPathIsNaN(number)) {
2336*6777b538SAndroid Build Coastguard Worker if (buffersize > (int)sizeof("NaN"))
2337*6777b538SAndroid Build Coastguard Worker snprintf(buffer, buffersize, "NaN");
2338*6777b538SAndroid Build Coastguard Worker } else if (number == 0) {
2339*6777b538SAndroid Build Coastguard Worker /* Omit sign for negative zero. */
2340*6777b538SAndroid Build Coastguard Worker snprintf(buffer, buffersize, "0");
2341*6777b538SAndroid Build Coastguard Worker } else if ((number > INT_MIN) && (number < INT_MAX) &&
2342*6777b538SAndroid Build Coastguard Worker (number == (int) number)) {
2343*6777b538SAndroid Build Coastguard Worker char work[30];
2344*6777b538SAndroid Build Coastguard Worker char *ptr, *cur;
2345*6777b538SAndroid Build Coastguard Worker int value = (int) number;
2346*6777b538SAndroid Build Coastguard Worker
2347*6777b538SAndroid Build Coastguard Worker ptr = &buffer[0];
2348*6777b538SAndroid Build Coastguard Worker if (value == 0) {
2349*6777b538SAndroid Build Coastguard Worker *ptr++ = '0';
2350*6777b538SAndroid Build Coastguard Worker } else {
2351*6777b538SAndroid Build Coastguard Worker snprintf(work, 29, "%d", value);
2352*6777b538SAndroid Build Coastguard Worker cur = &work[0];
2353*6777b538SAndroid Build Coastguard Worker while ((*cur) && (ptr - buffer < buffersize)) {
2354*6777b538SAndroid Build Coastguard Worker *ptr++ = *cur++;
2355*6777b538SAndroid Build Coastguard Worker }
2356*6777b538SAndroid Build Coastguard Worker }
2357*6777b538SAndroid Build Coastguard Worker if (ptr - buffer < buffersize) {
2358*6777b538SAndroid Build Coastguard Worker *ptr = 0;
2359*6777b538SAndroid Build Coastguard Worker } else if (buffersize > 0) {
2360*6777b538SAndroid Build Coastguard Worker ptr--;
2361*6777b538SAndroid Build Coastguard Worker *ptr = 0;
2362*6777b538SAndroid Build Coastguard Worker }
2363*6777b538SAndroid Build Coastguard Worker } else {
2364*6777b538SAndroid Build Coastguard Worker /*
2365*6777b538SAndroid Build Coastguard Worker For the dimension of work,
2366*6777b538SAndroid Build Coastguard Worker DBL_DIG is number of significant digits
2367*6777b538SAndroid Build Coastguard Worker EXPONENT is only needed for "scientific notation"
2368*6777b538SAndroid Build Coastguard Worker 3 is sign, decimal point, and terminating zero
2369*6777b538SAndroid Build Coastguard Worker LOWER_DOUBLE_EXP is max number of leading zeroes in fraction
2370*6777b538SAndroid Build Coastguard Worker Note that this dimension is slightly (a few characters)
2371*6777b538SAndroid Build Coastguard Worker larger than actually necessary.
2372*6777b538SAndroid Build Coastguard Worker */
2373*6777b538SAndroid Build Coastguard Worker char work[DBL_DIG + EXPONENT_DIGITS + 3 + LOWER_DOUBLE_EXP];
2374*6777b538SAndroid Build Coastguard Worker int integer_place, fraction_place;
2375*6777b538SAndroid Build Coastguard Worker char *ptr;
2376*6777b538SAndroid Build Coastguard Worker char *after_fraction;
2377*6777b538SAndroid Build Coastguard Worker double absolute_value;
2378*6777b538SAndroid Build Coastguard Worker int size;
2379*6777b538SAndroid Build Coastguard Worker
2380*6777b538SAndroid Build Coastguard Worker absolute_value = fabs(number);
2381*6777b538SAndroid Build Coastguard Worker
2382*6777b538SAndroid Build Coastguard Worker /*
2383*6777b538SAndroid Build Coastguard Worker * First choose format - scientific or regular floating point.
2384*6777b538SAndroid Build Coastguard Worker * In either case, result is in work, and after_fraction points
2385*6777b538SAndroid Build Coastguard Worker * just past the fractional part.
2386*6777b538SAndroid Build Coastguard Worker */
2387*6777b538SAndroid Build Coastguard Worker if ( ((absolute_value > UPPER_DOUBLE) ||
2388*6777b538SAndroid Build Coastguard Worker (absolute_value < LOWER_DOUBLE)) &&
2389*6777b538SAndroid Build Coastguard Worker (absolute_value != 0.0) ) {
2390*6777b538SAndroid Build Coastguard Worker /* Use scientific notation */
2391*6777b538SAndroid Build Coastguard Worker integer_place = DBL_DIG + EXPONENT_DIGITS + 1;
2392*6777b538SAndroid Build Coastguard Worker fraction_place = DBL_DIG - 1;
2393*6777b538SAndroid Build Coastguard Worker size = snprintf(work, sizeof(work),"%*.*e",
2394*6777b538SAndroid Build Coastguard Worker integer_place, fraction_place, number);
2395*6777b538SAndroid Build Coastguard Worker while ((size > 0) && (work[size] != 'e')) size--;
2396*6777b538SAndroid Build Coastguard Worker
2397*6777b538SAndroid Build Coastguard Worker }
2398*6777b538SAndroid Build Coastguard Worker else {
2399*6777b538SAndroid Build Coastguard Worker /* Use regular notation */
2400*6777b538SAndroid Build Coastguard Worker if (absolute_value > 0.0) {
2401*6777b538SAndroid Build Coastguard Worker integer_place = (int)log10(absolute_value);
2402*6777b538SAndroid Build Coastguard Worker if (integer_place > 0)
2403*6777b538SAndroid Build Coastguard Worker fraction_place = DBL_DIG - integer_place - 1;
2404*6777b538SAndroid Build Coastguard Worker else
2405*6777b538SAndroid Build Coastguard Worker fraction_place = DBL_DIG - integer_place;
2406*6777b538SAndroid Build Coastguard Worker } else {
2407*6777b538SAndroid Build Coastguard Worker fraction_place = 1;
2408*6777b538SAndroid Build Coastguard Worker }
2409*6777b538SAndroid Build Coastguard Worker size = snprintf(work, sizeof(work), "%0.*f",
2410*6777b538SAndroid Build Coastguard Worker fraction_place, number);
2411*6777b538SAndroid Build Coastguard Worker }
2412*6777b538SAndroid Build Coastguard Worker
2413*6777b538SAndroid Build Coastguard Worker /* Remove leading spaces sometimes inserted by snprintf */
2414*6777b538SAndroid Build Coastguard Worker while (work[0] == ' ') {
2415*6777b538SAndroid Build Coastguard Worker for (ptr = &work[0];(ptr[0] = ptr[1]);ptr++);
2416*6777b538SAndroid Build Coastguard Worker size--;
2417*6777b538SAndroid Build Coastguard Worker }
2418*6777b538SAndroid Build Coastguard Worker
2419*6777b538SAndroid Build Coastguard Worker /* Remove fractional trailing zeroes */
2420*6777b538SAndroid Build Coastguard Worker after_fraction = work + size;
2421*6777b538SAndroid Build Coastguard Worker ptr = after_fraction;
2422*6777b538SAndroid Build Coastguard Worker while (*(--ptr) == '0')
2423*6777b538SAndroid Build Coastguard Worker ;
2424*6777b538SAndroid Build Coastguard Worker if (*ptr != '.')
2425*6777b538SAndroid Build Coastguard Worker ptr++;
2426*6777b538SAndroid Build Coastguard Worker while ((*ptr++ = *after_fraction++) != 0);
2427*6777b538SAndroid Build Coastguard Worker
2428*6777b538SAndroid Build Coastguard Worker /* Finally copy result back to caller */
2429*6777b538SAndroid Build Coastguard Worker size = strlen(work) + 1;
2430*6777b538SAndroid Build Coastguard Worker if (size > buffersize) {
2431*6777b538SAndroid Build Coastguard Worker work[buffersize - 1] = 0;
2432*6777b538SAndroid Build Coastguard Worker size = buffersize;
2433*6777b538SAndroid Build Coastguard Worker }
2434*6777b538SAndroid Build Coastguard Worker memmove(buffer, work, size);
2435*6777b538SAndroid Build Coastguard Worker }
2436*6777b538SAndroid Build Coastguard Worker break;
2437*6777b538SAndroid Build Coastguard Worker }
2438*6777b538SAndroid Build Coastguard Worker }
2439*6777b538SAndroid Build Coastguard Worker
2440*6777b538SAndroid Build Coastguard Worker
2441*6777b538SAndroid Build Coastguard Worker /************************************************************************
2442*6777b538SAndroid Build Coastguard Worker * *
2443*6777b538SAndroid Build Coastguard Worker * Routines to handle NodeSets *
2444*6777b538SAndroid Build Coastguard Worker * *
2445*6777b538SAndroid Build Coastguard Worker ************************************************************************/
2446*6777b538SAndroid Build Coastguard Worker
2447*6777b538SAndroid Build Coastguard Worker /**
2448*6777b538SAndroid Build Coastguard Worker * xmlXPathOrderDocElems:
2449*6777b538SAndroid Build Coastguard Worker * @doc: an input document
2450*6777b538SAndroid Build Coastguard Worker *
2451*6777b538SAndroid Build Coastguard Worker * Call this routine to speed up XPath computation on static documents.
2452*6777b538SAndroid Build Coastguard Worker * This stamps all the element nodes with the document order
2453*6777b538SAndroid Build Coastguard Worker * Like for line information, the order is kept in the element->content
2454*6777b538SAndroid Build Coastguard Worker * field, the value stored is actually - the node number (starting at -1)
2455*6777b538SAndroid Build Coastguard Worker * to be able to differentiate from line numbers.
2456*6777b538SAndroid Build Coastguard Worker *
2457*6777b538SAndroid Build Coastguard Worker * Returns the number of elements found in the document or -1 in case
2458*6777b538SAndroid Build Coastguard Worker * of error.
2459*6777b538SAndroid Build Coastguard Worker */
2460*6777b538SAndroid Build Coastguard Worker long
xmlXPathOrderDocElems(xmlDocPtr doc)2461*6777b538SAndroid Build Coastguard Worker xmlXPathOrderDocElems(xmlDocPtr doc) {
2462*6777b538SAndroid Build Coastguard Worker ptrdiff_t count = 0;
2463*6777b538SAndroid Build Coastguard Worker xmlNodePtr cur;
2464*6777b538SAndroid Build Coastguard Worker
2465*6777b538SAndroid Build Coastguard Worker if (doc == NULL)
2466*6777b538SAndroid Build Coastguard Worker return(-1);
2467*6777b538SAndroid Build Coastguard Worker cur = doc->children;
2468*6777b538SAndroid Build Coastguard Worker while (cur != NULL) {
2469*6777b538SAndroid Build Coastguard Worker if (cur->type == XML_ELEMENT_NODE) {
2470*6777b538SAndroid Build Coastguard Worker cur->content = (void *) (-(++count));
2471*6777b538SAndroid Build Coastguard Worker if (cur->children != NULL) {
2472*6777b538SAndroid Build Coastguard Worker cur = cur->children;
2473*6777b538SAndroid Build Coastguard Worker continue;
2474*6777b538SAndroid Build Coastguard Worker }
2475*6777b538SAndroid Build Coastguard Worker }
2476*6777b538SAndroid Build Coastguard Worker if (cur->next != NULL) {
2477*6777b538SAndroid Build Coastguard Worker cur = cur->next;
2478*6777b538SAndroid Build Coastguard Worker continue;
2479*6777b538SAndroid Build Coastguard Worker }
2480*6777b538SAndroid Build Coastguard Worker do {
2481*6777b538SAndroid Build Coastguard Worker cur = cur->parent;
2482*6777b538SAndroid Build Coastguard Worker if (cur == NULL)
2483*6777b538SAndroid Build Coastguard Worker break;
2484*6777b538SAndroid Build Coastguard Worker if (cur == (xmlNodePtr) doc) {
2485*6777b538SAndroid Build Coastguard Worker cur = NULL;
2486*6777b538SAndroid Build Coastguard Worker break;
2487*6777b538SAndroid Build Coastguard Worker }
2488*6777b538SAndroid Build Coastguard Worker if (cur->next != NULL) {
2489*6777b538SAndroid Build Coastguard Worker cur = cur->next;
2490*6777b538SAndroid Build Coastguard Worker break;
2491*6777b538SAndroid Build Coastguard Worker }
2492*6777b538SAndroid Build Coastguard Worker } while (cur != NULL);
2493*6777b538SAndroid Build Coastguard Worker }
2494*6777b538SAndroid Build Coastguard Worker return(count);
2495*6777b538SAndroid Build Coastguard Worker }
2496*6777b538SAndroid Build Coastguard Worker
2497*6777b538SAndroid Build Coastguard Worker /**
2498*6777b538SAndroid Build Coastguard Worker * xmlXPathCmpNodes:
2499*6777b538SAndroid Build Coastguard Worker * @node1: the first node
2500*6777b538SAndroid Build Coastguard Worker * @node2: the second node
2501*6777b538SAndroid Build Coastguard Worker *
2502*6777b538SAndroid Build Coastguard Worker * Compare two nodes w.r.t document order
2503*6777b538SAndroid Build Coastguard Worker *
2504*6777b538SAndroid Build Coastguard Worker * Returns -2 in case of error 1 if first point < second point, 0 if
2505*6777b538SAndroid Build Coastguard Worker * it's the same node, -1 otherwise
2506*6777b538SAndroid Build Coastguard Worker */
2507*6777b538SAndroid Build Coastguard Worker int
xmlXPathCmpNodes(xmlNodePtr node1,xmlNodePtr node2)2508*6777b538SAndroid Build Coastguard Worker xmlXPathCmpNodes(xmlNodePtr node1, xmlNodePtr node2) {
2509*6777b538SAndroid Build Coastguard Worker int depth1, depth2;
2510*6777b538SAndroid Build Coastguard Worker int attr1 = 0, attr2 = 0;
2511*6777b538SAndroid Build Coastguard Worker xmlNodePtr attrNode1 = NULL, attrNode2 = NULL;
2512*6777b538SAndroid Build Coastguard Worker xmlNodePtr cur, root;
2513*6777b538SAndroid Build Coastguard Worker
2514*6777b538SAndroid Build Coastguard Worker if ((node1 == NULL) || (node2 == NULL))
2515*6777b538SAndroid Build Coastguard Worker return(-2);
2516*6777b538SAndroid Build Coastguard Worker /*
2517*6777b538SAndroid Build Coastguard Worker * a couple of optimizations which will avoid computations in most cases
2518*6777b538SAndroid Build Coastguard Worker */
2519*6777b538SAndroid Build Coastguard Worker if (node1 == node2) /* trivial case */
2520*6777b538SAndroid Build Coastguard Worker return(0);
2521*6777b538SAndroid Build Coastguard Worker if (node1->type == XML_ATTRIBUTE_NODE) {
2522*6777b538SAndroid Build Coastguard Worker attr1 = 1;
2523*6777b538SAndroid Build Coastguard Worker attrNode1 = node1;
2524*6777b538SAndroid Build Coastguard Worker node1 = node1->parent;
2525*6777b538SAndroid Build Coastguard Worker }
2526*6777b538SAndroid Build Coastguard Worker if (node2->type == XML_ATTRIBUTE_NODE) {
2527*6777b538SAndroid Build Coastguard Worker attr2 = 1;
2528*6777b538SAndroid Build Coastguard Worker attrNode2 = node2;
2529*6777b538SAndroid Build Coastguard Worker node2 = node2->parent;
2530*6777b538SAndroid Build Coastguard Worker }
2531*6777b538SAndroid Build Coastguard Worker if (node1 == node2) {
2532*6777b538SAndroid Build Coastguard Worker if (attr1 == attr2) {
2533*6777b538SAndroid Build Coastguard Worker /* not required, but we keep attributes in order */
2534*6777b538SAndroid Build Coastguard Worker if (attr1 != 0) {
2535*6777b538SAndroid Build Coastguard Worker cur = attrNode2->prev;
2536*6777b538SAndroid Build Coastguard Worker while (cur != NULL) {
2537*6777b538SAndroid Build Coastguard Worker if (cur == attrNode1)
2538*6777b538SAndroid Build Coastguard Worker return (1);
2539*6777b538SAndroid Build Coastguard Worker cur = cur->prev;
2540*6777b538SAndroid Build Coastguard Worker }
2541*6777b538SAndroid Build Coastguard Worker return (-1);
2542*6777b538SAndroid Build Coastguard Worker }
2543*6777b538SAndroid Build Coastguard Worker return(0);
2544*6777b538SAndroid Build Coastguard Worker }
2545*6777b538SAndroid Build Coastguard Worker if (attr2 == 1)
2546*6777b538SAndroid Build Coastguard Worker return(1);
2547*6777b538SAndroid Build Coastguard Worker return(-1);
2548*6777b538SAndroid Build Coastguard Worker }
2549*6777b538SAndroid Build Coastguard Worker if ((node1->type == XML_NAMESPACE_DECL) ||
2550*6777b538SAndroid Build Coastguard Worker (node2->type == XML_NAMESPACE_DECL))
2551*6777b538SAndroid Build Coastguard Worker return(1);
2552*6777b538SAndroid Build Coastguard Worker if (node1 == node2->prev)
2553*6777b538SAndroid Build Coastguard Worker return(1);
2554*6777b538SAndroid Build Coastguard Worker if (node1 == node2->next)
2555*6777b538SAndroid Build Coastguard Worker return(-1);
2556*6777b538SAndroid Build Coastguard Worker
2557*6777b538SAndroid Build Coastguard Worker /*
2558*6777b538SAndroid Build Coastguard Worker * Speedup using document order if available.
2559*6777b538SAndroid Build Coastguard Worker */
2560*6777b538SAndroid Build Coastguard Worker if ((node1->type == XML_ELEMENT_NODE) &&
2561*6777b538SAndroid Build Coastguard Worker (node2->type == XML_ELEMENT_NODE) &&
2562*6777b538SAndroid Build Coastguard Worker (0 > (ptrdiff_t) node1->content) &&
2563*6777b538SAndroid Build Coastguard Worker (0 > (ptrdiff_t) node2->content) &&
2564*6777b538SAndroid Build Coastguard Worker (node1->doc == node2->doc)) {
2565*6777b538SAndroid Build Coastguard Worker ptrdiff_t l1, l2;
2566*6777b538SAndroid Build Coastguard Worker
2567*6777b538SAndroid Build Coastguard Worker l1 = -((ptrdiff_t) node1->content);
2568*6777b538SAndroid Build Coastguard Worker l2 = -((ptrdiff_t) node2->content);
2569*6777b538SAndroid Build Coastguard Worker if (l1 < l2)
2570*6777b538SAndroid Build Coastguard Worker return(1);
2571*6777b538SAndroid Build Coastguard Worker if (l1 > l2)
2572*6777b538SAndroid Build Coastguard Worker return(-1);
2573*6777b538SAndroid Build Coastguard Worker }
2574*6777b538SAndroid Build Coastguard Worker
2575*6777b538SAndroid Build Coastguard Worker /*
2576*6777b538SAndroid Build Coastguard Worker * compute depth to root
2577*6777b538SAndroid Build Coastguard Worker */
2578*6777b538SAndroid Build Coastguard Worker for (depth2 = 0, cur = node2;cur->parent != NULL;cur = cur->parent) {
2579*6777b538SAndroid Build Coastguard Worker if (cur->parent == node1)
2580*6777b538SAndroid Build Coastguard Worker return(1);
2581*6777b538SAndroid Build Coastguard Worker depth2++;
2582*6777b538SAndroid Build Coastguard Worker }
2583*6777b538SAndroid Build Coastguard Worker root = cur;
2584*6777b538SAndroid Build Coastguard Worker for (depth1 = 0, cur = node1;cur->parent != NULL;cur = cur->parent) {
2585*6777b538SAndroid Build Coastguard Worker if (cur->parent == node2)
2586*6777b538SAndroid Build Coastguard Worker return(-1);
2587*6777b538SAndroid Build Coastguard Worker depth1++;
2588*6777b538SAndroid Build Coastguard Worker }
2589*6777b538SAndroid Build Coastguard Worker /*
2590*6777b538SAndroid Build Coastguard Worker * Distinct document (or distinct entities :-( ) case.
2591*6777b538SAndroid Build Coastguard Worker */
2592*6777b538SAndroid Build Coastguard Worker if (root != cur) {
2593*6777b538SAndroid Build Coastguard Worker return(-2);
2594*6777b538SAndroid Build Coastguard Worker }
2595*6777b538SAndroid Build Coastguard Worker /*
2596*6777b538SAndroid Build Coastguard Worker * get the nearest common ancestor.
2597*6777b538SAndroid Build Coastguard Worker */
2598*6777b538SAndroid Build Coastguard Worker while (depth1 > depth2) {
2599*6777b538SAndroid Build Coastguard Worker depth1--;
2600*6777b538SAndroid Build Coastguard Worker node1 = node1->parent;
2601*6777b538SAndroid Build Coastguard Worker }
2602*6777b538SAndroid Build Coastguard Worker while (depth2 > depth1) {
2603*6777b538SAndroid Build Coastguard Worker depth2--;
2604*6777b538SAndroid Build Coastguard Worker node2 = node2->parent;
2605*6777b538SAndroid Build Coastguard Worker }
2606*6777b538SAndroid Build Coastguard Worker while (node1->parent != node2->parent) {
2607*6777b538SAndroid Build Coastguard Worker node1 = node1->parent;
2608*6777b538SAndroid Build Coastguard Worker node2 = node2->parent;
2609*6777b538SAndroid Build Coastguard Worker /* should not happen but just in case ... */
2610*6777b538SAndroid Build Coastguard Worker if ((node1 == NULL) || (node2 == NULL))
2611*6777b538SAndroid Build Coastguard Worker return(-2);
2612*6777b538SAndroid Build Coastguard Worker }
2613*6777b538SAndroid Build Coastguard Worker /*
2614*6777b538SAndroid Build Coastguard Worker * Find who's first.
2615*6777b538SAndroid Build Coastguard Worker */
2616*6777b538SAndroid Build Coastguard Worker if (node1 == node2->prev)
2617*6777b538SAndroid Build Coastguard Worker return(1);
2618*6777b538SAndroid Build Coastguard Worker if (node1 == node2->next)
2619*6777b538SAndroid Build Coastguard Worker return(-1);
2620*6777b538SAndroid Build Coastguard Worker /*
2621*6777b538SAndroid Build Coastguard Worker * Speedup using document order if available.
2622*6777b538SAndroid Build Coastguard Worker */
2623*6777b538SAndroid Build Coastguard Worker if ((node1->type == XML_ELEMENT_NODE) &&
2624*6777b538SAndroid Build Coastguard Worker (node2->type == XML_ELEMENT_NODE) &&
2625*6777b538SAndroid Build Coastguard Worker (0 > (ptrdiff_t) node1->content) &&
2626*6777b538SAndroid Build Coastguard Worker (0 > (ptrdiff_t) node2->content) &&
2627*6777b538SAndroid Build Coastguard Worker (node1->doc == node2->doc)) {
2628*6777b538SAndroid Build Coastguard Worker ptrdiff_t l1, l2;
2629*6777b538SAndroid Build Coastguard Worker
2630*6777b538SAndroid Build Coastguard Worker l1 = -((ptrdiff_t) node1->content);
2631*6777b538SAndroid Build Coastguard Worker l2 = -((ptrdiff_t) node2->content);
2632*6777b538SAndroid Build Coastguard Worker if (l1 < l2)
2633*6777b538SAndroid Build Coastguard Worker return(1);
2634*6777b538SAndroid Build Coastguard Worker if (l1 > l2)
2635*6777b538SAndroid Build Coastguard Worker return(-1);
2636*6777b538SAndroid Build Coastguard Worker }
2637*6777b538SAndroid Build Coastguard Worker
2638*6777b538SAndroid Build Coastguard Worker for (cur = node1->next;cur != NULL;cur = cur->next)
2639*6777b538SAndroid Build Coastguard Worker if (cur == node2)
2640*6777b538SAndroid Build Coastguard Worker return(1);
2641*6777b538SAndroid Build Coastguard Worker return(-1); /* assume there is no sibling list corruption */
2642*6777b538SAndroid Build Coastguard Worker }
2643*6777b538SAndroid Build Coastguard Worker
2644*6777b538SAndroid Build Coastguard Worker /**
2645*6777b538SAndroid Build Coastguard Worker * xmlXPathNodeSetSort:
2646*6777b538SAndroid Build Coastguard Worker * @set: the node set
2647*6777b538SAndroid Build Coastguard Worker *
2648*6777b538SAndroid Build Coastguard Worker * Sort the node set in document order
2649*6777b538SAndroid Build Coastguard Worker */
2650*6777b538SAndroid Build Coastguard Worker void
xmlXPathNodeSetSort(xmlNodeSetPtr set)2651*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetSort(xmlNodeSetPtr set) {
2652*6777b538SAndroid Build Coastguard Worker #ifndef WITH_TIM_SORT
2653*6777b538SAndroid Build Coastguard Worker int i, j, incr, len;
2654*6777b538SAndroid Build Coastguard Worker xmlNodePtr tmp;
2655*6777b538SAndroid Build Coastguard Worker #endif
2656*6777b538SAndroid Build Coastguard Worker
2657*6777b538SAndroid Build Coastguard Worker if (set == NULL)
2658*6777b538SAndroid Build Coastguard Worker return;
2659*6777b538SAndroid Build Coastguard Worker
2660*6777b538SAndroid Build Coastguard Worker #ifndef WITH_TIM_SORT
2661*6777b538SAndroid Build Coastguard Worker /*
2662*6777b538SAndroid Build Coastguard Worker * Use the old Shell's sort implementation to sort the node-set
2663*6777b538SAndroid Build Coastguard Worker * Timsort ought to be quite faster
2664*6777b538SAndroid Build Coastguard Worker */
2665*6777b538SAndroid Build Coastguard Worker len = set->nodeNr;
2666*6777b538SAndroid Build Coastguard Worker for (incr = len / 2; incr > 0; incr /= 2) {
2667*6777b538SAndroid Build Coastguard Worker for (i = incr; i < len; i++) {
2668*6777b538SAndroid Build Coastguard Worker j = i - incr;
2669*6777b538SAndroid Build Coastguard Worker while (j >= 0) {
2670*6777b538SAndroid Build Coastguard Worker #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
2671*6777b538SAndroid Build Coastguard Worker if (xmlXPathCmpNodesExt(set->nodeTab[j],
2672*6777b538SAndroid Build Coastguard Worker set->nodeTab[j + incr]) == -1)
2673*6777b538SAndroid Build Coastguard Worker #else
2674*6777b538SAndroid Build Coastguard Worker if (xmlXPathCmpNodes(set->nodeTab[j],
2675*6777b538SAndroid Build Coastguard Worker set->nodeTab[j + incr]) == -1)
2676*6777b538SAndroid Build Coastguard Worker #endif
2677*6777b538SAndroid Build Coastguard Worker {
2678*6777b538SAndroid Build Coastguard Worker tmp = set->nodeTab[j];
2679*6777b538SAndroid Build Coastguard Worker set->nodeTab[j] = set->nodeTab[j + incr];
2680*6777b538SAndroid Build Coastguard Worker set->nodeTab[j + incr] = tmp;
2681*6777b538SAndroid Build Coastguard Worker j -= incr;
2682*6777b538SAndroid Build Coastguard Worker } else
2683*6777b538SAndroid Build Coastguard Worker break;
2684*6777b538SAndroid Build Coastguard Worker }
2685*6777b538SAndroid Build Coastguard Worker }
2686*6777b538SAndroid Build Coastguard Worker }
2687*6777b538SAndroid Build Coastguard Worker #else /* WITH_TIM_SORT */
2688*6777b538SAndroid Build Coastguard Worker libxml_domnode_tim_sort(set->nodeTab, set->nodeNr);
2689*6777b538SAndroid Build Coastguard Worker #endif /* WITH_TIM_SORT */
2690*6777b538SAndroid Build Coastguard Worker }
2691*6777b538SAndroid Build Coastguard Worker
2692*6777b538SAndroid Build Coastguard Worker #define XML_NODESET_DEFAULT 10
2693*6777b538SAndroid Build Coastguard Worker /**
2694*6777b538SAndroid Build Coastguard Worker * xmlXPathNodeSetDupNs:
2695*6777b538SAndroid Build Coastguard Worker * @node: the parent node of the namespace XPath node
2696*6777b538SAndroid Build Coastguard Worker * @ns: the libxml namespace declaration node.
2697*6777b538SAndroid Build Coastguard Worker *
2698*6777b538SAndroid Build Coastguard Worker * Namespace node in libxml don't match the XPath semantic. In a node set
2699*6777b538SAndroid Build Coastguard Worker * the namespace nodes are duplicated and the next pointer is set to the
2700*6777b538SAndroid Build Coastguard Worker * parent node in the XPath semantic.
2701*6777b538SAndroid Build Coastguard Worker *
2702*6777b538SAndroid Build Coastguard Worker * Returns the newly created object.
2703*6777b538SAndroid Build Coastguard Worker */
2704*6777b538SAndroid Build Coastguard Worker static xmlNodePtr
xmlXPathNodeSetDupNs(xmlNodePtr node,xmlNsPtr ns)2705*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetDupNs(xmlNodePtr node, xmlNsPtr ns) {
2706*6777b538SAndroid Build Coastguard Worker xmlNsPtr cur;
2707*6777b538SAndroid Build Coastguard Worker
2708*6777b538SAndroid Build Coastguard Worker if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL))
2709*6777b538SAndroid Build Coastguard Worker return(NULL);
2710*6777b538SAndroid Build Coastguard Worker if ((node == NULL) || (node->type == XML_NAMESPACE_DECL))
2711*6777b538SAndroid Build Coastguard Worker return((xmlNodePtr) ns);
2712*6777b538SAndroid Build Coastguard Worker
2713*6777b538SAndroid Build Coastguard Worker /*
2714*6777b538SAndroid Build Coastguard Worker * Allocate a new Namespace and fill the fields.
2715*6777b538SAndroid Build Coastguard Worker */
2716*6777b538SAndroid Build Coastguard Worker cur = (xmlNsPtr) xmlMalloc(sizeof(xmlNs));
2717*6777b538SAndroid Build Coastguard Worker if (cur == NULL)
2718*6777b538SAndroid Build Coastguard Worker return(NULL);
2719*6777b538SAndroid Build Coastguard Worker memset(cur, 0, sizeof(xmlNs));
2720*6777b538SAndroid Build Coastguard Worker cur->type = XML_NAMESPACE_DECL;
2721*6777b538SAndroid Build Coastguard Worker if (ns->href != NULL) {
2722*6777b538SAndroid Build Coastguard Worker cur->href = xmlStrdup(ns->href);
2723*6777b538SAndroid Build Coastguard Worker if (cur->href == NULL) {
2724*6777b538SAndroid Build Coastguard Worker xmlFree(cur);
2725*6777b538SAndroid Build Coastguard Worker return(NULL);
2726*6777b538SAndroid Build Coastguard Worker }
2727*6777b538SAndroid Build Coastguard Worker }
2728*6777b538SAndroid Build Coastguard Worker if (ns->prefix != NULL) {
2729*6777b538SAndroid Build Coastguard Worker cur->prefix = xmlStrdup(ns->prefix);
2730*6777b538SAndroid Build Coastguard Worker if (cur->prefix == NULL) {
2731*6777b538SAndroid Build Coastguard Worker xmlFree((xmlChar *) cur->href);
2732*6777b538SAndroid Build Coastguard Worker xmlFree(cur);
2733*6777b538SAndroid Build Coastguard Worker return(NULL);
2734*6777b538SAndroid Build Coastguard Worker }
2735*6777b538SAndroid Build Coastguard Worker }
2736*6777b538SAndroid Build Coastguard Worker cur->next = (xmlNsPtr) node;
2737*6777b538SAndroid Build Coastguard Worker return((xmlNodePtr) cur);
2738*6777b538SAndroid Build Coastguard Worker }
2739*6777b538SAndroid Build Coastguard Worker
2740*6777b538SAndroid Build Coastguard Worker /**
2741*6777b538SAndroid Build Coastguard Worker * xmlXPathNodeSetFreeNs:
2742*6777b538SAndroid Build Coastguard Worker * @ns: the XPath namespace node found in a nodeset.
2743*6777b538SAndroid Build Coastguard Worker *
2744*6777b538SAndroid Build Coastguard Worker * Namespace nodes in libxml don't match the XPath semantic. In a node set
2745*6777b538SAndroid Build Coastguard Worker * the namespace nodes are duplicated and the next pointer is set to the
2746*6777b538SAndroid Build Coastguard Worker * parent node in the XPath semantic. Check if such a node needs to be freed
2747*6777b538SAndroid Build Coastguard Worker */
2748*6777b538SAndroid Build Coastguard Worker void
xmlXPathNodeSetFreeNs(xmlNsPtr ns)2749*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetFreeNs(xmlNsPtr ns) {
2750*6777b538SAndroid Build Coastguard Worker if ((ns == NULL) || (ns->type != XML_NAMESPACE_DECL))
2751*6777b538SAndroid Build Coastguard Worker return;
2752*6777b538SAndroid Build Coastguard Worker
2753*6777b538SAndroid Build Coastguard Worker if ((ns->next != NULL) && (ns->next->type != XML_NAMESPACE_DECL)) {
2754*6777b538SAndroid Build Coastguard Worker if (ns->href != NULL)
2755*6777b538SAndroid Build Coastguard Worker xmlFree((xmlChar *)ns->href);
2756*6777b538SAndroid Build Coastguard Worker if (ns->prefix != NULL)
2757*6777b538SAndroid Build Coastguard Worker xmlFree((xmlChar *)ns->prefix);
2758*6777b538SAndroid Build Coastguard Worker xmlFree(ns);
2759*6777b538SAndroid Build Coastguard Worker }
2760*6777b538SAndroid Build Coastguard Worker }
2761*6777b538SAndroid Build Coastguard Worker
2762*6777b538SAndroid Build Coastguard Worker /**
2763*6777b538SAndroid Build Coastguard Worker * xmlXPathNodeSetCreate:
2764*6777b538SAndroid Build Coastguard Worker * @val: an initial xmlNodePtr, or NULL
2765*6777b538SAndroid Build Coastguard Worker *
2766*6777b538SAndroid Build Coastguard Worker * Create a new xmlNodeSetPtr of type double and of value @val
2767*6777b538SAndroid Build Coastguard Worker *
2768*6777b538SAndroid Build Coastguard Worker * Returns the newly created object.
2769*6777b538SAndroid Build Coastguard Worker */
2770*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathNodeSetCreate(xmlNodePtr val)2771*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetCreate(xmlNodePtr val) {
2772*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr ret;
2773*6777b538SAndroid Build Coastguard Worker
2774*6777b538SAndroid Build Coastguard Worker ret = (xmlNodeSetPtr) xmlMalloc(sizeof(xmlNodeSet));
2775*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
2776*6777b538SAndroid Build Coastguard Worker return(NULL);
2777*6777b538SAndroid Build Coastguard Worker memset(ret, 0 , sizeof(xmlNodeSet));
2778*6777b538SAndroid Build Coastguard Worker if (val != NULL) {
2779*6777b538SAndroid Build Coastguard Worker ret->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
2780*6777b538SAndroid Build Coastguard Worker sizeof(xmlNodePtr));
2781*6777b538SAndroid Build Coastguard Worker if (ret->nodeTab == NULL) {
2782*6777b538SAndroid Build Coastguard Worker xmlFree(ret);
2783*6777b538SAndroid Build Coastguard Worker return(NULL);
2784*6777b538SAndroid Build Coastguard Worker }
2785*6777b538SAndroid Build Coastguard Worker memset(ret->nodeTab, 0 ,
2786*6777b538SAndroid Build Coastguard Worker XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
2787*6777b538SAndroid Build Coastguard Worker ret->nodeMax = XML_NODESET_DEFAULT;
2788*6777b538SAndroid Build Coastguard Worker if (val->type == XML_NAMESPACE_DECL) {
2789*6777b538SAndroid Build Coastguard Worker xmlNsPtr ns = (xmlNsPtr) val;
2790*6777b538SAndroid Build Coastguard Worker xmlNodePtr nsNode = xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
2791*6777b538SAndroid Build Coastguard Worker
2792*6777b538SAndroid Build Coastguard Worker if (nsNode == NULL) {
2793*6777b538SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(ret);
2794*6777b538SAndroid Build Coastguard Worker return(NULL);
2795*6777b538SAndroid Build Coastguard Worker }
2796*6777b538SAndroid Build Coastguard Worker ret->nodeTab[ret->nodeNr++] = nsNode;
2797*6777b538SAndroid Build Coastguard Worker } else
2798*6777b538SAndroid Build Coastguard Worker ret->nodeTab[ret->nodeNr++] = val;
2799*6777b538SAndroid Build Coastguard Worker }
2800*6777b538SAndroid Build Coastguard Worker return(ret);
2801*6777b538SAndroid Build Coastguard Worker }
2802*6777b538SAndroid Build Coastguard Worker
2803*6777b538SAndroid Build Coastguard Worker /**
2804*6777b538SAndroid Build Coastguard Worker * xmlXPathNodeSetContains:
2805*6777b538SAndroid Build Coastguard Worker * @cur: the node-set
2806*6777b538SAndroid Build Coastguard Worker * @val: the node
2807*6777b538SAndroid Build Coastguard Worker *
2808*6777b538SAndroid Build Coastguard Worker * checks whether @cur contains @val
2809*6777b538SAndroid Build Coastguard Worker *
2810*6777b538SAndroid Build Coastguard Worker * Returns true (1) if @cur contains @val, false (0) otherwise
2811*6777b538SAndroid Build Coastguard Worker */
2812*6777b538SAndroid Build Coastguard Worker int
xmlXPathNodeSetContains(xmlNodeSetPtr cur,xmlNodePtr val)2813*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetContains (xmlNodeSetPtr cur, xmlNodePtr val) {
2814*6777b538SAndroid Build Coastguard Worker int i;
2815*6777b538SAndroid Build Coastguard Worker
2816*6777b538SAndroid Build Coastguard Worker if ((cur == NULL) || (val == NULL)) return(0);
2817*6777b538SAndroid Build Coastguard Worker if (val->type == XML_NAMESPACE_DECL) {
2818*6777b538SAndroid Build Coastguard Worker for (i = 0; i < cur->nodeNr; i++) {
2819*6777b538SAndroid Build Coastguard Worker if (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) {
2820*6777b538SAndroid Build Coastguard Worker xmlNsPtr ns1, ns2;
2821*6777b538SAndroid Build Coastguard Worker
2822*6777b538SAndroid Build Coastguard Worker ns1 = (xmlNsPtr) val;
2823*6777b538SAndroid Build Coastguard Worker ns2 = (xmlNsPtr) cur->nodeTab[i];
2824*6777b538SAndroid Build Coastguard Worker if (ns1 == ns2)
2825*6777b538SAndroid Build Coastguard Worker return(1);
2826*6777b538SAndroid Build Coastguard Worker if ((ns1->next != NULL) && (ns2->next == ns1->next) &&
2827*6777b538SAndroid Build Coastguard Worker (xmlStrEqual(ns1->prefix, ns2->prefix)))
2828*6777b538SAndroid Build Coastguard Worker return(1);
2829*6777b538SAndroid Build Coastguard Worker }
2830*6777b538SAndroid Build Coastguard Worker }
2831*6777b538SAndroid Build Coastguard Worker } else {
2832*6777b538SAndroid Build Coastguard Worker for (i = 0; i < cur->nodeNr; i++) {
2833*6777b538SAndroid Build Coastguard Worker if (cur->nodeTab[i] == val)
2834*6777b538SAndroid Build Coastguard Worker return(1);
2835*6777b538SAndroid Build Coastguard Worker }
2836*6777b538SAndroid Build Coastguard Worker }
2837*6777b538SAndroid Build Coastguard Worker return(0);
2838*6777b538SAndroid Build Coastguard Worker }
2839*6777b538SAndroid Build Coastguard Worker
2840*6777b538SAndroid Build Coastguard Worker /**
2841*6777b538SAndroid Build Coastguard Worker * xmlXPathNodeSetAddNs:
2842*6777b538SAndroid Build Coastguard Worker * @cur: the initial node set
2843*6777b538SAndroid Build Coastguard Worker * @node: the hosting node
2844*6777b538SAndroid Build Coastguard Worker * @ns: a the namespace node
2845*6777b538SAndroid Build Coastguard Worker *
2846*6777b538SAndroid Build Coastguard Worker * add a new namespace node to an existing NodeSet
2847*6777b538SAndroid Build Coastguard Worker *
2848*6777b538SAndroid Build Coastguard Worker * Returns 0 in case of success and -1 in case of error
2849*6777b538SAndroid Build Coastguard Worker */
2850*6777b538SAndroid Build Coastguard Worker int
xmlXPathNodeSetAddNs(xmlNodeSetPtr cur,xmlNodePtr node,xmlNsPtr ns)2851*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetAddNs(xmlNodeSetPtr cur, xmlNodePtr node, xmlNsPtr ns) {
2852*6777b538SAndroid Build Coastguard Worker int i;
2853*6777b538SAndroid Build Coastguard Worker xmlNodePtr nsNode;
2854*6777b538SAndroid Build Coastguard Worker
2855*6777b538SAndroid Build Coastguard Worker if ((cur == NULL) || (ns == NULL) || (node == NULL) ||
2856*6777b538SAndroid Build Coastguard Worker (ns->type != XML_NAMESPACE_DECL) ||
2857*6777b538SAndroid Build Coastguard Worker (node->type != XML_ELEMENT_NODE))
2858*6777b538SAndroid Build Coastguard Worker return(-1);
2859*6777b538SAndroid Build Coastguard Worker
2860*6777b538SAndroid Build Coastguard Worker /* @@ with_ns to check whether namespace nodes should be looked at @@ */
2861*6777b538SAndroid Build Coastguard Worker /*
2862*6777b538SAndroid Build Coastguard Worker * prevent duplicates
2863*6777b538SAndroid Build Coastguard Worker */
2864*6777b538SAndroid Build Coastguard Worker for (i = 0;i < cur->nodeNr;i++) {
2865*6777b538SAndroid Build Coastguard Worker if ((cur->nodeTab[i] != NULL) &&
2866*6777b538SAndroid Build Coastguard Worker (cur->nodeTab[i]->type == XML_NAMESPACE_DECL) &&
2867*6777b538SAndroid Build Coastguard Worker (((xmlNsPtr)cur->nodeTab[i])->next == (xmlNsPtr) node) &&
2868*6777b538SAndroid Build Coastguard Worker (xmlStrEqual(ns->prefix, ((xmlNsPtr)cur->nodeTab[i])->prefix)))
2869*6777b538SAndroid Build Coastguard Worker return(0);
2870*6777b538SAndroid Build Coastguard Worker }
2871*6777b538SAndroid Build Coastguard Worker
2872*6777b538SAndroid Build Coastguard Worker /*
2873*6777b538SAndroid Build Coastguard Worker * grow the nodeTab if needed
2874*6777b538SAndroid Build Coastguard Worker */
2875*6777b538SAndroid Build Coastguard Worker if (cur->nodeMax == 0) {
2876*6777b538SAndroid Build Coastguard Worker cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
2877*6777b538SAndroid Build Coastguard Worker sizeof(xmlNodePtr));
2878*6777b538SAndroid Build Coastguard Worker if (cur->nodeTab == NULL)
2879*6777b538SAndroid Build Coastguard Worker return(-1);
2880*6777b538SAndroid Build Coastguard Worker memset(cur->nodeTab, 0 ,
2881*6777b538SAndroid Build Coastguard Worker XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
2882*6777b538SAndroid Build Coastguard Worker cur->nodeMax = XML_NODESET_DEFAULT;
2883*6777b538SAndroid Build Coastguard Worker } else if (cur->nodeNr == cur->nodeMax) {
2884*6777b538SAndroid Build Coastguard Worker xmlNodePtr *temp;
2885*6777b538SAndroid Build Coastguard Worker
2886*6777b538SAndroid Build Coastguard Worker if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH)
2887*6777b538SAndroid Build Coastguard Worker return(-1);
2888*6777b538SAndroid Build Coastguard Worker temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
2889*6777b538SAndroid Build Coastguard Worker sizeof(xmlNodePtr));
2890*6777b538SAndroid Build Coastguard Worker if (temp == NULL)
2891*6777b538SAndroid Build Coastguard Worker return(-1);
2892*6777b538SAndroid Build Coastguard Worker cur->nodeMax *= 2;
2893*6777b538SAndroid Build Coastguard Worker cur->nodeTab = temp;
2894*6777b538SAndroid Build Coastguard Worker }
2895*6777b538SAndroid Build Coastguard Worker nsNode = xmlXPathNodeSetDupNs(node, ns);
2896*6777b538SAndroid Build Coastguard Worker if(nsNode == NULL)
2897*6777b538SAndroid Build Coastguard Worker return(-1);
2898*6777b538SAndroid Build Coastguard Worker cur->nodeTab[cur->nodeNr++] = nsNode;
2899*6777b538SAndroid Build Coastguard Worker return(0);
2900*6777b538SAndroid Build Coastguard Worker }
2901*6777b538SAndroid Build Coastguard Worker
2902*6777b538SAndroid Build Coastguard Worker /**
2903*6777b538SAndroid Build Coastguard Worker * xmlXPathNodeSetAdd:
2904*6777b538SAndroid Build Coastguard Worker * @cur: the initial node set
2905*6777b538SAndroid Build Coastguard Worker * @val: a new xmlNodePtr
2906*6777b538SAndroid Build Coastguard Worker *
2907*6777b538SAndroid Build Coastguard Worker * add a new xmlNodePtr to an existing NodeSet
2908*6777b538SAndroid Build Coastguard Worker *
2909*6777b538SAndroid Build Coastguard Worker * Returns 0 in case of success, and -1 in case of error
2910*6777b538SAndroid Build Coastguard Worker */
2911*6777b538SAndroid Build Coastguard Worker int
xmlXPathNodeSetAdd(xmlNodeSetPtr cur,xmlNodePtr val)2912*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetAdd(xmlNodeSetPtr cur, xmlNodePtr val) {
2913*6777b538SAndroid Build Coastguard Worker int i;
2914*6777b538SAndroid Build Coastguard Worker
2915*6777b538SAndroid Build Coastguard Worker if ((cur == NULL) || (val == NULL)) return(-1);
2916*6777b538SAndroid Build Coastguard Worker
2917*6777b538SAndroid Build Coastguard Worker /* @@ with_ns to check whether namespace nodes should be looked at @@ */
2918*6777b538SAndroid Build Coastguard Worker /*
2919*6777b538SAndroid Build Coastguard Worker * prevent duplicates
2920*6777b538SAndroid Build Coastguard Worker */
2921*6777b538SAndroid Build Coastguard Worker for (i = 0;i < cur->nodeNr;i++)
2922*6777b538SAndroid Build Coastguard Worker if (cur->nodeTab[i] == val) return(0);
2923*6777b538SAndroid Build Coastguard Worker
2924*6777b538SAndroid Build Coastguard Worker /*
2925*6777b538SAndroid Build Coastguard Worker * grow the nodeTab if needed
2926*6777b538SAndroid Build Coastguard Worker */
2927*6777b538SAndroid Build Coastguard Worker if (cur->nodeMax == 0) {
2928*6777b538SAndroid Build Coastguard Worker cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
2929*6777b538SAndroid Build Coastguard Worker sizeof(xmlNodePtr));
2930*6777b538SAndroid Build Coastguard Worker if (cur->nodeTab == NULL)
2931*6777b538SAndroid Build Coastguard Worker return(-1);
2932*6777b538SAndroid Build Coastguard Worker memset(cur->nodeTab, 0 ,
2933*6777b538SAndroid Build Coastguard Worker XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
2934*6777b538SAndroid Build Coastguard Worker cur->nodeMax = XML_NODESET_DEFAULT;
2935*6777b538SAndroid Build Coastguard Worker } else if (cur->nodeNr == cur->nodeMax) {
2936*6777b538SAndroid Build Coastguard Worker xmlNodePtr *temp;
2937*6777b538SAndroid Build Coastguard Worker
2938*6777b538SAndroid Build Coastguard Worker if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH)
2939*6777b538SAndroid Build Coastguard Worker return(-1);
2940*6777b538SAndroid Build Coastguard Worker temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
2941*6777b538SAndroid Build Coastguard Worker sizeof(xmlNodePtr));
2942*6777b538SAndroid Build Coastguard Worker if (temp == NULL)
2943*6777b538SAndroid Build Coastguard Worker return(-1);
2944*6777b538SAndroid Build Coastguard Worker cur->nodeMax *= 2;
2945*6777b538SAndroid Build Coastguard Worker cur->nodeTab = temp;
2946*6777b538SAndroid Build Coastguard Worker }
2947*6777b538SAndroid Build Coastguard Worker if (val->type == XML_NAMESPACE_DECL) {
2948*6777b538SAndroid Build Coastguard Worker xmlNsPtr ns = (xmlNsPtr) val;
2949*6777b538SAndroid Build Coastguard Worker xmlNodePtr nsNode = xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
2950*6777b538SAndroid Build Coastguard Worker
2951*6777b538SAndroid Build Coastguard Worker if (nsNode == NULL)
2952*6777b538SAndroid Build Coastguard Worker return(-1);
2953*6777b538SAndroid Build Coastguard Worker cur->nodeTab[cur->nodeNr++] = nsNode;
2954*6777b538SAndroid Build Coastguard Worker } else
2955*6777b538SAndroid Build Coastguard Worker cur->nodeTab[cur->nodeNr++] = val;
2956*6777b538SAndroid Build Coastguard Worker return(0);
2957*6777b538SAndroid Build Coastguard Worker }
2958*6777b538SAndroid Build Coastguard Worker
2959*6777b538SAndroid Build Coastguard Worker /**
2960*6777b538SAndroid Build Coastguard Worker * xmlXPathNodeSetAddUnique:
2961*6777b538SAndroid Build Coastguard Worker * @cur: the initial node set
2962*6777b538SAndroid Build Coastguard Worker * @val: a new xmlNodePtr
2963*6777b538SAndroid Build Coastguard Worker *
2964*6777b538SAndroid Build Coastguard Worker * add a new xmlNodePtr to an existing NodeSet, optimized version
2965*6777b538SAndroid Build Coastguard Worker * when we are sure the node is not already in the set.
2966*6777b538SAndroid Build Coastguard Worker *
2967*6777b538SAndroid Build Coastguard Worker * Returns 0 in case of success and -1 in case of failure
2968*6777b538SAndroid Build Coastguard Worker */
2969*6777b538SAndroid Build Coastguard Worker int
xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur,xmlNodePtr val)2970*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetAddUnique(xmlNodeSetPtr cur, xmlNodePtr val) {
2971*6777b538SAndroid Build Coastguard Worker if ((cur == NULL) || (val == NULL)) return(-1);
2972*6777b538SAndroid Build Coastguard Worker
2973*6777b538SAndroid Build Coastguard Worker /* @@ with_ns to check whether namespace nodes should be looked at @@ */
2974*6777b538SAndroid Build Coastguard Worker /*
2975*6777b538SAndroid Build Coastguard Worker * grow the nodeTab if needed
2976*6777b538SAndroid Build Coastguard Worker */
2977*6777b538SAndroid Build Coastguard Worker if (cur->nodeMax == 0) {
2978*6777b538SAndroid Build Coastguard Worker cur->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
2979*6777b538SAndroid Build Coastguard Worker sizeof(xmlNodePtr));
2980*6777b538SAndroid Build Coastguard Worker if (cur->nodeTab == NULL)
2981*6777b538SAndroid Build Coastguard Worker return(-1);
2982*6777b538SAndroid Build Coastguard Worker memset(cur->nodeTab, 0 ,
2983*6777b538SAndroid Build Coastguard Worker XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
2984*6777b538SAndroid Build Coastguard Worker cur->nodeMax = XML_NODESET_DEFAULT;
2985*6777b538SAndroid Build Coastguard Worker } else if (cur->nodeNr == cur->nodeMax) {
2986*6777b538SAndroid Build Coastguard Worker xmlNodePtr *temp;
2987*6777b538SAndroid Build Coastguard Worker
2988*6777b538SAndroid Build Coastguard Worker if (cur->nodeMax >= XPATH_MAX_NODESET_LENGTH)
2989*6777b538SAndroid Build Coastguard Worker return(-1);
2990*6777b538SAndroid Build Coastguard Worker temp = (xmlNodePtr *) xmlRealloc(cur->nodeTab, cur->nodeMax * 2 *
2991*6777b538SAndroid Build Coastguard Worker sizeof(xmlNodePtr));
2992*6777b538SAndroid Build Coastguard Worker if (temp == NULL)
2993*6777b538SAndroid Build Coastguard Worker return(-1);
2994*6777b538SAndroid Build Coastguard Worker cur->nodeTab = temp;
2995*6777b538SAndroid Build Coastguard Worker cur->nodeMax *= 2;
2996*6777b538SAndroid Build Coastguard Worker }
2997*6777b538SAndroid Build Coastguard Worker if (val->type == XML_NAMESPACE_DECL) {
2998*6777b538SAndroid Build Coastguard Worker xmlNsPtr ns = (xmlNsPtr) val;
2999*6777b538SAndroid Build Coastguard Worker xmlNodePtr nsNode = xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
3000*6777b538SAndroid Build Coastguard Worker
3001*6777b538SAndroid Build Coastguard Worker if (nsNode == NULL)
3002*6777b538SAndroid Build Coastguard Worker return(-1);
3003*6777b538SAndroid Build Coastguard Worker cur->nodeTab[cur->nodeNr++] = nsNode;
3004*6777b538SAndroid Build Coastguard Worker } else
3005*6777b538SAndroid Build Coastguard Worker cur->nodeTab[cur->nodeNr++] = val;
3006*6777b538SAndroid Build Coastguard Worker return(0);
3007*6777b538SAndroid Build Coastguard Worker }
3008*6777b538SAndroid Build Coastguard Worker
3009*6777b538SAndroid Build Coastguard Worker /**
3010*6777b538SAndroid Build Coastguard Worker * xmlXPathNodeSetMerge:
3011*6777b538SAndroid Build Coastguard Worker * @val1: the first NodeSet or NULL
3012*6777b538SAndroid Build Coastguard Worker * @val2: the second NodeSet
3013*6777b538SAndroid Build Coastguard Worker *
3014*6777b538SAndroid Build Coastguard Worker * Merges two nodesets, all nodes from @val2 are added to @val1
3015*6777b538SAndroid Build Coastguard Worker * if @val1 is NULL, a new set is created and copied from @val2
3016*6777b538SAndroid Build Coastguard Worker *
3017*6777b538SAndroid Build Coastguard Worker * Returns @val1 once extended or NULL in case of error.
3018*6777b538SAndroid Build Coastguard Worker *
3019*6777b538SAndroid Build Coastguard Worker * Frees @val1 in case of error.
3020*6777b538SAndroid Build Coastguard Worker */
3021*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathNodeSetMerge(xmlNodeSetPtr val1,xmlNodeSetPtr val2)3022*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetMerge(xmlNodeSetPtr val1, xmlNodeSetPtr val2) {
3023*6777b538SAndroid Build Coastguard Worker int i, j, initNr, skip;
3024*6777b538SAndroid Build Coastguard Worker xmlNodePtr n1, n2;
3025*6777b538SAndroid Build Coastguard Worker
3026*6777b538SAndroid Build Coastguard Worker if (val1 == NULL) {
3027*6777b538SAndroid Build Coastguard Worker val1 = xmlXPathNodeSetCreate(NULL);
3028*6777b538SAndroid Build Coastguard Worker if (val1 == NULL)
3029*6777b538SAndroid Build Coastguard Worker return (NULL);
3030*6777b538SAndroid Build Coastguard Worker }
3031*6777b538SAndroid Build Coastguard Worker if (val2 == NULL)
3032*6777b538SAndroid Build Coastguard Worker return(val1);
3033*6777b538SAndroid Build Coastguard Worker
3034*6777b538SAndroid Build Coastguard Worker /* @@ with_ns to check whether namespace nodes should be looked at @@ */
3035*6777b538SAndroid Build Coastguard Worker initNr = val1->nodeNr;
3036*6777b538SAndroid Build Coastguard Worker
3037*6777b538SAndroid Build Coastguard Worker for (i = 0;i < val2->nodeNr;i++) {
3038*6777b538SAndroid Build Coastguard Worker n2 = val2->nodeTab[i];
3039*6777b538SAndroid Build Coastguard Worker /*
3040*6777b538SAndroid Build Coastguard Worker * check against duplicates
3041*6777b538SAndroid Build Coastguard Worker */
3042*6777b538SAndroid Build Coastguard Worker skip = 0;
3043*6777b538SAndroid Build Coastguard Worker for (j = 0; j < initNr; j++) {
3044*6777b538SAndroid Build Coastguard Worker n1 = val1->nodeTab[j];
3045*6777b538SAndroid Build Coastguard Worker if (n1 == n2) {
3046*6777b538SAndroid Build Coastguard Worker skip = 1;
3047*6777b538SAndroid Build Coastguard Worker break;
3048*6777b538SAndroid Build Coastguard Worker } else if ((n1->type == XML_NAMESPACE_DECL) &&
3049*6777b538SAndroid Build Coastguard Worker (n2->type == XML_NAMESPACE_DECL)) {
3050*6777b538SAndroid Build Coastguard Worker if ((((xmlNsPtr) n1)->next == ((xmlNsPtr) n2)->next) &&
3051*6777b538SAndroid Build Coastguard Worker (xmlStrEqual(((xmlNsPtr) n1)->prefix,
3052*6777b538SAndroid Build Coastguard Worker ((xmlNsPtr) n2)->prefix)))
3053*6777b538SAndroid Build Coastguard Worker {
3054*6777b538SAndroid Build Coastguard Worker skip = 1;
3055*6777b538SAndroid Build Coastguard Worker break;
3056*6777b538SAndroid Build Coastguard Worker }
3057*6777b538SAndroid Build Coastguard Worker }
3058*6777b538SAndroid Build Coastguard Worker }
3059*6777b538SAndroid Build Coastguard Worker if (skip)
3060*6777b538SAndroid Build Coastguard Worker continue;
3061*6777b538SAndroid Build Coastguard Worker
3062*6777b538SAndroid Build Coastguard Worker /*
3063*6777b538SAndroid Build Coastguard Worker * grow the nodeTab if needed
3064*6777b538SAndroid Build Coastguard Worker */
3065*6777b538SAndroid Build Coastguard Worker if (val1->nodeMax == 0) {
3066*6777b538SAndroid Build Coastguard Worker val1->nodeTab = (xmlNodePtr *) xmlMalloc(XML_NODESET_DEFAULT *
3067*6777b538SAndroid Build Coastguard Worker sizeof(xmlNodePtr));
3068*6777b538SAndroid Build Coastguard Worker if (val1->nodeTab == NULL)
3069*6777b538SAndroid Build Coastguard Worker goto error;
3070*6777b538SAndroid Build Coastguard Worker memset(val1->nodeTab, 0 ,
3071*6777b538SAndroid Build Coastguard Worker XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
3072*6777b538SAndroid Build Coastguard Worker val1->nodeMax = XML_NODESET_DEFAULT;
3073*6777b538SAndroid Build Coastguard Worker } else if (val1->nodeNr == val1->nodeMax) {
3074*6777b538SAndroid Build Coastguard Worker xmlNodePtr *temp;
3075*6777b538SAndroid Build Coastguard Worker
3076*6777b538SAndroid Build Coastguard Worker if (val1->nodeMax >= XPATH_MAX_NODESET_LENGTH)
3077*6777b538SAndroid Build Coastguard Worker goto error;
3078*6777b538SAndroid Build Coastguard Worker temp = (xmlNodePtr *) xmlRealloc(val1->nodeTab, val1->nodeMax * 2 *
3079*6777b538SAndroid Build Coastguard Worker sizeof(xmlNodePtr));
3080*6777b538SAndroid Build Coastguard Worker if (temp == NULL)
3081*6777b538SAndroid Build Coastguard Worker goto error;
3082*6777b538SAndroid Build Coastguard Worker val1->nodeTab = temp;
3083*6777b538SAndroid Build Coastguard Worker val1->nodeMax *= 2;
3084*6777b538SAndroid Build Coastguard Worker }
3085*6777b538SAndroid Build Coastguard Worker if (n2->type == XML_NAMESPACE_DECL) {
3086*6777b538SAndroid Build Coastguard Worker xmlNsPtr ns = (xmlNsPtr) n2;
3087*6777b538SAndroid Build Coastguard Worker xmlNodePtr nsNode = xmlXPathNodeSetDupNs((xmlNodePtr) ns->next, ns);
3088*6777b538SAndroid Build Coastguard Worker
3089*6777b538SAndroid Build Coastguard Worker if (nsNode == NULL)
3090*6777b538SAndroid Build Coastguard Worker goto error;
3091*6777b538SAndroid Build Coastguard Worker val1->nodeTab[val1->nodeNr++] = nsNode;
3092*6777b538SAndroid Build Coastguard Worker } else
3093*6777b538SAndroid Build Coastguard Worker val1->nodeTab[val1->nodeNr++] = n2;
3094*6777b538SAndroid Build Coastguard Worker }
3095*6777b538SAndroid Build Coastguard Worker
3096*6777b538SAndroid Build Coastguard Worker return(val1);
3097*6777b538SAndroid Build Coastguard Worker
3098*6777b538SAndroid Build Coastguard Worker error:
3099*6777b538SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(val1);
3100*6777b538SAndroid Build Coastguard Worker return(NULL);
3101*6777b538SAndroid Build Coastguard Worker }
3102*6777b538SAndroid Build Coastguard Worker
3103*6777b538SAndroid Build Coastguard Worker
3104*6777b538SAndroid Build Coastguard Worker /**
3105*6777b538SAndroid Build Coastguard Worker * xmlXPathNodeSetMergeAndClear:
3106*6777b538SAndroid Build Coastguard Worker * @set1: the first NodeSet or NULL
3107*6777b538SAndroid Build Coastguard Worker * @set2: the second NodeSet
3108*6777b538SAndroid Build Coastguard Worker *
3109*6777b538SAndroid Build Coastguard Worker * Merges two nodesets, all nodes from @set2 are added to @set1.
3110*6777b538SAndroid Build Coastguard Worker * Checks for duplicate nodes. Clears set2.
3111*6777b538SAndroid Build Coastguard Worker *
3112*6777b538SAndroid Build Coastguard Worker * Returns @set1 once extended or NULL in case of error.
3113*6777b538SAndroid Build Coastguard Worker *
3114*6777b538SAndroid Build Coastguard Worker * Frees @set1 in case of error.
3115*6777b538SAndroid Build Coastguard Worker */
3116*6777b538SAndroid Build Coastguard Worker static xmlNodeSetPtr
xmlXPathNodeSetMergeAndClear(xmlNodeSetPtr set1,xmlNodeSetPtr set2)3117*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetMergeAndClear(xmlNodeSetPtr set1, xmlNodeSetPtr set2)
3118*6777b538SAndroid Build Coastguard Worker {
3119*6777b538SAndroid Build Coastguard Worker {
3120*6777b538SAndroid Build Coastguard Worker int i, j, initNbSet1;
3121*6777b538SAndroid Build Coastguard Worker xmlNodePtr n1, n2;
3122*6777b538SAndroid Build Coastguard Worker
3123*6777b538SAndroid Build Coastguard Worker initNbSet1 = set1->nodeNr;
3124*6777b538SAndroid Build Coastguard Worker for (i = 0;i < set2->nodeNr;i++) {
3125*6777b538SAndroid Build Coastguard Worker n2 = set2->nodeTab[i];
3126*6777b538SAndroid Build Coastguard Worker /*
3127*6777b538SAndroid Build Coastguard Worker * Skip duplicates.
3128*6777b538SAndroid Build Coastguard Worker */
3129*6777b538SAndroid Build Coastguard Worker for (j = 0; j < initNbSet1; j++) {
3130*6777b538SAndroid Build Coastguard Worker n1 = set1->nodeTab[j];
3131*6777b538SAndroid Build Coastguard Worker if (n1 == n2) {
3132*6777b538SAndroid Build Coastguard Worker goto skip_node;
3133*6777b538SAndroid Build Coastguard Worker } else if ((n1->type == XML_NAMESPACE_DECL) &&
3134*6777b538SAndroid Build Coastguard Worker (n2->type == XML_NAMESPACE_DECL))
3135*6777b538SAndroid Build Coastguard Worker {
3136*6777b538SAndroid Build Coastguard Worker if ((((xmlNsPtr) n1)->next == ((xmlNsPtr) n2)->next) &&
3137*6777b538SAndroid Build Coastguard Worker (xmlStrEqual(((xmlNsPtr) n1)->prefix,
3138*6777b538SAndroid Build Coastguard Worker ((xmlNsPtr) n2)->prefix)))
3139*6777b538SAndroid Build Coastguard Worker {
3140*6777b538SAndroid Build Coastguard Worker /*
3141*6777b538SAndroid Build Coastguard Worker * Free the namespace node.
3142*6777b538SAndroid Build Coastguard Worker */
3143*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetFreeNs((xmlNsPtr) n2);
3144*6777b538SAndroid Build Coastguard Worker goto skip_node;
3145*6777b538SAndroid Build Coastguard Worker }
3146*6777b538SAndroid Build Coastguard Worker }
3147*6777b538SAndroid Build Coastguard Worker }
3148*6777b538SAndroid Build Coastguard Worker /*
3149*6777b538SAndroid Build Coastguard Worker * grow the nodeTab if needed
3150*6777b538SAndroid Build Coastguard Worker */
3151*6777b538SAndroid Build Coastguard Worker if (set1->nodeMax == 0) {
3152*6777b538SAndroid Build Coastguard Worker set1->nodeTab = (xmlNodePtr *) xmlMalloc(
3153*6777b538SAndroid Build Coastguard Worker XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
3154*6777b538SAndroid Build Coastguard Worker if (set1->nodeTab == NULL)
3155*6777b538SAndroid Build Coastguard Worker goto error;
3156*6777b538SAndroid Build Coastguard Worker memset(set1->nodeTab, 0,
3157*6777b538SAndroid Build Coastguard Worker XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
3158*6777b538SAndroid Build Coastguard Worker set1->nodeMax = XML_NODESET_DEFAULT;
3159*6777b538SAndroid Build Coastguard Worker } else if (set1->nodeNr >= set1->nodeMax) {
3160*6777b538SAndroid Build Coastguard Worker xmlNodePtr *temp;
3161*6777b538SAndroid Build Coastguard Worker
3162*6777b538SAndroid Build Coastguard Worker if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH)
3163*6777b538SAndroid Build Coastguard Worker goto error;
3164*6777b538SAndroid Build Coastguard Worker temp = (xmlNodePtr *) xmlRealloc(
3165*6777b538SAndroid Build Coastguard Worker set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr));
3166*6777b538SAndroid Build Coastguard Worker if (temp == NULL)
3167*6777b538SAndroid Build Coastguard Worker goto error;
3168*6777b538SAndroid Build Coastguard Worker set1->nodeTab = temp;
3169*6777b538SAndroid Build Coastguard Worker set1->nodeMax *= 2;
3170*6777b538SAndroid Build Coastguard Worker }
3171*6777b538SAndroid Build Coastguard Worker set1->nodeTab[set1->nodeNr++] = n2;
3172*6777b538SAndroid Build Coastguard Worker skip_node:
3173*6777b538SAndroid Build Coastguard Worker set2->nodeTab[i] = NULL;
3174*6777b538SAndroid Build Coastguard Worker }
3175*6777b538SAndroid Build Coastguard Worker }
3176*6777b538SAndroid Build Coastguard Worker set2->nodeNr = 0;
3177*6777b538SAndroid Build Coastguard Worker return(set1);
3178*6777b538SAndroid Build Coastguard Worker
3179*6777b538SAndroid Build Coastguard Worker error:
3180*6777b538SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(set1);
3181*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetClear(set2, 1);
3182*6777b538SAndroid Build Coastguard Worker return(NULL);
3183*6777b538SAndroid Build Coastguard Worker }
3184*6777b538SAndroid Build Coastguard Worker
3185*6777b538SAndroid Build Coastguard Worker /**
3186*6777b538SAndroid Build Coastguard Worker * xmlXPathNodeSetMergeAndClearNoDupls:
3187*6777b538SAndroid Build Coastguard Worker * @set1: the first NodeSet or NULL
3188*6777b538SAndroid Build Coastguard Worker * @set2: the second NodeSet
3189*6777b538SAndroid Build Coastguard Worker *
3190*6777b538SAndroid Build Coastguard Worker * Merges two nodesets, all nodes from @set2 are added to @set1.
3191*6777b538SAndroid Build Coastguard Worker * Doesn't check for duplicate nodes. Clears set2.
3192*6777b538SAndroid Build Coastguard Worker *
3193*6777b538SAndroid Build Coastguard Worker * Returns @set1 once extended or NULL in case of error.
3194*6777b538SAndroid Build Coastguard Worker *
3195*6777b538SAndroid Build Coastguard Worker * Frees @set1 in case of error.
3196*6777b538SAndroid Build Coastguard Worker */
3197*6777b538SAndroid Build Coastguard Worker static xmlNodeSetPtr
xmlXPathNodeSetMergeAndClearNoDupls(xmlNodeSetPtr set1,xmlNodeSetPtr set2)3198*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetMergeAndClearNoDupls(xmlNodeSetPtr set1, xmlNodeSetPtr set2)
3199*6777b538SAndroid Build Coastguard Worker {
3200*6777b538SAndroid Build Coastguard Worker {
3201*6777b538SAndroid Build Coastguard Worker int i;
3202*6777b538SAndroid Build Coastguard Worker xmlNodePtr n2;
3203*6777b538SAndroid Build Coastguard Worker
3204*6777b538SAndroid Build Coastguard Worker for (i = 0;i < set2->nodeNr;i++) {
3205*6777b538SAndroid Build Coastguard Worker n2 = set2->nodeTab[i];
3206*6777b538SAndroid Build Coastguard Worker if (set1->nodeMax == 0) {
3207*6777b538SAndroid Build Coastguard Worker set1->nodeTab = (xmlNodePtr *) xmlMalloc(
3208*6777b538SAndroid Build Coastguard Worker XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
3209*6777b538SAndroid Build Coastguard Worker if (set1->nodeTab == NULL)
3210*6777b538SAndroid Build Coastguard Worker goto error;
3211*6777b538SAndroid Build Coastguard Worker memset(set1->nodeTab, 0,
3212*6777b538SAndroid Build Coastguard Worker XML_NODESET_DEFAULT * sizeof(xmlNodePtr));
3213*6777b538SAndroid Build Coastguard Worker set1->nodeMax = XML_NODESET_DEFAULT;
3214*6777b538SAndroid Build Coastguard Worker } else if (set1->nodeNr >= set1->nodeMax) {
3215*6777b538SAndroid Build Coastguard Worker xmlNodePtr *temp;
3216*6777b538SAndroid Build Coastguard Worker
3217*6777b538SAndroid Build Coastguard Worker if (set1->nodeMax >= XPATH_MAX_NODESET_LENGTH)
3218*6777b538SAndroid Build Coastguard Worker goto error;
3219*6777b538SAndroid Build Coastguard Worker temp = (xmlNodePtr *) xmlRealloc(
3220*6777b538SAndroid Build Coastguard Worker set1->nodeTab, set1->nodeMax * 2 * sizeof(xmlNodePtr));
3221*6777b538SAndroid Build Coastguard Worker if (temp == NULL)
3222*6777b538SAndroid Build Coastguard Worker goto error;
3223*6777b538SAndroid Build Coastguard Worker set1->nodeTab = temp;
3224*6777b538SAndroid Build Coastguard Worker set1->nodeMax *= 2;
3225*6777b538SAndroid Build Coastguard Worker }
3226*6777b538SAndroid Build Coastguard Worker set1->nodeTab[set1->nodeNr++] = n2;
3227*6777b538SAndroid Build Coastguard Worker set2->nodeTab[i] = NULL;
3228*6777b538SAndroid Build Coastguard Worker }
3229*6777b538SAndroid Build Coastguard Worker }
3230*6777b538SAndroid Build Coastguard Worker set2->nodeNr = 0;
3231*6777b538SAndroid Build Coastguard Worker return(set1);
3232*6777b538SAndroid Build Coastguard Worker
3233*6777b538SAndroid Build Coastguard Worker error:
3234*6777b538SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(set1);
3235*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetClear(set2, 1);
3236*6777b538SAndroid Build Coastguard Worker return(NULL);
3237*6777b538SAndroid Build Coastguard Worker }
3238*6777b538SAndroid Build Coastguard Worker
3239*6777b538SAndroid Build Coastguard Worker /**
3240*6777b538SAndroid Build Coastguard Worker * xmlXPathNodeSetDel:
3241*6777b538SAndroid Build Coastguard Worker * @cur: the initial node set
3242*6777b538SAndroid Build Coastguard Worker * @val: an xmlNodePtr
3243*6777b538SAndroid Build Coastguard Worker *
3244*6777b538SAndroid Build Coastguard Worker * Removes an xmlNodePtr from an existing NodeSet
3245*6777b538SAndroid Build Coastguard Worker */
3246*6777b538SAndroid Build Coastguard Worker void
xmlXPathNodeSetDel(xmlNodeSetPtr cur,xmlNodePtr val)3247*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetDel(xmlNodeSetPtr cur, xmlNodePtr val) {
3248*6777b538SAndroid Build Coastguard Worker int i;
3249*6777b538SAndroid Build Coastguard Worker
3250*6777b538SAndroid Build Coastguard Worker if (cur == NULL) return;
3251*6777b538SAndroid Build Coastguard Worker if (val == NULL) return;
3252*6777b538SAndroid Build Coastguard Worker
3253*6777b538SAndroid Build Coastguard Worker /*
3254*6777b538SAndroid Build Coastguard Worker * find node in nodeTab
3255*6777b538SAndroid Build Coastguard Worker */
3256*6777b538SAndroid Build Coastguard Worker for (i = 0;i < cur->nodeNr;i++)
3257*6777b538SAndroid Build Coastguard Worker if (cur->nodeTab[i] == val) break;
3258*6777b538SAndroid Build Coastguard Worker
3259*6777b538SAndroid Build Coastguard Worker if (i >= cur->nodeNr) { /* not found */
3260*6777b538SAndroid Build Coastguard Worker return;
3261*6777b538SAndroid Build Coastguard Worker }
3262*6777b538SAndroid Build Coastguard Worker if ((cur->nodeTab[i] != NULL) &&
3263*6777b538SAndroid Build Coastguard Worker (cur->nodeTab[i]->type == XML_NAMESPACE_DECL))
3264*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetFreeNs((xmlNsPtr) cur->nodeTab[i]);
3265*6777b538SAndroid Build Coastguard Worker cur->nodeNr--;
3266*6777b538SAndroid Build Coastguard Worker for (;i < cur->nodeNr;i++)
3267*6777b538SAndroid Build Coastguard Worker cur->nodeTab[i] = cur->nodeTab[i + 1];
3268*6777b538SAndroid Build Coastguard Worker cur->nodeTab[cur->nodeNr] = NULL;
3269*6777b538SAndroid Build Coastguard Worker }
3270*6777b538SAndroid Build Coastguard Worker
3271*6777b538SAndroid Build Coastguard Worker /**
3272*6777b538SAndroid Build Coastguard Worker * xmlXPathNodeSetRemove:
3273*6777b538SAndroid Build Coastguard Worker * @cur: the initial node set
3274*6777b538SAndroid Build Coastguard Worker * @val: the index to remove
3275*6777b538SAndroid Build Coastguard Worker *
3276*6777b538SAndroid Build Coastguard Worker * Removes an entry from an existing NodeSet list.
3277*6777b538SAndroid Build Coastguard Worker */
3278*6777b538SAndroid Build Coastguard Worker void
xmlXPathNodeSetRemove(xmlNodeSetPtr cur,int val)3279*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetRemove(xmlNodeSetPtr cur, int val) {
3280*6777b538SAndroid Build Coastguard Worker if (cur == NULL) return;
3281*6777b538SAndroid Build Coastguard Worker if (val >= cur->nodeNr) return;
3282*6777b538SAndroid Build Coastguard Worker if ((cur->nodeTab[val] != NULL) &&
3283*6777b538SAndroid Build Coastguard Worker (cur->nodeTab[val]->type == XML_NAMESPACE_DECL))
3284*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetFreeNs((xmlNsPtr) cur->nodeTab[val]);
3285*6777b538SAndroid Build Coastguard Worker cur->nodeNr--;
3286*6777b538SAndroid Build Coastguard Worker for (;val < cur->nodeNr;val++)
3287*6777b538SAndroid Build Coastguard Worker cur->nodeTab[val] = cur->nodeTab[val + 1];
3288*6777b538SAndroid Build Coastguard Worker cur->nodeTab[cur->nodeNr] = NULL;
3289*6777b538SAndroid Build Coastguard Worker }
3290*6777b538SAndroid Build Coastguard Worker
3291*6777b538SAndroid Build Coastguard Worker /**
3292*6777b538SAndroid Build Coastguard Worker * xmlXPathFreeNodeSet:
3293*6777b538SAndroid Build Coastguard Worker * @obj: the xmlNodeSetPtr to free
3294*6777b538SAndroid Build Coastguard Worker *
3295*6777b538SAndroid Build Coastguard Worker * Free the NodeSet compound (not the actual nodes !).
3296*6777b538SAndroid Build Coastguard Worker */
3297*6777b538SAndroid Build Coastguard Worker void
xmlXPathFreeNodeSet(xmlNodeSetPtr obj)3298*6777b538SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(xmlNodeSetPtr obj) {
3299*6777b538SAndroid Build Coastguard Worker if (obj == NULL) return;
3300*6777b538SAndroid Build Coastguard Worker if (obj->nodeTab != NULL) {
3301*6777b538SAndroid Build Coastguard Worker int i;
3302*6777b538SAndroid Build Coastguard Worker
3303*6777b538SAndroid Build Coastguard Worker /* @@ with_ns to check whether namespace nodes should be looked at @@ */
3304*6777b538SAndroid Build Coastguard Worker for (i = 0;i < obj->nodeNr;i++)
3305*6777b538SAndroid Build Coastguard Worker if ((obj->nodeTab[i] != NULL) &&
3306*6777b538SAndroid Build Coastguard Worker (obj->nodeTab[i]->type == XML_NAMESPACE_DECL))
3307*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetFreeNs((xmlNsPtr) obj->nodeTab[i]);
3308*6777b538SAndroid Build Coastguard Worker xmlFree(obj->nodeTab);
3309*6777b538SAndroid Build Coastguard Worker }
3310*6777b538SAndroid Build Coastguard Worker xmlFree(obj);
3311*6777b538SAndroid Build Coastguard Worker }
3312*6777b538SAndroid Build Coastguard Worker
3313*6777b538SAndroid Build Coastguard Worker /**
3314*6777b538SAndroid Build Coastguard Worker * xmlXPathNodeSetClearFromPos:
3315*6777b538SAndroid Build Coastguard Worker * @set: the node set to be cleared
3316*6777b538SAndroid Build Coastguard Worker * @pos: the start position to clear from
3317*6777b538SAndroid Build Coastguard Worker *
3318*6777b538SAndroid Build Coastguard Worker * Clears the list from temporary XPath objects (e.g. namespace nodes
3319*6777b538SAndroid Build Coastguard Worker * are feed) starting with the entry at @pos, but does *not* free the list
3320*6777b538SAndroid Build Coastguard Worker * itself. Sets the length of the list to @pos.
3321*6777b538SAndroid Build Coastguard Worker */
3322*6777b538SAndroid Build Coastguard Worker static void
xmlXPathNodeSetClearFromPos(xmlNodeSetPtr set,int pos,int hasNsNodes)3323*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetClearFromPos(xmlNodeSetPtr set, int pos, int hasNsNodes)
3324*6777b538SAndroid Build Coastguard Worker {
3325*6777b538SAndroid Build Coastguard Worker if ((set == NULL) || (pos >= set->nodeNr))
3326*6777b538SAndroid Build Coastguard Worker return;
3327*6777b538SAndroid Build Coastguard Worker else if ((hasNsNodes)) {
3328*6777b538SAndroid Build Coastguard Worker int i;
3329*6777b538SAndroid Build Coastguard Worker xmlNodePtr node;
3330*6777b538SAndroid Build Coastguard Worker
3331*6777b538SAndroid Build Coastguard Worker for (i = pos; i < set->nodeNr; i++) {
3332*6777b538SAndroid Build Coastguard Worker node = set->nodeTab[i];
3333*6777b538SAndroid Build Coastguard Worker if ((node != NULL) &&
3334*6777b538SAndroid Build Coastguard Worker (node->type == XML_NAMESPACE_DECL))
3335*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetFreeNs((xmlNsPtr) node);
3336*6777b538SAndroid Build Coastguard Worker }
3337*6777b538SAndroid Build Coastguard Worker }
3338*6777b538SAndroid Build Coastguard Worker set->nodeNr = pos;
3339*6777b538SAndroid Build Coastguard Worker }
3340*6777b538SAndroid Build Coastguard Worker
3341*6777b538SAndroid Build Coastguard Worker /**
3342*6777b538SAndroid Build Coastguard Worker * xmlXPathNodeSetClear:
3343*6777b538SAndroid Build Coastguard Worker * @set: the node set to clear
3344*6777b538SAndroid Build Coastguard Worker *
3345*6777b538SAndroid Build Coastguard Worker * Clears the list from all temporary XPath objects (e.g. namespace nodes
3346*6777b538SAndroid Build Coastguard Worker * are feed), but does *not* free the list itself. Sets the length of the
3347*6777b538SAndroid Build Coastguard Worker * list to 0.
3348*6777b538SAndroid Build Coastguard Worker */
3349*6777b538SAndroid Build Coastguard Worker static void
xmlXPathNodeSetClear(xmlNodeSetPtr set,int hasNsNodes)3350*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetClear(xmlNodeSetPtr set, int hasNsNodes)
3351*6777b538SAndroid Build Coastguard Worker {
3352*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetClearFromPos(set, 0, hasNsNodes);
3353*6777b538SAndroid Build Coastguard Worker }
3354*6777b538SAndroid Build Coastguard Worker
3355*6777b538SAndroid Build Coastguard Worker /**
3356*6777b538SAndroid Build Coastguard Worker * xmlXPathNodeSetKeepLast:
3357*6777b538SAndroid Build Coastguard Worker * @set: the node set to be cleared
3358*6777b538SAndroid Build Coastguard Worker *
3359*6777b538SAndroid Build Coastguard Worker * Move the last node to the first position and clear temporary XPath objects
3360*6777b538SAndroid Build Coastguard Worker * (e.g. namespace nodes) from all other nodes. Sets the length of the list
3361*6777b538SAndroid Build Coastguard Worker * to 1.
3362*6777b538SAndroid Build Coastguard Worker */
3363*6777b538SAndroid Build Coastguard Worker static void
xmlXPathNodeSetKeepLast(xmlNodeSetPtr set)3364*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetKeepLast(xmlNodeSetPtr set)
3365*6777b538SAndroid Build Coastguard Worker {
3366*6777b538SAndroid Build Coastguard Worker int i;
3367*6777b538SAndroid Build Coastguard Worker xmlNodePtr node;
3368*6777b538SAndroid Build Coastguard Worker
3369*6777b538SAndroid Build Coastguard Worker if ((set == NULL) || (set->nodeNr <= 1))
3370*6777b538SAndroid Build Coastguard Worker return;
3371*6777b538SAndroid Build Coastguard Worker for (i = 0; i < set->nodeNr - 1; i++) {
3372*6777b538SAndroid Build Coastguard Worker node = set->nodeTab[i];
3373*6777b538SAndroid Build Coastguard Worker if ((node != NULL) &&
3374*6777b538SAndroid Build Coastguard Worker (node->type == XML_NAMESPACE_DECL))
3375*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetFreeNs((xmlNsPtr) node);
3376*6777b538SAndroid Build Coastguard Worker }
3377*6777b538SAndroid Build Coastguard Worker set->nodeTab[0] = set->nodeTab[set->nodeNr-1];
3378*6777b538SAndroid Build Coastguard Worker set->nodeNr = 1;
3379*6777b538SAndroid Build Coastguard Worker }
3380*6777b538SAndroid Build Coastguard Worker
3381*6777b538SAndroid Build Coastguard Worker /**
3382*6777b538SAndroid Build Coastguard Worker * xmlXPathNewNodeSet:
3383*6777b538SAndroid Build Coastguard Worker * @val: the NodePtr value
3384*6777b538SAndroid Build Coastguard Worker *
3385*6777b538SAndroid Build Coastguard Worker * Create a new xmlXPathObjectPtr of type NodeSet and initialize
3386*6777b538SAndroid Build Coastguard Worker * it with the single Node @val
3387*6777b538SAndroid Build Coastguard Worker *
3388*6777b538SAndroid Build Coastguard Worker * Returns the newly created object.
3389*6777b538SAndroid Build Coastguard Worker */
3390*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathNewNodeSet(xmlNodePtr val)3391*6777b538SAndroid Build Coastguard Worker xmlXPathNewNodeSet(xmlNodePtr val) {
3392*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
3393*6777b538SAndroid Build Coastguard Worker
3394*6777b538SAndroid Build Coastguard Worker ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
3395*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
3396*6777b538SAndroid Build Coastguard Worker return(NULL);
3397*6777b538SAndroid Build Coastguard Worker memset(ret, 0 , sizeof(xmlXPathObject));
3398*6777b538SAndroid Build Coastguard Worker ret->type = XPATH_NODESET;
3399*6777b538SAndroid Build Coastguard Worker ret->boolval = 0;
3400*6777b538SAndroid Build Coastguard Worker ret->nodesetval = xmlXPathNodeSetCreate(val);
3401*6777b538SAndroid Build Coastguard Worker if (ret->nodesetval == NULL) {
3402*6777b538SAndroid Build Coastguard Worker xmlFree(ret);
3403*6777b538SAndroid Build Coastguard Worker return(NULL);
3404*6777b538SAndroid Build Coastguard Worker }
3405*6777b538SAndroid Build Coastguard Worker /* @@ with_ns to check whether namespace nodes should be looked at @@ */
3406*6777b538SAndroid Build Coastguard Worker return(ret);
3407*6777b538SAndroid Build Coastguard Worker }
3408*6777b538SAndroid Build Coastguard Worker
3409*6777b538SAndroid Build Coastguard Worker /**
3410*6777b538SAndroid Build Coastguard Worker * xmlXPathNewValueTree:
3411*6777b538SAndroid Build Coastguard Worker * @val: the NodePtr value
3412*6777b538SAndroid Build Coastguard Worker *
3413*6777b538SAndroid Build Coastguard Worker * Create a new xmlXPathObjectPtr of type Value Tree (XSLT) and initialize
3414*6777b538SAndroid Build Coastguard Worker * it with the tree root @val
3415*6777b538SAndroid Build Coastguard Worker *
3416*6777b538SAndroid Build Coastguard Worker * Returns the newly created object.
3417*6777b538SAndroid Build Coastguard Worker */
3418*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathNewValueTree(xmlNodePtr val)3419*6777b538SAndroid Build Coastguard Worker xmlXPathNewValueTree(xmlNodePtr val) {
3420*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
3421*6777b538SAndroid Build Coastguard Worker
3422*6777b538SAndroid Build Coastguard Worker ret = xmlXPathNewNodeSet(val);
3423*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
3424*6777b538SAndroid Build Coastguard Worker return(NULL);
3425*6777b538SAndroid Build Coastguard Worker ret->type = XPATH_XSLT_TREE;
3426*6777b538SAndroid Build Coastguard Worker
3427*6777b538SAndroid Build Coastguard Worker return(ret);
3428*6777b538SAndroid Build Coastguard Worker }
3429*6777b538SAndroid Build Coastguard Worker
3430*6777b538SAndroid Build Coastguard Worker /**
3431*6777b538SAndroid Build Coastguard Worker * xmlXPathNewNodeSetList:
3432*6777b538SAndroid Build Coastguard Worker * @val: an existing NodeSet
3433*6777b538SAndroid Build Coastguard Worker *
3434*6777b538SAndroid Build Coastguard Worker * Create a new xmlXPathObjectPtr of type NodeSet and initialize
3435*6777b538SAndroid Build Coastguard Worker * it with the Nodeset @val
3436*6777b538SAndroid Build Coastguard Worker *
3437*6777b538SAndroid Build Coastguard Worker * Returns the newly created object.
3438*6777b538SAndroid Build Coastguard Worker */
3439*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathNewNodeSetList(xmlNodeSetPtr val)3440*6777b538SAndroid Build Coastguard Worker xmlXPathNewNodeSetList(xmlNodeSetPtr val)
3441*6777b538SAndroid Build Coastguard Worker {
3442*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
3443*6777b538SAndroid Build Coastguard Worker
3444*6777b538SAndroid Build Coastguard Worker if (val == NULL)
3445*6777b538SAndroid Build Coastguard Worker ret = NULL;
3446*6777b538SAndroid Build Coastguard Worker else if (val->nodeTab == NULL)
3447*6777b538SAndroid Build Coastguard Worker ret = xmlXPathNewNodeSet(NULL);
3448*6777b538SAndroid Build Coastguard Worker else {
3449*6777b538SAndroid Build Coastguard Worker ret = xmlXPathNewNodeSet(val->nodeTab[0]);
3450*6777b538SAndroid Build Coastguard Worker if (ret) {
3451*6777b538SAndroid Build Coastguard Worker ret->nodesetval = xmlXPathNodeSetMerge(NULL, val);
3452*6777b538SAndroid Build Coastguard Worker if (ret->nodesetval == NULL) {
3453*6777b538SAndroid Build Coastguard Worker xmlFree(ret);
3454*6777b538SAndroid Build Coastguard Worker return(NULL);
3455*6777b538SAndroid Build Coastguard Worker }
3456*6777b538SAndroid Build Coastguard Worker }
3457*6777b538SAndroid Build Coastguard Worker }
3458*6777b538SAndroid Build Coastguard Worker
3459*6777b538SAndroid Build Coastguard Worker return (ret);
3460*6777b538SAndroid Build Coastguard Worker }
3461*6777b538SAndroid Build Coastguard Worker
3462*6777b538SAndroid Build Coastguard Worker /**
3463*6777b538SAndroid Build Coastguard Worker * xmlXPathWrapNodeSet:
3464*6777b538SAndroid Build Coastguard Worker * @val: the NodePtr value
3465*6777b538SAndroid Build Coastguard Worker *
3466*6777b538SAndroid Build Coastguard Worker * Wrap the Nodeset @val in a new xmlXPathObjectPtr
3467*6777b538SAndroid Build Coastguard Worker *
3468*6777b538SAndroid Build Coastguard Worker * Returns the newly created object.
3469*6777b538SAndroid Build Coastguard Worker *
3470*6777b538SAndroid Build Coastguard Worker * In case of error the node set is destroyed and NULL is returned.
3471*6777b538SAndroid Build Coastguard Worker */
3472*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathWrapNodeSet(xmlNodeSetPtr val)3473*6777b538SAndroid Build Coastguard Worker xmlXPathWrapNodeSet(xmlNodeSetPtr val) {
3474*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
3475*6777b538SAndroid Build Coastguard Worker
3476*6777b538SAndroid Build Coastguard Worker ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
3477*6777b538SAndroid Build Coastguard Worker if (ret == NULL) {
3478*6777b538SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(val);
3479*6777b538SAndroid Build Coastguard Worker return(NULL);
3480*6777b538SAndroid Build Coastguard Worker }
3481*6777b538SAndroid Build Coastguard Worker memset(ret, 0 , sizeof(xmlXPathObject));
3482*6777b538SAndroid Build Coastguard Worker ret->type = XPATH_NODESET;
3483*6777b538SAndroid Build Coastguard Worker ret->nodesetval = val;
3484*6777b538SAndroid Build Coastguard Worker return(ret);
3485*6777b538SAndroid Build Coastguard Worker }
3486*6777b538SAndroid Build Coastguard Worker
3487*6777b538SAndroid Build Coastguard Worker /**
3488*6777b538SAndroid Build Coastguard Worker * xmlXPathFreeNodeSetList:
3489*6777b538SAndroid Build Coastguard Worker * @obj: an existing NodeSetList object
3490*6777b538SAndroid Build Coastguard Worker *
3491*6777b538SAndroid Build Coastguard Worker * Free up the xmlXPathObjectPtr @obj but don't deallocate the objects in
3492*6777b538SAndroid Build Coastguard Worker * the list contrary to xmlXPathFreeObject().
3493*6777b538SAndroid Build Coastguard Worker */
3494*6777b538SAndroid Build Coastguard Worker void
xmlXPathFreeNodeSetList(xmlXPathObjectPtr obj)3495*6777b538SAndroid Build Coastguard Worker xmlXPathFreeNodeSetList(xmlXPathObjectPtr obj) {
3496*6777b538SAndroid Build Coastguard Worker if (obj == NULL) return;
3497*6777b538SAndroid Build Coastguard Worker xmlFree(obj);
3498*6777b538SAndroid Build Coastguard Worker }
3499*6777b538SAndroid Build Coastguard Worker
3500*6777b538SAndroid Build Coastguard Worker /**
3501*6777b538SAndroid Build Coastguard Worker * xmlXPathDifference:
3502*6777b538SAndroid Build Coastguard Worker * @nodes1: a node-set
3503*6777b538SAndroid Build Coastguard Worker * @nodes2: a node-set
3504*6777b538SAndroid Build Coastguard Worker *
3505*6777b538SAndroid Build Coastguard Worker * Implements the EXSLT - Sets difference() function:
3506*6777b538SAndroid Build Coastguard Worker * node-set set:difference (node-set, node-set)
3507*6777b538SAndroid Build Coastguard Worker *
3508*6777b538SAndroid Build Coastguard Worker * Returns the difference between the two node sets, or nodes1 if
3509*6777b538SAndroid Build Coastguard Worker * nodes2 is empty
3510*6777b538SAndroid Build Coastguard Worker */
3511*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathDifference(xmlNodeSetPtr nodes1,xmlNodeSetPtr nodes2)3512*6777b538SAndroid Build Coastguard Worker xmlXPathDifference (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
3513*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr ret;
3514*6777b538SAndroid Build Coastguard Worker int i, l1;
3515*6777b538SAndroid Build Coastguard Worker xmlNodePtr cur;
3516*6777b538SAndroid Build Coastguard Worker
3517*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes2))
3518*6777b538SAndroid Build Coastguard Worker return(nodes1);
3519*6777b538SAndroid Build Coastguard Worker
3520*6777b538SAndroid Build Coastguard Worker ret = xmlXPathNodeSetCreate(NULL);
3521*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
3522*6777b538SAndroid Build Coastguard Worker return(NULL);
3523*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes1))
3524*6777b538SAndroid Build Coastguard Worker return(ret);
3525*6777b538SAndroid Build Coastguard Worker
3526*6777b538SAndroid Build Coastguard Worker l1 = xmlXPathNodeSetGetLength(nodes1);
3527*6777b538SAndroid Build Coastguard Worker
3528*6777b538SAndroid Build Coastguard Worker for (i = 0; i < l1; i++) {
3529*6777b538SAndroid Build Coastguard Worker cur = xmlXPathNodeSetItem(nodes1, i);
3530*6777b538SAndroid Build Coastguard Worker if (!xmlXPathNodeSetContains(nodes2, cur)) {
3531*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetAddUnique(ret, cur) < 0) {
3532*6777b538SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(ret);
3533*6777b538SAndroid Build Coastguard Worker return(NULL);
3534*6777b538SAndroid Build Coastguard Worker }
3535*6777b538SAndroid Build Coastguard Worker }
3536*6777b538SAndroid Build Coastguard Worker }
3537*6777b538SAndroid Build Coastguard Worker return(ret);
3538*6777b538SAndroid Build Coastguard Worker }
3539*6777b538SAndroid Build Coastguard Worker
3540*6777b538SAndroid Build Coastguard Worker /**
3541*6777b538SAndroid Build Coastguard Worker * xmlXPathIntersection:
3542*6777b538SAndroid Build Coastguard Worker * @nodes1: a node-set
3543*6777b538SAndroid Build Coastguard Worker * @nodes2: a node-set
3544*6777b538SAndroid Build Coastguard Worker *
3545*6777b538SAndroid Build Coastguard Worker * Implements the EXSLT - Sets intersection() function:
3546*6777b538SAndroid Build Coastguard Worker * node-set set:intersection (node-set, node-set)
3547*6777b538SAndroid Build Coastguard Worker *
3548*6777b538SAndroid Build Coastguard Worker * Returns a node set comprising the nodes that are within both the
3549*6777b538SAndroid Build Coastguard Worker * node sets passed as arguments
3550*6777b538SAndroid Build Coastguard Worker */
3551*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathIntersection(xmlNodeSetPtr nodes1,xmlNodeSetPtr nodes2)3552*6777b538SAndroid Build Coastguard Worker xmlXPathIntersection (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
3553*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr ret = xmlXPathNodeSetCreate(NULL);
3554*6777b538SAndroid Build Coastguard Worker int i, l1;
3555*6777b538SAndroid Build Coastguard Worker xmlNodePtr cur;
3556*6777b538SAndroid Build Coastguard Worker
3557*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
3558*6777b538SAndroid Build Coastguard Worker return(ret);
3559*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes1))
3560*6777b538SAndroid Build Coastguard Worker return(ret);
3561*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes2))
3562*6777b538SAndroid Build Coastguard Worker return(ret);
3563*6777b538SAndroid Build Coastguard Worker
3564*6777b538SAndroid Build Coastguard Worker l1 = xmlXPathNodeSetGetLength(nodes1);
3565*6777b538SAndroid Build Coastguard Worker
3566*6777b538SAndroid Build Coastguard Worker for (i = 0; i < l1; i++) {
3567*6777b538SAndroid Build Coastguard Worker cur = xmlXPathNodeSetItem(nodes1, i);
3568*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetContains(nodes2, cur)) {
3569*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetAddUnique(ret, cur) < 0) {
3570*6777b538SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(ret);
3571*6777b538SAndroid Build Coastguard Worker return(NULL);
3572*6777b538SAndroid Build Coastguard Worker }
3573*6777b538SAndroid Build Coastguard Worker }
3574*6777b538SAndroid Build Coastguard Worker }
3575*6777b538SAndroid Build Coastguard Worker return(ret);
3576*6777b538SAndroid Build Coastguard Worker }
3577*6777b538SAndroid Build Coastguard Worker
3578*6777b538SAndroid Build Coastguard Worker /**
3579*6777b538SAndroid Build Coastguard Worker * xmlXPathDistinctSorted:
3580*6777b538SAndroid Build Coastguard Worker * @nodes: a node-set, sorted by document order
3581*6777b538SAndroid Build Coastguard Worker *
3582*6777b538SAndroid Build Coastguard Worker * Implements the EXSLT - Sets distinct() function:
3583*6777b538SAndroid Build Coastguard Worker * node-set set:distinct (node-set)
3584*6777b538SAndroid Build Coastguard Worker *
3585*6777b538SAndroid Build Coastguard Worker * Returns a subset of the nodes contained in @nodes, or @nodes if
3586*6777b538SAndroid Build Coastguard Worker * it is empty
3587*6777b538SAndroid Build Coastguard Worker */
3588*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathDistinctSorted(xmlNodeSetPtr nodes)3589*6777b538SAndroid Build Coastguard Worker xmlXPathDistinctSorted (xmlNodeSetPtr nodes) {
3590*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr ret;
3591*6777b538SAndroid Build Coastguard Worker xmlHashTablePtr hash;
3592*6777b538SAndroid Build Coastguard Worker int i, l;
3593*6777b538SAndroid Build Coastguard Worker xmlChar * strval;
3594*6777b538SAndroid Build Coastguard Worker xmlNodePtr cur;
3595*6777b538SAndroid Build Coastguard Worker
3596*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes))
3597*6777b538SAndroid Build Coastguard Worker return(nodes);
3598*6777b538SAndroid Build Coastguard Worker
3599*6777b538SAndroid Build Coastguard Worker ret = xmlXPathNodeSetCreate(NULL);
3600*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
3601*6777b538SAndroid Build Coastguard Worker return(ret);
3602*6777b538SAndroid Build Coastguard Worker l = xmlXPathNodeSetGetLength(nodes);
3603*6777b538SAndroid Build Coastguard Worker hash = xmlHashCreate (l);
3604*6777b538SAndroid Build Coastguard Worker for (i = 0; i < l; i++) {
3605*6777b538SAndroid Build Coastguard Worker cur = xmlXPathNodeSetItem(nodes, i);
3606*6777b538SAndroid Build Coastguard Worker strval = xmlXPathCastNodeToString(cur);
3607*6777b538SAndroid Build Coastguard Worker if (xmlHashLookup(hash, strval) == NULL) {
3608*6777b538SAndroid Build Coastguard Worker if (xmlHashAddEntry(hash, strval, strval) < 0) {
3609*6777b538SAndroid Build Coastguard Worker xmlFree(strval);
3610*6777b538SAndroid Build Coastguard Worker goto error;
3611*6777b538SAndroid Build Coastguard Worker }
3612*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetAddUnique(ret, cur) < 0)
3613*6777b538SAndroid Build Coastguard Worker goto error;
3614*6777b538SAndroid Build Coastguard Worker } else {
3615*6777b538SAndroid Build Coastguard Worker xmlFree(strval);
3616*6777b538SAndroid Build Coastguard Worker }
3617*6777b538SAndroid Build Coastguard Worker }
3618*6777b538SAndroid Build Coastguard Worker xmlHashFree(hash, xmlHashDefaultDeallocator);
3619*6777b538SAndroid Build Coastguard Worker return(ret);
3620*6777b538SAndroid Build Coastguard Worker
3621*6777b538SAndroid Build Coastguard Worker error:
3622*6777b538SAndroid Build Coastguard Worker xmlHashFree(hash, xmlHashDefaultDeallocator);
3623*6777b538SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(ret);
3624*6777b538SAndroid Build Coastguard Worker return(NULL);
3625*6777b538SAndroid Build Coastguard Worker }
3626*6777b538SAndroid Build Coastguard Worker
3627*6777b538SAndroid Build Coastguard Worker /**
3628*6777b538SAndroid Build Coastguard Worker * xmlXPathDistinct:
3629*6777b538SAndroid Build Coastguard Worker * @nodes: a node-set
3630*6777b538SAndroid Build Coastguard Worker *
3631*6777b538SAndroid Build Coastguard Worker * Implements the EXSLT - Sets distinct() function:
3632*6777b538SAndroid Build Coastguard Worker * node-set set:distinct (node-set)
3633*6777b538SAndroid Build Coastguard Worker * @nodes is sorted by document order, then #exslSetsDistinctSorted
3634*6777b538SAndroid Build Coastguard Worker * is called with the sorted node-set
3635*6777b538SAndroid Build Coastguard Worker *
3636*6777b538SAndroid Build Coastguard Worker * Returns a subset of the nodes contained in @nodes, or @nodes if
3637*6777b538SAndroid Build Coastguard Worker * it is empty
3638*6777b538SAndroid Build Coastguard Worker */
3639*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathDistinct(xmlNodeSetPtr nodes)3640*6777b538SAndroid Build Coastguard Worker xmlXPathDistinct (xmlNodeSetPtr nodes) {
3641*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes))
3642*6777b538SAndroid Build Coastguard Worker return(nodes);
3643*6777b538SAndroid Build Coastguard Worker
3644*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetSort(nodes);
3645*6777b538SAndroid Build Coastguard Worker return(xmlXPathDistinctSorted(nodes));
3646*6777b538SAndroid Build Coastguard Worker }
3647*6777b538SAndroid Build Coastguard Worker
3648*6777b538SAndroid Build Coastguard Worker /**
3649*6777b538SAndroid Build Coastguard Worker * xmlXPathHasSameNodes:
3650*6777b538SAndroid Build Coastguard Worker * @nodes1: a node-set
3651*6777b538SAndroid Build Coastguard Worker * @nodes2: a node-set
3652*6777b538SAndroid Build Coastguard Worker *
3653*6777b538SAndroid Build Coastguard Worker * Implements the EXSLT - Sets has-same-nodes function:
3654*6777b538SAndroid Build Coastguard Worker * boolean set:has-same-node(node-set, node-set)
3655*6777b538SAndroid Build Coastguard Worker *
3656*6777b538SAndroid Build Coastguard Worker * Returns true (1) if @nodes1 shares any node with @nodes2, false (0)
3657*6777b538SAndroid Build Coastguard Worker * otherwise
3658*6777b538SAndroid Build Coastguard Worker */
3659*6777b538SAndroid Build Coastguard Worker int
xmlXPathHasSameNodes(xmlNodeSetPtr nodes1,xmlNodeSetPtr nodes2)3660*6777b538SAndroid Build Coastguard Worker xmlXPathHasSameNodes (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
3661*6777b538SAndroid Build Coastguard Worker int i, l;
3662*6777b538SAndroid Build Coastguard Worker xmlNodePtr cur;
3663*6777b538SAndroid Build Coastguard Worker
3664*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes1) ||
3665*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetIsEmpty(nodes2))
3666*6777b538SAndroid Build Coastguard Worker return(0);
3667*6777b538SAndroid Build Coastguard Worker
3668*6777b538SAndroid Build Coastguard Worker l = xmlXPathNodeSetGetLength(nodes1);
3669*6777b538SAndroid Build Coastguard Worker for (i = 0; i < l; i++) {
3670*6777b538SAndroid Build Coastguard Worker cur = xmlXPathNodeSetItem(nodes1, i);
3671*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetContains(nodes2, cur))
3672*6777b538SAndroid Build Coastguard Worker return(1);
3673*6777b538SAndroid Build Coastguard Worker }
3674*6777b538SAndroid Build Coastguard Worker return(0);
3675*6777b538SAndroid Build Coastguard Worker }
3676*6777b538SAndroid Build Coastguard Worker
3677*6777b538SAndroid Build Coastguard Worker /**
3678*6777b538SAndroid Build Coastguard Worker * xmlXPathNodeLeadingSorted:
3679*6777b538SAndroid Build Coastguard Worker * @nodes: a node-set, sorted by document order
3680*6777b538SAndroid Build Coastguard Worker * @node: a node
3681*6777b538SAndroid Build Coastguard Worker *
3682*6777b538SAndroid Build Coastguard Worker * Implements the EXSLT - Sets leading() function:
3683*6777b538SAndroid Build Coastguard Worker * node-set set:leading (node-set, node-set)
3684*6777b538SAndroid Build Coastguard Worker *
3685*6777b538SAndroid Build Coastguard Worker * Returns the nodes in @nodes that precede @node in document order,
3686*6777b538SAndroid Build Coastguard Worker * @nodes if @node is NULL or an empty node-set if @nodes
3687*6777b538SAndroid Build Coastguard Worker * doesn't contain @node
3688*6777b538SAndroid Build Coastguard Worker */
3689*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathNodeLeadingSorted(xmlNodeSetPtr nodes,xmlNodePtr node)3690*6777b538SAndroid Build Coastguard Worker xmlXPathNodeLeadingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) {
3691*6777b538SAndroid Build Coastguard Worker int i, l;
3692*6777b538SAndroid Build Coastguard Worker xmlNodePtr cur;
3693*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr ret;
3694*6777b538SAndroid Build Coastguard Worker
3695*6777b538SAndroid Build Coastguard Worker if (node == NULL)
3696*6777b538SAndroid Build Coastguard Worker return(nodes);
3697*6777b538SAndroid Build Coastguard Worker
3698*6777b538SAndroid Build Coastguard Worker ret = xmlXPathNodeSetCreate(NULL);
3699*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
3700*6777b538SAndroid Build Coastguard Worker return(ret);
3701*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes) ||
3702*6777b538SAndroid Build Coastguard Worker (!xmlXPathNodeSetContains(nodes, node)))
3703*6777b538SAndroid Build Coastguard Worker return(ret);
3704*6777b538SAndroid Build Coastguard Worker
3705*6777b538SAndroid Build Coastguard Worker l = xmlXPathNodeSetGetLength(nodes);
3706*6777b538SAndroid Build Coastguard Worker for (i = 0; i < l; i++) {
3707*6777b538SAndroid Build Coastguard Worker cur = xmlXPathNodeSetItem(nodes, i);
3708*6777b538SAndroid Build Coastguard Worker if (cur == node)
3709*6777b538SAndroid Build Coastguard Worker break;
3710*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetAddUnique(ret, cur) < 0) {
3711*6777b538SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(ret);
3712*6777b538SAndroid Build Coastguard Worker return(NULL);
3713*6777b538SAndroid Build Coastguard Worker }
3714*6777b538SAndroid Build Coastguard Worker }
3715*6777b538SAndroid Build Coastguard Worker return(ret);
3716*6777b538SAndroid Build Coastguard Worker }
3717*6777b538SAndroid Build Coastguard Worker
3718*6777b538SAndroid Build Coastguard Worker /**
3719*6777b538SAndroid Build Coastguard Worker * xmlXPathNodeLeading:
3720*6777b538SAndroid Build Coastguard Worker * @nodes: a node-set
3721*6777b538SAndroid Build Coastguard Worker * @node: a node
3722*6777b538SAndroid Build Coastguard Worker *
3723*6777b538SAndroid Build Coastguard Worker * Implements the EXSLT - Sets leading() function:
3724*6777b538SAndroid Build Coastguard Worker * node-set set:leading (node-set, node-set)
3725*6777b538SAndroid Build Coastguard Worker * @nodes is sorted by document order, then #exslSetsNodeLeadingSorted
3726*6777b538SAndroid Build Coastguard Worker * is called.
3727*6777b538SAndroid Build Coastguard Worker *
3728*6777b538SAndroid Build Coastguard Worker * Returns the nodes in @nodes that precede @node in document order,
3729*6777b538SAndroid Build Coastguard Worker * @nodes if @node is NULL or an empty node-set if @nodes
3730*6777b538SAndroid Build Coastguard Worker * doesn't contain @node
3731*6777b538SAndroid Build Coastguard Worker */
3732*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathNodeLeading(xmlNodeSetPtr nodes,xmlNodePtr node)3733*6777b538SAndroid Build Coastguard Worker xmlXPathNodeLeading (xmlNodeSetPtr nodes, xmlNodePtr node) {
3734*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetSort(nodes);
3735*6777b538SAndroid Build Coastguard Worker return(xmlXPathNodeLeadingSorted(nodes, node));
3736*6777b538SAndroid Build Coastguard Worker }
3737*6777b538SAndroid Build Coastguard Worker
3738*6777b538SAndroid Build Coastguard Worker /**
3739*6777b538SAndroid Build Coastguard Worker * xmlXPathLeadingSorted:
3740*6777b538SAndroid Build Coastguard Worker * @nodes1: a node-set, sorted by document order
3741*6777b538SAndroid Build Coastguard Worker * @nodes2: a node-set, sorted by document order
3742*6777b538SAndroid Build Coastguard Worker *
3743*6777b538SAndroid Build Coastguard Worker * Implements the EXSLT - Sets leading() function:
3744*6777b538SAndroid Build Coastguard Worker * node-set set:leading (node-set, node-set)
3745*6777b538SAndroid Build Coastguard Worker *
3746*6777b538SAndroid Build Coastguard Worker * Returns the nodes in @nodes1 that precede the first node in @nodes2
3747*6777b538SAndroid Build Coastguard Worker * in document order, @nodes1 if @nodes2 is NULL or empty or
3748*6777b538SAndroid Build Coastguard Worker * an empty node-set if @nodes1 doesn't contain @nodes2
3749*6777b538SAndroid Build Coastguard Worker */
3750*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathLeadingSorted(xmlNodeSetPtr nodes1,xmlNodeSetPtr nodes2)3751*6777b538SAndroid Build Coastguard Worker xmlXPathLeadingSorted (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
3752*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes2))
3753*6777b538SAndroid Build Coastguard Worker return(nodes1);
3754*6777b538SAndroid Build Coastguard Worker return(xmlXPathNodeLeadingSorted(nodes1,
3755*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetItem(nodes2, 1)));
3756*6777b538SAndroid Build Coastguard Worker }
3757*6777b538SAndroid Build Coastguard Worker
3758*6777b538SAndroid Build Coastguard Worker /**
3759*6777b538SAndroid Build Coastguard Worker * xmlXPathLeading:
3760*6777b538SAndroid Build Coastguard Worker * @nodes1: a node-set
3761*6777b538SAndroid Build Coastguard Worker * @nodes2: a node-set
3762*6777b538SAndroid Build Coastguard Worker *
3763*6777b538SAndroid Build Coastguard Worker * Implements the EXSLT - Sets leading() function:
3764*6777b538SAndroid Build Coastguard Worker * node-set set:leading (node-set, node-set)
3765*6777b538SAndroid Build Coastguard Worker * @nodes1 and @nodes2 are sorted by document order, then
3766*6777b538SAndroid Build Coastguard Worker * #exslSetsLeadingSorted is called.
3767*6777b538SAndroid Build Coastguard Worker *
3768*6777b538SAndroid Build Coastguard Worker * Returns the nodes in @nodes1 that precede the first node in @nodes2
3769*6777b538SAndroid Build Coastguard Worker * in document order, @nodes1 if @nodes2 is NULL or empty or
3770*6777b538SAndroid Build Coastguard Worker * an empty node-set if @nodes1 doesn't contain @nodes2
3771*6777b538SAndroid Build Coastguard Worker */
3772*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathLeading(xmlNodeSetPtr nodes1,xmlNodeSetPtr nodes2)3773*6777b538SAndroid Build Coastguard Worker xmlXPathLeading (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
3774*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes2))
3775*6777b538SAndroid Build Coastguard Worker return(nodes1);
3776*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes1))
3777*6777b538SAndroid Build Coastguard Worker return(xmlXPathNodeSetCreate(NULL));
3778*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetSort(nodes1);
3779*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetSort(nodes2);
3780*6777b538SAndroid Build Coastguard Worker return(xmlXPathNodeLeadingSorted(nodes1,
3781*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetItem(nodes2, 1)));
3782*6777b538SAndroid Build Coastguard Worker }
3783*6777b538SAndroid Build Coastguard Worker
3784*6777b538SAndroid Build Coastguard Worker /**
3785*6777b538SAndroid Build Coastguard Worker * xmlXPathNodeTrailingSorted:
3786*6777b538SAndroid Build Coastguard Worker * @nodes: a node-set, sorted by document order
3787*6777b538SAndroid Build Coastguard Worker * @node: a node
3788*6777b538SAndroid Build Coastguard Worker *
3789*6777b538SAndroid Build Coastguard Worker * Implements the EXSLT - Sets trailing() function:
3790*6777b538SAndroid Build Coastguard Worker * node-set set:trailing (node-set, node-set)
3791*6777b538SAndroid Build Coastguard Worker *
3792*6777b538SAndroid Build Coastguard Worker * Returns the nodes in @nodes that follow @node in document order,
3793*6777b538SAndroid Build Coastguard Worker * @nodes if @node is NULL or an empty node-set if @nodes
3794*6777b538SAndroid Build Coastguard Worker * doesn't contain @node
3795*6777b538SAndroid Build Coastguard Worker */
3796*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathNodeTrailingSorted(xmlNodeSetPtr nodes,xmlNodePtr node)3797*6777b538SAndroid Build Coastguard Worker xmlXPathNodeTrailingSorted (xmlNodeSetPtr nodes, xmlNodePtr node) {
3798*6777b538SAndroid Build Coastguard Worker int i, l;
3799*6777b538SAndroid Build Coastguard Worker xmlNodePtr cur;
3800*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr ret;
3801*6777b538SAndroid Build Coastguard Worker
3802*6777b538SAndroid Build Coastguard Worker if (node == NULL)
3803*6777b538SAndroid Build Coastguard Worker return(nodes);
3804*6777b538SAndroid Build Coastguard Worker
3805*6777b538SAndroid Build Coastguard Worker ret = xmlXPathNodeSetCreate(NULL);
3806*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
3807*6777b538SAndroid Build Coastguard Worker return(ret);
3808*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes) ||
3809*6777b538SAndroid Build Coastguard Worker (!xmlXPathNodeSetContains(nodes, node)))
3810*6777b538SAndroid Build Coastguard Worker return(ret);
3811*6777b538SAndroid Build Coastguard Worker
3812*6777b538SAndroid Build Coastguard Worker l = xmlXPathNodeSetGetLength(nodes);
3813*6777b538SAndroid Build Coastguard Worker for (i = l - 1; i >= 0; i--) {
3814*6777b538SAndroid Build Coastguard Worker cur = xmlXPathNodeSetItem(nodes, i);
3815*6777b538SAndroid Build Coastguard Worker if (cur == node)
3816*6777b538SAndroid Build Coastguard Worker break;
3817*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetAddUnique(ret, cur) < 0) {
3818*6777b538SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(ret);
3819*6777b538SAndroid Build Coastguard Worker return(NULL);
3820*6777b538SAndroid Build Coastguard Worker }
3821*6777b538SAndroid Build Coastguard Worker }
3822*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetSort(ret); /* bug 413451 */
3823*6777b538SAndroid Build Coastguard Worker return(ret);
3824*6777b538SAndroid Build Coastguard Worker }
3825*6777b538SAndroid Build Coastguard Worker
3826*6777b538SAndroid Build Coastguard Worker /**
3827*6777b538SAndroid Build Coastguard Worker * xmlXPathNodeTrailing:
3828*6777b538SAndroid Build Coastguard Worker * @nodes: a node-set
3829*6777b538SAndroid Build Coastguard Worker * @node: a node
3830*6777b538SAndroid Build Coastguard Worker *
3831*6777b538SAndroid Build Coastguard Worker * Implements the EXSLT - Sets trailing() function:
3832*6777b538SAndroid Build Coastguard Worker * node-set set:trailing (node-set, node-set)
3833*6777b538SAndroid Build Coastguard Worker * @nodes is sorted by document order, then #xmlXPathNodeTrailingSorted
3834*6777b538SAndroid Build Coastguard Worker * is called.
3835*6777b538SAndroid Build Coastguard Worker *
3836*6777b538SAndroid Build Coastguard Worker * Returns the nodes in @nodes that follow @node in document order,
3837*6777b538SAndroid Build Coastguard Worker * @nodes if @node is NULL or an empty node-set if @nodes
3838*6777b538SAndroid Build Coastguard Worker * doesn't contain @node
3839*6777b538SAndroid Build Coastguard Worker */
3840*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathNodeTrailing(xmlNodeSetPtr nodes,xmlNodePtr node)3841*6777b538SAndroid Build Coastguard Worker xmlXPathNodeTrailing (xmlNodeSetPtr nodes, xmlNodePtr node) {
3842*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetSort(nodes);
3843*6777b538SAndroid Build Coastguard Worker return(xmlXPathNodeTrailingSorted(nodes, node));
3844*6777b538SAndroid Build Coastguard Worker }
3845*6777b538SAndroid Build Coastguard Worker
3846*6777b538SAndroid Build Coastguard Worker /**
3847*6777b538SAndroid Build Coastguard Worker * xmlXPathTrailingSorted:
3848*6777b538SAndroid Build Coastguard Worker * @nodes1: a node-set, sorted by document order
3849*6777b538SAndroid Build Coastguard Worker * @nodes2: a node-set, sorted by document order
3850*6777b538SAndroid Build Coastguard Worker *
3851*6777b538SAndroid Build Coastguard Worker * Implements the EXSLT - Sets trailing() function:
3852*6777b538SAndroid Build Coastguard Worker * node-set set:trailing (node-set, node-set)
3853*6777b538SAndroid Build Coastguard Worker *
3854*6777b538SAndroid Build Coastguard Worker * Returns the nodes in @nodes1 that follow the first node in @nodes2
3855*6777b538SAndroid Build Coastguard Worker * in document order, @nodes1 if @nodes2 is NULL or empty or
3856*6777b538SAndroid Build Coastguard Worker * an empty node-set if @nodes1 doesn't contain @nodes2
3857*6777b538SAndroid Build Coastguard Worker */
3858*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathTrailingSorted(xmlNodeSetPtr nodes1,xmlNodeSetPtr nodes2)3859*6777b538SAndroid Build Coastguard Worker xmlXPathTrailingSorted (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
3860*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes2))
3861*6777b538SAndroid Build Coastguard Worker return(nodes1);
3862*6777b538SAndroid Build Coastguard Worker return(xmlXPathNodeTrailingSorted(nodes1,
3863*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetItem(nodes2, 0)));
3864*6777b538SAndroid Build Coastguard Worker }
3865*6777b538SAndroid Build Coastguard Worker
3866*6777b538SAndroid Build Coastguard Worker /**
3867*6777b538SAndroid Build Coastguard Worker * xmlXPathTrailing:
3868*6777b538SAndroid Build Coastguard Worker * @nodes1: a node-set
3869*6777b538SAndroid Build Coastguard Worker * @nodes2: a node-set
3870*6777b538SAndroid Build Coastguard Worker *
3871*6777b538SAndroid Build Coastguard Worker * Implements the EXSLT - Sets trailing() function:
3872*6777b538SAndroid Build Coastguard Worker * node-set set:trailing (node-set, node-set)
3873*6777b538SAndroid Build Coastguard Worker * @nodes1 and @nodes2 are sorted by document order, then
3874*6777b538SAndroid Build Coastguard Worker * #xmlXPathTrailingSorted is called.
3875*6777b538SAndroid Build Coastguard Worker *
3876*6777b538SAndroid Build Coastguard Worker * Returns the nodes in @nodes1 that follow the first node in @nodes2
3877*6777b538SAndroid Build Coastguard Worker * in document order, @nodes1 if @nodes2 is NULL or empty or
3878*6777b538SAndroid Build Coastguard Worker * an empty node-set if @nodes1 doesn't contain @nodes2
3879*6777b538SAndroid Build Coastguard Worker */
3880*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr
xmlXPathTrailing(xmlNodeSetPtr nodes1,xmlNodeSetPtr nodes2)3881*6777b538SAndroid Build Coastguard Worker xmlXPathTrailing (xmlNodeSetPtr nodes1, xmlNodeSetPtr nodes2) {
3882*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes2))
3883*6777b538SAndroid Build Coastguard Worker return(nodes1);
3884*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetIsEmpty(nodes1))
3885*6777b538SAndroid Build Coastguard Worker return(xmlXPathNodeSetCreate(NULL));
3886*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetSort(nodes1);
3887*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetSort(nodes2);
3888*6777b538SAndroid Build Coastguard Worker return(xmlXPathNodeTrailingSorted(nodes1,
3889*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetItem(nodes2, 0)));
3890*6777b538SAndroid Build Coastguard Worker }
3891*6777b538SAndroid Build Coastguard Worker
3892*6777b538SAndroid Build Coastguard Worker /************************************************************************
3893*6777b538SAndroid Build Coastguard Worker * *
3894*6777b538SAndroid Build Coastguard Worker * Routines to handle extra functions *
3895*6777b538SAndroid Build Coastguard Worker * *
3896*6777b538SAndroid Build Coastguard Worker ************************************************************************/
3897*6777b538SAndroid Build Coastguard Worker
3898*6777b538SAndroid Build Coastguard Worker /**
3899*6777b538SAndroid Build Coastguard Worker * xmlXPathRegisterFunc:
3900*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath context
3901*6777b538SAndroid Build Coastguard Worker * @name: the function name
3902*6777b538SAndroid Build Coastguard Worker * @f: the function implementation or NULL
3903*6777b538SAndroid Build Coastguard Worker *
3904*6777b538SAndroid Build Coastguard Worker * Register a new function. If @f is NULL it unregisters the function
3905*6777b538SAndroid Build Coastguard Worker *
3906*6777b538SAndroid Build Coastguard Worker * Returns 0 in case of success, -1 in case of error
3907*6777b538SAndroid Build Coastguard Worker */
3908*6777b538SAndroid Build Coastguard Worker int
xmlXPathRegisterFunc(xmlXPathContextPtr ctxt,const xmlChar * name,xmlXPathFunction f)3909*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(xmlXPathContextPtr ctxt, const xmlChar *name,
3910*6777b538SAndroid Build Coastguard Worker xmlXPathFunction f) {
3911*6777b538SAndroid Build Coastguard Worker return(xmlXPathRegisterFuncNS(ctxt, name, NULL, f));
3912*6777b538SAndroid Build Coastguard Worker }
3913*6777b538SAndroid Build Coastguard Worker
3914*6777b538SAndroid Build Coastguard Worker /**
3915*6777b538SAndroid Build Coastguard Worker * xmlXPathRegisterFuncNS:
3916*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath context
3917*6777b538SAndroid Build Coastguard Worker * @name: the function name
3918*6777b538SAndroid Build Coastguard Worker * @ns_uri: the function namespace URI
3919*6777b538SAndroid Build Coastguard Worker * @f: the function implementation or NULL
3920*6777b538SAndroid Build Coastguard Worker *
3921*6777b538SAndroid Build Coastguard Worker * Register a new function. If @f is NULL it unregisters the function
3922*6777b538SAndroid Build Coastguard Worker *
3923*6777b538SAndroid Build Coastguard Worker * Returns 0 in case of success, -1 in case of error
3924*6777b538SAndroid Build Coastguard Worker */
3925*6777b538SAndroid Build Coastguard Worker int
xmlXPathRegisterFuncNS(xmlXPathContextPtr ctxt,const xmlChar * name,const xmlChar * ns_uri,xmlXPathFunction f)3926*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFuncNS(xmlXPathContextPtr ctxt, const xmlChar *name,
3927*6777b538SAndroid Build Coastguard Worker const xmlChar *ns_uri, xmlXPathFunction f) {
3928*6777b538SAndroid Build Coastguard Worker int ret;
3929*6777b538SAndroid Build Coastguard Worker
3930*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
3931*6777b538SAndroid Build Coastguard Worker return(-1);
3932*6777b538SAndroid Build Coastguard Worker if (name == NULL)
3933*6777b538SAndroid Build Coastguard Worker return(-1);
3934*6777b538SAndroid Build Coastguard Worker
3935*6777b538SAndroid Build Coastguard Worker if (ctxt->funcHash == NULL)
3936*6777b538SAndroid Build Coastguard Worker ctxt->funcHash = xmlHashCreate(0);
3937*6777b538SAndroid Build Coastguard Worker if (ctxt->funcHash == NULL) {
3938*6777b538SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt);
3939*6777b538SAndroid Build Coastguard Worker return(-1);
3940*6777b538SAndroid Build Coastguard Worker }
3941*6777b538SAndroid Build Coastguard Worker if (f == NULL)
3942*6777b538SAndroid Build Coastguard Worker return(xmlHashRemoveEntry2(ctxt->funcHash, name, ns_uri, NULL));
3943*6777b538SAndroid Build Coastguard Worker XML_IGNORE_FPTR_CAST_WARNINGS
3944*6777b538SAndroid Build Coastguard Worker ret = xmlHashAddEntry2(ctxt->funcHash, name, ns_uri, (void *) f);
3945*6777b538SAndroid Build Coastguard Worker XML_POP_WARNINGS
3946*6777b538SAndroid Build Coastguard Worker if (ret < 0) {
3947*6777b538SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt);
3948*6777b538SAndroid Build Coastguard Worker return(-1);
3949*6777b538SAndroid Build Coastguard Worker }
3950*6777b538SAndroid Build Coastguard Worker
3951*6777b538SAndroid Build Coastguard Worker return(0);
3952*6777b538SAndroid Build Coastguard Worker }
3953*6777b538SAndroid Build Coastguard Worker
3954*6777b538SAndroid Build Coastguard Worker /**
3955*6777b538SAndroid Build Coastguard Worker * xmlXPathRegisterFuncLookup:
3956*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath context
3957*6777b538SAndroid Build Coastguard Worker * @f: the lookup function
3958*6777b538SAndroid Build Coastguard Worker * @funcCtxt: the lookup data
3959*6777b538SAndroid Build Coastguard Worker *
3960*6777b538SAndroid Build Coastguard Worker * Registers an external mechanism to do function lookup.
3961*6777b538SAndroid Build Coastguard Worker */
3962*6777b538SAndroid Build Coastguard Worker void
xmlXPathRegisterFuncLookup(xmlXPathContextPtr ctxt,xmlXPathFuncLookupFunc f,void * funcCtxt)3963*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFuncLookup (xmlXPathContextPtr ctxt,
3964*6777b538SAndroid Build Coastguard Worker xmlXPathFuncLookupFunc f,
3965*6777b538SAndroid Build Coastguard Worker void *funcCtxt) {
3966*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
3967*6777b538SAndroid Build Coastguard Worker return;
3968*6777b538SAndroid Build Coastguard Worker ctxt->funcLookupFunc = f;
3969*6777b538SAndroid Build Coastguard Worker ctxt->funcLookupData = funcCtxt;
3970*6777b538SAndroid Build Coastguard Worker }
3971*6777b538SAndroid Build Coastguard Worker
3972*6777b538SAndroid Build Coastguard Worker /**
3973*6777b538SAndroid Build Coastguard Worker * xmlXPathFunctionLookup:
3974*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath context
3975*6777b538SAndroid Build Coastguard Worker * @name: the function name
3976*6777b538SAndroid Build Coastguard Worker *
3977*6777b538SAndroid Build Coastguard Worker * Search in the Function array of the context for the given
3978*6777b538SAndroid Build Coastguard Worker * function.
3979*6777b538SAndroid Build Coastguard Worker *
3980*6777b538SAndroid Build Coastguard Worker * Returns the xmlXPathFunction or NULL if not found
3981*6777b538SAndroid Build Coastguard Worker */
3982*6777b538SAndroid Build Coastguard Worker xmlXPathFunction
xmlXPathFunctionLookup(xmlXPathContextPtr ctxt,const xmlChar * name)3983*6777b538SAndroid Build Coastguard Worker xmlXPathFunctionLookup(xmlXPathContextPtr ctxt, const xmlChar *name) {
3984*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
3985*6777b538SAndroid Build Coastguard Worker return (NULL);
3986*6777b538SAndroid Build Coastguard Worker
3987*6777b538SAndroid Build Coastguard Worker if (ctxt->funcLookupFunc != NULL) {
3988*6777b538SAndroid Build Coastguard Worker xmlXPathFunction ret;
3989*6777b538SAndroid Build Coastguard Worker xmlXPathFuncLookupFunc f;
3990*6777b538SAndroid Build Coastguard Worker
3991*6777b538SAndroid Build Coastguard Worker f = ctxt->funcLookupFunc;
3992*6777b538SAndroid Build Coastguard Worker ret = f(ctxt->funcLookupData, name, NULL);
3993*6777b538SAndroid Build Coastguard Worker if (ret != NULL)
3994*6777b538SAndroid Build Coastguard Worker return(ret);
3995*6777b538SAndroid Build Coastguard Worker }
3996*6777b538SAndroid Build Coastguard Worker return(xmlXPathFunctionLookupNS(ctxt, name, NULL));
3997*6777b538SAndroid Build Coastguard Worker }
3998*6777b538SAndroid Build Coastguard Worker
3999*6777b538SAndroid Build Coastguard Worker /**
4000*6777b538SAndroid Build Coastguard Worker * xmlXPathFunctionLookupNS:
4001*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath context
4002*6777b538SAndroid Build Coastguard Worker * @name: the function name
4003*6777b538SAndroid Build Coastguard Worker * @ns_uri: the function namespace URI
4004*6777b538SAndroid Build Coastguard Worker *
4005*6777b538SAndroid Build Coastguard Worker * Search in the Function array of the context for the given
4006*6777b538SAndroid Build Coastguard Worker * function.
4007*6777b538SAndroid Build Coastguard Worker *
4008*6777b538SAndroid Build Coastguard Worker * Returns the xmlXPathFunction or NULL if not found
4009*6777b538SAndroid Build Coastguard Worker */
4010*6777b538SAndroid Build Coastguard Worker xmlXPathFunction
xmlXPathFunctionLookupNS(xmlXPathContextPtr ctxt,const xmlChar * name,const xmlChar * ns_uri)4011*6777b538SAndroid Build Coastguard Worker xmlXPathFunctionLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name,
4012*6777b538SAndroid Build Coastguard Worker const xmlChar *ns_uri) {
4013*6777b538SAndroid Build Coastguard Worker xmlXPathFunction ret;
4014*6777b538SAndroid Build Coastguard Worker
4015*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
4016*6777b538SAndroid Build Coastguard Worker return(NULL);
4017*6777b538SAndroid Build Coastguard Worker if (name == NULL)
4018*6777b538SAndroid Build Coastguard Worker return(NULL);
4019*6777b538SAndroid Build Coastguard Worker
4020*6777b538SAndroid Build Coastguard Worker if (ctxt->funcLookupFunc != NULL) {
4021*6777b538SAndroid Build Coastguard Worker xmlXPathFuncLookupFunc f;
4022*6777b538SAndroid Build Coastguard Worker
4023*6777b538SAndroid Build Coastguard Worker f = ctxt->funcLookupFunc;
4024*6777b538SAndroid Build Coastguard Worker ret = f(ctxt->funcLookupData, name, ns_uri);
4025*6777b538SAndroid Build Coastguard Worker if (ret != NULL)
4026*6777b538SAndroid Build Coastguard Worker return(ret);
4027*6777b538SAndroid Build Coastguard Worker }
4028*6777b538SAndroid Build Coastguard Worker
4029*6777b538SAndroid Build Coastguard Worker if (ctxt->funcHash == NULL)
4030*6777b538SAndroid Build Coastguard Worker return(NULL);
4031*6777b538SAndroid Build Coastguard Worker
4032*6777b538SAndroid Build Coastguard Worker XML_IGNORE_FPTR_CAST_WARNINGS
4033*6777b538SAndroid Build Coastguard Worker ret = (xmlXPathFunction) xmlHashLookup2(ctxt->funcHash, name, ns_uri);
4034*6777b538SAndroid Build Coastguard Worker XML_POP_WARNINGS
4035*6777b538SAndroid Build Coastguard Worker return(ret);
4036*6777b538SAndroid Build Coastguard Worker }
4037*6777b538SAndroid Build Coastguard Worker
4038*6777b538SAndroid Build Coastguard Worker /**
4039*6777b538SAndroid Build Coastguard Worker * xmlXPathRegisteredFuncsCleanup:
4040*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath context
4041*6777b538SAndroid Build Coastguard Worker *
4042*6777b538SAndroid Build Coastguard Worker * Cleanup the XPath context data associated to registered functions
4043*6777b538SAndroid Build Coastguard Worker */
4044*6777b538SAndroid Build Coastguard Worker void
xmlXPathRegisteredFuncsCleanup(xmlXPathContextPtr ctxt)4045*6777b538SAndroid Build Coastguard Worker xmlXPathRegisteredFuncsCleanup(xmlXPathContextPtr ctxt) {
4046*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
4047*6777b538SAndroid Build Coastguard Worker return;
4048*6777b538SAndroid Build Coastguard Worker
4049*6777b538SAndroid Build Coastguard Worker xmlHashFree(ctxt->funcHash, NULL);
4050*6777b538SAndroid Build Coastguard Worker ctxt->funcHash = NULL;
4051*6777b538SAndroid Build Coastguard Worker }
4052*6777b538SAndroid Build Coastguard Worker
4053*6777b538SAndroid Build Coastguard Worker /************************************************************************
4054*6777b538SAndroid Build Coastguard Worker * *
4055*6777b538SAndroid Build Coastguard Worker * Routines to handle Variables *
4056*6777b538SAndroid Build Coastguard Worker * *
4057*6777b538SAndroid Build Coastguard Worker ************************************************************************/
4058*6777b538SAndroid Build Coastguard Worker
4059*6777b538SAndroid Build Coastguard Worker /**
4060*6777b538SAndroid Build Coastguard Worker * xmlXPathRegisterVariable:
4061*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath context
4062*6777b538SAndroid Build Coastguard Worker * @name: the variable name
4063*6777b538SAndroid Build Coastguard Worker * @value: the variable value or NULL
4064*6777b538SAndroid Build Coastguard Worker *
4065*6777b538SAndroid Build Coastguard Worker * Register a new variable value. If @value is NULL it unregisters
4066*6777b538SAndroid Build Coastguard Worker * the variable
4067*6777b538SAndroid Build Coastguard Worker *
4068*6777b538SAndroid Build Coastguard Worker * Returns 0 in case of success, -1 in case of error
4069*6777b538SAndroid Build Coastguard Worker */
4070*6777b538SAndroid Build Coastguard Worker int
xmlXPathRegisterVariable(xmlXPathContextPtr ctxt,const xmlChar * name,xmlXPathObjectPtr value)4071*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterVariable(xmlXPathContextPtr ctxt, const xmlChar *name,
4072*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr value) {
4073*6777b538SAndroid Build Coastguard Worker return(xmlXPathRegisterVariableNS(ctxt, name, NULL, value));
4074*6777b538SAndroid Build Coastguard Worker }
4075*6777b538SAndroid Build Coastguard Worker
4076*6777b538SAndroid Build Coastguard Worker /**
4077*6777b538SAndroid Build Coastguard Worker * xmlXPathRegisterVariableNS:
4078*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath context
4079*6777b538SAndroid Build Coastguard Worker * @name: the variable name
4080*6777b538SAndroid Build Coastguard Worker * @ns_uri: the variable namespace URI
4081*6777b538SAndroid Build Coastguard Worker * @value: the variable value or NULL
4082*6777b538SAndroid Build Coastguard Worker *
4083*6777b538SAndroid Build Coastguard Worker * Register a new variable value. If @value is NULL it unregisters
4084*6777b538SAndroid Build Coastguard Worker * the variable
4085*6777b538SAndroid Build Coastguard Worker *
4086*6777b538SAndroid Build Coastguard Worker * Returns 0 in case of success, -1 in case of error
4087*6777b538SAndroid Build Coastguard Worker */
4088*6777b538SAndroid Build Coastguard Worker int
xmlXPathRegisterVariableNS(xmlXPathContextPtr ctxt,const xmlChar * name,const xmlChar * ns_uri,xmlXPathObjectPtr value)4089*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterVariableNS(xmlXPathContextPtr ctxt, const xmlChar *name,
4090*6777b538SAndroid Build Coastguard Worker const xmlChar *ns_uri,
4091*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr value) {
4092*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
4093*6777b538SAndroid Build Coastguard Worker return(-1);
4094*6777b538SAndroid Build Coastguard Worker if (name == NULL)
4095*6777b538SAndroid Build Coastguard Worker return(-1);
4096*6777b538SAndroid Build Coastguard Worker
4097*6777b538SAndroid Build Coastguard Worker if (ctxt->varHash == NULL)
4098*6777b538SAndroid Build Coastguard Worker ctxt->varHash = xmlHashCreate(0);
4099*6777b538SAndroid Build Coastguard Worker if (ctxt->varHash == NULL)
4100*6777b538SAndroid Build Coastguard Worker return(-1);
4101*6777b538SAndroid Build Coastguard Worker if (value == NULL)
4102*6777b538SAndroid Build Coastguard Worker return(xmlHashRemoveEntry2(ctxt->varHash, name, ns_uri,
4103*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObjectEntry));
4104*6777b538SAndroid Build Coastguard Worker return(xmlHashUpdateEntry2(ctxt->varHash, name, ns_uri,
4105*6777b538SAndroid Build Coastguard Worker (void *) value, xmlXPathFreeObjectEntry));
4106*6777b538SAndroid Build Coastguard Worker }
4107*6777b538SAndroid Build Coastguard Worker
4108*6777b538SAndroid Build Coastguard Worker /**
4109*6777b538SAndroid Build Coastguard Worker * xmlXPathRegisterVariableLookup:
4110*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath context
4111*6777b538SAndroid Build Coastguard Worker * @f: the lookup function
4112*6777b538SAndroid Build Coastguard Worker * @data: the lookup data
4113*6777b538SAndroid Build Coastguard Worker *
4114*6777b538SAndroid Build Coastguard Worker * register an external mechanism to do variable lookup
4115*6777b538SAndroid Build Coastguard Worker */
4116*6777b538SAndroid Build Coastguard Worker void
xmlXPathRegisterVariableLookup(xmlXPathContextPtr ctxt,xmlXPathVariableLookupFunc f,void * data)4117*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterVariableLookup(xmlXPathContextPtr ctxt,
4118*6777b538SAndroid Build Coastguard Worker xmlXPathVariableLookupFunc f, void *data) {
4119*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
4120*6777b538SAndroid Build Coastguard Worker return;
4121*6777b538SAndroid Build Coastguard Worker ctxt->varLookupFunc = f;
4122*6777b538SAndroid Build Coastguard Worker ctxt->varLookupData = data;
4123*6777b538SAndroid Build Coastguard Worker }
4124*6777b538SAndroid Build Coastguard Worker
4125*6777b538SAndroid Build Coastguard Worker /**
4126*6777b538SAndroid Build Coastguard Worker * xmlXPathVariableLookup:
4127*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath context
4128*6777b538SAndroid Build Coastguard Worker * @name: the variable name
4129*6777b538SAndroid Build Coastguard Worker *
4130*6777b538SAndroid Build Coastguard Worker * Search in the Variable array of the context for the given
4131*6777b538SAndroid Build Coastguard Worker * variable value.
4132*6777b538SAndroid Build Coastguard Worker *
4133*6777b538SAndroid Build Coastguard Worker * Returns a copy of the value or NULL if not found
4134*6777b538SAndroid Build Coastguard Worker */
4135*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathVariableLookup(xmlXPathContextPtr ctxt,const xmlChar * name)4136*6777b538SAndroid Build Coastguard Worker xmlXPathVariableLookup(xmlXPathContextPtr ctxt, const xmlChar *name) {
4137*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
4138*6777b538SAndroid Build Coastguard Worker return(NULL);
4139*6777b538SAndroid Build Coastguard Worker
4140*6777b538SAndroid Build Coastguard Worker if (ctxt->varLookupFunc != NULL) {
4141*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
4142*6777b538SAndroid Build Coastguard Worker
4143*6777b538SAndroid Build Coastguard Worker ret = ((xmlXPathVariableLookupFunc)ctxt->varLookupFunc)
4144*6777b538SAndroid Build Coastguard Worker (ctxt->varLookupData, name, NULL);
4145*6777b538SAndroid Build Coastguard Worker return(ret);
4146*6777b538SAndroid Build Coastguard Worker }
4147*6777b538SAndroid Build Coastguard Worker return(xmlXPathVariableLookupNS(ctxt, name, NULL));
4148*6777b538SAndroid Build Coastguard Worker }
4149*6777b538SAndroid Build Coastguard Worker
4150*6777b538SAndroid Build Coastguard Worker /**
4151*6777b538SAndroid Build Coastguard Worker * xmlXPathVariableLookupNS:
4152*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath context
4153*6777b538SAndroid Build Coastguard Worker * @name: the variable name
4154*6777b538SAndroid Build Coastguard Worker * @ns_uri: the variable namespace URI
4155*6777b538SAndroid Build Coastguard Worker *
4156*6777b538SAndroid Build Coastguard Worker * Search in the Variable array of the context for the given
4157*6777b538SAndroid Build Coastguard Worker * variable value.
4158*6777b538SAndroid Build Coastguard Worker *
4159*6777b538SAndroid Build Coastguard Worker * Returns the a copy of the value or NULL if not found
4160*6777b538SAndroid Build Coastguard Worker */
4161*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathVariableLookupNS(xmlXPathContextPtr ctxt,const xmlChar * name,const xmlChar * ns_uri)4162*6777b538SAndroid Build Coastguard Worker xmlXPathVariableLookupNS(xmlXPathContextPtr ctxt, const xmlChar *name,
4163*6777b538SAndroid Build Coastguard Worker const xmlChar *ns_uri) {
4164*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
4165*6777b538SAndroid Build Coastguard Worker return(NULL);
4166*6777b538SAndroid Build Coastguard Worker
4167*6777b538SAndroid Build Coastguard Worker if (ctxt->varLookupFunc != NULL) {
4168*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
4169*6777b538SAndroid Build Coastguard Worker
4170*6777b538SAndroid Build Coastguard Worker ret = ((xmlXPathVariableLookupFunc)ctxt->varLookupFunc)
4171*6777b538SAndroid Build Coastguard Worker (ctxt->varLookupData, name, ns_uri);
4172*6777b538SAndroid Build Coastguard Worker if (ret != NULL) return(ret);
4173*6777b538SAndroid Build Coastguard Worker }
4174*6777b538SAndroid Build Coastguard Worker
4175*6777b538SAndroid Build Coastguard Worker if (ctxt->varHash == NULL)
4176*6777b538SAndroid Build Coastguard Worker return(NULL);
4177*6777b538SAndroid Build Coastguard Worker if (name == NULL)
4178*6777b538SAndroid Build Coastguard Worker return(NULL);
4179*6777b538SAndroid Build Coastguard Worker
4180*6777b538SAndroid Build Coastguard Worker return(xmlXPathObjectCopy(xmlHashLookup2(ctxt->varHash, name, ns_uri)));
4181*6777b538SAndroid Build Coastguard Worker }
4182*6777b538SAndroid Build Coastguard Worker
4183*6777b538SAndroid Build Coastguard Worker /**
4184*6777b538SAndroid Build Coastguard Worker * xmlXPathRegisteredVariablesCleanup:
4185*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath context
4186*6777b538SAndroid Build Coastguard Worker *
4187*6777b538SAndroid Build Coastguard Worker * Cleanup the XPath context data associated to registered variables
4188*6777b538SAndroid Build Coastguard Worker */
4189*6777b538SAndroid Build Coastguard Worker void
xmlXPathRegisteredVariablesCleanup(xmlXPathContextPtr ctxt)4190*6777b538SAndroid Build Coastguard Worker xmlXPathRegisteredVariablesCleanup(xmlXPathContextPtr ctxt) {
4191*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
4192*6777b538SAndroid Build Coastguard Worker return;
4193*6777b538SAndroid Build Coastguard Worker
4194*6777b538SAndroid Build Coastguard Worker xmlHashFree(ctxt->varHash, xmlXPathFreeObjectEntry);
4195*6777b538SAndroid Build Coastguard Worker ctxt->varHash = NULL;
4196*6777b538SAndroid Build Coastguard Worker }
4197*6777b538SAndroid Build Coastguard Worker
4198*6777b538SAndroid Build Coastguard Worker /**
4199*6777b538SAndroid Build Coastguard Worker * xmlXPathRegisterNs:
4200*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath context
4201*6777b538SAndroid Build Coastguard Worker * @prefix: the namespace prefix cannot be NULL or empty string
4202*6777b538SAndroid Build Coastguard Worker * @ns_uri: the namespace name
4203*6777b538SAndroid Build Coastguard Worker *
4204*6777b538SAndroid Build Coastguard Worker * Register a new namespace. If @ns_uri is NULL it unregisters
4205*6777b538SAndroid Build Coastguard Worker * the namespace
4206*6777b538SAndroid Build Coastguard Worker *
4207*6777b538SAndroid Build Coastguard Worker * Returns 0 in case of success, -1 in case of error
4208*6777b538SAndroid Build Coastguard Worker */
4209*6777b538SAndroid Build Coastguard Worker int
xmlXPathRegisterNs(xmlXPathContextPtr ctxt,const xmlChar * prefix,const xmlChar * ns_uri)4210*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterNs(xmlXPathContextPtr ctxt, const xmlChar *prefix,
4211*6777b538SAndroid Build Coastguard Worker const xmlChar *ns_uri) {
4212*6777b538SAndroid Build Coastguard Worker xmlChar *copy;
4213*6777b538SAndroid Build Coastguard Worker
4214*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
4215*6777b538SAndroid Build Coastguard Worker return(-1);
4216*6777b538SAndroid Build Coastguard Worker if (prefix == NULL)
4217*6777b538SAndroid Build Coastguard Worker return(-1);
4218*6777b538SAndroid Build Coastguard Worker if (prefix[0] == 0)
4219*6777b538SAndroid Build Coastguard Worker return(-1);
4220*6777b538SAndroid Build Coastguard Worker
4221*6777b538SAndroid Build Coastguard Worker if (ctxt->nsHash == NULL)
4222*6777b538SAndroid Build Coastguard Worker ctxt->nsHash = xmlHashCreate(10);
4223*6777b538SAndroid Build Coastguard Worker if (ctxt->nsHash == NULL) {
4224*6777b538SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt);
4225*6777b538SAndroid Build Coastguard Worker return(-1);
4226*6777b538SAndroid Build Coastguard Worker }
4227*6777b538SAndroid Build Coastguard Worker if (ns_uri == NULL)
4228*6777b538SAndroid Build Coastguard Worker return(xmlHashRemoveEntry(ctxt->nsHash, prefix,
4229*6777b538SAndroid Build Coastguard Worker xmlHashDefaultDeallocator));
4230*6777b538SAndroid Build Coastguard Worker
4231*6777b538SAndroid Build Coastguard Worker copy = xmlStrdup(ns_uri);
4232*6777b538SAndroid Build Coastguard Worker if (copy == NULL) {
4233*6777b538SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt);
4234*6777b538SAndroid Build Coastguard Worker return(-1);
4235*6777b538SAndroid Build Coastguard Worker }
4236*6777b538SAndroid Build Coastguard Worker if (xmlHashUpdateEntry(ctxt->nsHash, prefix, copy,
4237*6777b538SAndroid Build Coastguard Worker xmlHashDefaultDeallocator) < 0) {
4238*6777b538SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt);
4239*6777b538SAndroid Build Coastguard Worker xmlFree(copy);
4240*6777b538SAndroid Build Coastguard Worker return(-1);
4241*6777b538SAndroid Build Coastguard Worker }
4242*6777b538SAndroid Build Coastguard Worker
4243*6777b538SAndroid Build Coastguard Worker return(0);
4244*6777b538SAndroid Build Coastguard Worker }
4245*6777b538SAndroid Build Coastguard Worker
4246*6777b538SAndroid Build Coastguard Worker /**
4247*6777b538SAndroid Build Coastguard Worker * xmlXPathNsLookup:
4248*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath context
4249*6777b538SAndroid Build Coastguard Worker * @prefix: the namespace prefix value
4250*6777b538SAndroid Build Coastguard Worker *
4251*6777b538SAndroid Build Coastguard Worker * Search in the namespace declaration array of the context for the given
4252*6777b538SAndroid Build Coastguard Worker * namespace name associated to the given prefix
4253*6777b538SAndroid Build Coastguard Worker *
4254*6777b538SAndroid Build Coastguard Worker * Returns the value or NULL if not found
4255*6777b538SAndroid Build Coastguard Worker */
4256*6777b538SAndroid Build Coastguard Worker const xmlChar *
xmlXPathNsLookup(xmlXPathContextPtr ctxt,const xmlChar * prefix)4257*6777b538SAndroid Build Coastguard Worker xmlXPathNsLookup(xmlXPathContextPtr ctxt, const xmlChar *prefix) {
4258*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
4259*6777b538SAndroid Build Coastguard Worker return(NULL);
4260*6777b538SAndroid Build Coastguard Worker if (prefix == NULL)
4261*6777b538SAndroid Build Coastguard Worker return(NULL);
4262*6777b538SAndroid Build Coastguard Worker
4263*6777b538SAndroid Build Coastguard Worker #ifdef XML_XML_NAMESPACE
4264*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(prefix, (const xmlChar *) "xml"))
4265*6777b538SAndroid Build Coastguard Worker return(XML_XML_NAMESPACE);
4266*6777b538SAndroid Build Coastguard Worker #endif
4267*6777b538SAndroid Build Coastguard Worker
4268*6777b538SAndroid Build Coastguard Worker if (ctxt->namespaces != NULL) {
4269*6777b538SAndroid Build Coastguard Worker int i;
4270*6777b538SAndroid Build Coastguard Worker
4271*6777b538SAndroid Build Coastguard Worker for (i = 0;i < ctxt->nsNr;i++) {
4272*6777b538SAndroid Build Coastguard Worker if ((ctxt->namespaces[i] != NULL) &&
4273*6777b538SAndroid Build Coastguard Worker (xmlStrEqual(ctxt->namespaces[i]->prefix, prefix)))
4274*6777b538SAndroid Build Coastguard Worker return(ctxt->namespaces[i]->href);
4275*6777b538SAndroid Build Coastguard Worker }
4276*6777b538SAndroid Build Coastguard Worker }
4277*6777b538SAndroid Build Coastguard Worker
4278*6777b538SAndroid Build Coastguard Worker return((const xmlChar *) xmlHashLookup(ctxt->nsHash, prefix));
4279*6777b538SAndroid Build Coastguard Worker }
4280*6777b538SAndroid Build Coastguard Worker
4281*6777b538SAndroid Build Coastguard Worker /**
4282*6777b538SAndroid Build Coastguard Worker * xmlXPathRegisteredNsCleanup:
4283*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath context
4284*6777b538SAndroid Build Coastguard Worker *
4285*6777b538SAndroid Build Coastguard Worker * Cleanup the XPath context data associated to registered variables
4286*6777b538SAndroid Build Coastguard Worker */
4287*6777b538SAndroid Build Coastguard Worker void
xmlXPathRegisteredNsCleanup(xmlXPathContextPtr ctxt)4288*6777b538SAndroid Build Coastguard Worker xmlXPathRegisteredNsCleanup(xmlXPathContextPtr ctxt) {
4289*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
4290*6777b538SAndroid Build Coastguard Worker return;
4291*6777b538SAndroid Build Coastguard Worker
4292*6777b538SAndroid Build Coastguard Worker xmlHashFree(ctxt->nsHash, xmlHashDefaultDeallocator);
4293*6777b538SAndroid Build Coastguard Worker ctxt->nsHash = NULL;
4294*6777b538SAndroid Build Coastguard Worker }
4295*6777b538SAndroid Build Coastguard Worker
4296*6777b538SAndroid Build Coastguard Worker /************************************************************************
4297*6777b538SAndroid Build Coastguard Worker * *
4298*6777b538SAndroid Build Coastguard Worker * Routines to handle Values *
4299*6777b538SAndroid Build Coastguard Worker * *
4300*6777b538SAndroid Build Coastguard Worker ************************************************************************/
4301*6777b538SAndroid Build Coastguard Worker
4302*6777b538SAndroid Build Coastguard Worker /* Allocations are terrible, one needs to optimize all this !!! */
4303*6777b538SAndroid Build Coastguard Worker
4304*6777b538SAndroid Build Coastguard Worker /**
4305*6777b538SAndroid Build Coastguard Worker * xmlXPathNewFloat:
4306*6777b538SAndroid Build Coastguard Worker * @val: the double value
4307*6777b538SAndroid Build Coastguard Worker *
4308*6777b538SAndroid Build Coastguard Worker * Create a new xmlXPathObjectPtr of type double and of value @val
4309*6777b538SAndroid Build Coastguard Worker *
4310*6777b538SAndroid Build Coastguard Worker * Returns the newly created object.
4311*6777b538SAndroid Build Coastguard Worker */
4312*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathNewFloat(double val)4313*6777b538SAndroid Build Coastguard Worker xmlXPathNewFloat(double val) {
4314*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
4315*6777b538SAndroid Build Coastguard Worker
4316*6777b538SAndroid Build Coastguard Worker ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
4317*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
4318*6777b538SAndroid Build Coastguard Worker return(NULL);
4319*6777b538SAndroid Build Coastguard Worker memset(ret, 0 , sizeof(xmlXPathObject));
4320*6777b538SAndroid Build Coastguard Worker ret->type = XPATH_NUMBER;
4321*6777b538SAndroid Build Coastguard Worker ret->floatval = val;
4322*6777b538SAndroid Build Coastguard Worker return(ret);
4323*6777b538SAndroid Build Coastguard Worker }
4324*6777b538SAndroid Build Coastguard Worker
4325*6777b538SAndroid Build Coastguard Worker /**
4326*6777b538SAndroid Build Coastguard Worker * xmlXPathNewBoolean:
4327*6777b538SAndroid Build Coastguard Worker * @val: the boolean value
4328*6777b538SAndroid Build Coastguard Worker *
4329*6777b538SAndroid Build Coastguard Worker * Create a new xmlXPathObjectPtr of type boolean and of value @val
4330*6777b538SAndroid Build Coastguard Worker *
4331*6777b538SAndroid Build Coastguard Worker * Returns the newly created object.
4332*6777b538SAndroid Build Coastguard Worker */
4333*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathNewBoolean(int val)4334*6777b538SAndroid Build Coastguard Worker xmlXPathNewBoolean(int val) {
4335*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
4336*6777b538SAndroid Build Coastguard Worker
4337*6777b538SAndroid Build Coastguard Worker ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
4338*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
4339*6777b538SAndroid Build Coastguard Worker return(NULL);
4340*6777b538SAndroid Build Coastguard Worker memset(ret, 0 , sizeof(xmlXPathObject));
4341*6777b538SAndroid Build Coastguard Worker ret->type = XPATH_BOOLEAN;
4342*6777b538SAndroid Build Coastguard Worker ret->boolval = (val != 0);
4343*6777b538SAndroid Build Coastguard Worker return(ret);
4344*6777b538SAndroid Build Coastguard Worker }
4345*6777b538SAndroid Build Coastguard Worker
4346*6777b538SAndroid Build Coastguard Worker /**
4347*6777b538SAndroid Build Coastguard Worker * xmlXPathNewString:
4348*6777b538SAndroid Build Coastguard Worker * @val: the xmlChar * value
4349*6777b538SAndroid Build Coastguard Worker *
4350*6777b538SAndroid Build Coastguard Worker * Create a new xmlXPathObjectPtr of type string and of value @val
4351*6777b538SAndroid Build Coastguard Worker *
4352*6777b538SAndroid Build Coastguard Worker * Returns the newly created object.
4353*6777b538SAndroid Build Coastguard Worker */
4354*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathNewString(const xmlChar * val)4355*6777b538SAndroid Build Coastguard Worker xmlXPathNewString(const xmlChar *val) {
4356*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
4357*6777b538SAndroid Build Coastguard Worker
4358*6777b538SAndroid Build Coastguard Worker ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
4359*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
4360*6777b538SAndroid Build Coastguard Worker return(NULL);
4361*6777b538SAndroid Build Coastguard Worker memset(ret, 0 , sizeof(xmlXPathObject));
4362*6777b538SAndroid Build Coastguard Worker ret->type = XPATH_STRING;
4363*6777b538SAndroid Build Coastguard Worker if (val == NULL)
4364*6777b538SAndroid Build Coastguard Worker val = BAD_CAST "";
4365*6777b538SAndroid Build Coastguard Worker ret->stringval = xmlStrdup(val);
4366*6777b538SAndroid Build Coastguard Worker if (ret->stringval == NULL) {
4367*6777b538SAndroid Build Coastguard Worker xmlFree(ret);
4368*6777b538SAndroid Build Coastguard Worker return(NULL);
4369*6777b538SAndroid Build Coastguard Worker }
4370*6777b538SAndroid Build Coastguard Worker return(ret);
4371*6777b538SAndroid Build Coastguard Worker }
4372*6777b538SAndroid Build Coastguard Worker
4373*6777b538SAndroid Build Coastguard Worker /**
4374*6777b538SAndroid Build Coastguard Worker * xmlXPathWrapString:
4375*6777b538SAndroid Build Coastguard Worker * @val: the xmlChar * value
4376*6777b538SAndroid Build Coastguard Worker *
4377*6777b538SAndroid Build Coastguard Worker * Wraps the @val string into an XPath object.
4378*6777b538SAndroid Build Coastguard Worker *
4379*6777b538SAndroid Build Coastguard Worker * Returns the newly created object.
4380*6777b538SAndroid Build Coastguard Worker *
4381*6777b538SAndroid Build Coastguard Worker * Frees @val in case of error.
4382*6777b538SAndroid Build Coastguard Worker */
4383*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathWrapString(xmlChar * val)4384*6777b538SAndroid Build Coastguard Worker xmlXPathWrapString (xmlChar *val) {
4385*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
4386*6777b538SAndroid Build Coastguard Worker
4387*6777b538SAndroid Build Coastguard Worker ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
4388*6777b538SAndroid Build Coastguard Worker if (ret == NULL) {
4389*6777b538SAndroid Build Coastguard Worker xmlFree(val);
4390*6777b538SAndroid Build Coastguard Worker return(NULL);
4391*6777b538SAndroid Build Coastguard Worker }
4392*6777b538SAndroid Build Coastguard Worker memset(ret, 0 , sizeof(xmlXPathObject));
4393*6777b538SAndroid Build Coastguard Worker ret->type = XPATH_STRING;
4394*6777b538SAndroid Build Coastguard Worker ret->stringval = val;
4395*6777b538SAndroid Build Coastguard Worker return(ret);
4396*6777b538SAndroid Build Coastguard Worker }
4397*6777b538SAndroid Build Coastguard Worker
4398*6777b538SAndroid Build Coastguard Worker /**
4399*6777b538SAndroid Build Coastguard Worker * xmlXPathNewCString:
4400*6777b538SAndroid Build Coastguard Worker * @val: the char * value
4401*6777b538SAndroid Build Coastguard Worker *
4402*6777b538SAndroid Build Coastguard Worker * Create a new xmlXPathObjectPtr of type string and of value @val
4403*6777b538SAndroid Build Coastguard Worker *
4404*6777b538SAndroid Build Coastguard Worker * Returns the newly created object.
4405*6777b538SAndroid Build Coastguard Worker */
4406*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathNewCString(const char * val)4407*6777b538SAndroid Build Coastguard Worker xmlXPathNewCString(const char *val) {
4408*6777b538SAndroid Build Coastguard Worker return(xmlXPathNewString(BAD_CAST val));
4409*6777b538SAndroid Build Coastguard Worker }
4410*6777b538SAndroid Build Coastguard Worker
4411*6777b538SAndroid Build Coastguard Worker /**
4412*6777b538SAndroid Build Coastguard Worker * xmlXPathWrapCString:
4413*6777b538SAndroid Build Coastguard Worker * @val: the char * value
4414*6777b538SAndroid Build Coastguard Worker *
4415*6777b538SAndroid Build Coastguard Worker * Wraps a string into an XPath object.
4416*6777b538SAndroid Build Coastguard Worker *
4417*6777b538SAndroid Build Coastguard Worker * Returns the newly created object.
4418*6777b538SAndroid Build Coastguard Worker */
4419*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathWrapCString(char * val)4420*6777b538SAndroid Build Coastguard Worker xmlXPathWrapCString (char * val) {
4421*6777b538SAndroid Build Coastguard Worker return(xmlXPathWrapString((xmlChar *)(val)));
4422*6777b538SAndroid Build Coastguard Worker }
4423*6777b538SAndroid Build Coastguard Worker
4424*6777b538SAndroid Build Coastguard Worker /**
4425*6777b538SAndroid Build Coastguard Worker * xmlXPathWrapExternal:
4426*6777b538SAndroid Build Coastguard Worker * @val: the user data
4427*6777b538SAndroid Build Coastguard Worker *
4428*6777b538SAndroid Build Coastguard Worker * Wraps the @val data into an XPath object.
4429*6777b538SAndroid Build Coastguard Worker *
4430*6777b538SAndroid Build Coastguard Worker * Returns the newly created object.
4431*6777b538SAndroid Build Coastguard Worker */
4432*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathWrapExternal(void * val)4433*6777b538SAndroid Build Coastguard Worker xmlXPathWrapExternal (void *val) {
4434*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
4435*6777b538SAndroid Build Coastguard Worker
4436*6777b538SAndroid Build Coastguard Worker ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
4437*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
4438*6777b538SAndroid Build Coastguard Worker return(NULL);
4439*6777b538SAndroid Build Coastguard Worker memset(ret, 0 , sizeof(xmlXPathObject));
4440*6777b538SAndroid Build Coastguard Worker ret->type = XPATH_USERS;
4441*6777b538SAndroid Build Coastguard Worker ret->user = val;
4442*6777b538SAndroid Build Coastguard Worker return(ret);
4443*6777b538SAndroid Build Coastguard Worker }
4444*6777b538SAndroid Build Coastguard Worker
4445*6777b538SAndroid Build Coastguard Worker /**
4446*6777b538SAndroid Build Coastguard Worker * xmlXPathObjectCopy:
4447*6777b538SAndroid Build Coastguard Worker * @val: the original object
4448*6777b538SAndroid Build Coastguard Worker *
4449*6777b538SAndroid Build Coastguard Worker * allocate a new copy of a given object
4450*6777b538SAndroid Build Coastguard Worker *
4451*6777b538SAndroid Build Coastguard Worker * Returns the newly created object.
4452*6777b538SAndroid Build Coastguard Worker */
4453*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathObjectCopy(xmlXPathObjectPtr val)4454*6777b538SAndroid Build Coastguard Worker xmlXPathObjectCopy(xmlXPathObjectPtr val) {
4455*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
4456*6777b538SAndroid Build Coastguard Worker
4457*6777b538SAndroid Build Coastguard Worker if (val == NULL)
4458*6777b538SAndroid Build Coastguard Worker return(NULL);
4459*6777b538SAndroid Build Coastguard Worker
4460*6777b538SAndroid Build Coastguard Worker ret = (xmlXPathObjectPtr) xmlMalloc(sizeof(xmlXPathObject));
4461*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
4462*6777b538SAndroid Build Coastguard Worker return(NULL);
4463*6777b538SAndroid Build Coastguard Worker memcpy(ret, val , sizeof(xmlXPathObject));
4464*6777b538SAndroid Build Coastguard Worker switch (val->type) {
4465*6777b538SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
4466*6777b538SAndroid Build Coastguard Worker case XPATH_NUMBER:
4467*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
4468*6777b538SAndroid Build Coastguard Worker case XPATH_POINT:
4469*6777b538SAndroid Build Coastguard Worker case XPATH_RANGE:
4470*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_XPTR_LOCS_ENABLED */
4471*6777b538SAndroid Build Coastguard Worker break;
4472*6777b538SAndroid Build Coastguard Worker case XPATH_STRING:
4473*6777b538SAndroid Build Coastguard Worker ret->stringval = xmlStrdup(val->stringval);
4474*6777b538SAndroid Build Coastguard Worker if (ret->stringval == NULL) {
4475*6777b538SAndroid Build Coastguard Worker xmlFree(ret);
4476*6777b538SAndroid Build Coastguard Worker return(NULL);
4477*6777b538SAndroid Build Coastguard Worker }
4478*6777b538SAndroid Build Coastguard Worker break;
4479*6777b538SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
4480*6777b538SAndroid Build Coastguard Worker #if 0
4481*6777b538SAndroid Build Coastguard Worker /*
4482*6777b538SAndroid Build Coastguard Worker Removed 11 July 2004 - the current handling of xslt tmpRVT nodes means that
4483*6777b538SAndroid Build Coastguard Worker this previous handling is no longer correct, and can cause some serious
4484*6777b538SAndroid Build Coastguard Worker problems (ref. bug 145547)
4485*6777b538SAndroid Build Coastguard Worker */
4486*6777b538SAndroid Build Coastguard Worker if ((val->nodesetval != NULL) &&
4487*6777b538SAndroid Build Coastguard Worker (val->nodesetval->nodeTab != NULL)) {
4488*6777b538SAndroid Build Coastguard Worker xmlNodePtr cur, tmp;
4489*6777b538SAndroid Build Coastguard Worker xmlDocPtr top;
4490*6777b538SAndroid Build Coastguard Worker
4491*6777b538SAndroid Build Coastguard Worker ret->boolval = 1;
4492*6777b538SAndroid Build Coastguard Worker top = xmlNewDoc(NULL);
4493*6777b538SAndroid Build Coastguard Worker top->name = (char *)
4494*6777b538SAndroid Build Coastguard Worker xmlStrdup(val->nodesetval->nodeTab[0]->name);
4495*6777b538SAndroid Build Coastguard Worker ret->user = top;
4496*6777b538SAndroid Build Coastguard Worker if (top != NULL) {
4497*6777b538SAndroid Build Coastguard Worker top->doc = top;
4498*6777b538SAndroid Build Coastguard Worker cur = val->nodesetval->nodeTab[0]->children;
4499*6777b538SAndroid Build Coastguard Worker while (cur != NULL) {
4500*6777b538SAndroid Build Coastguard Worker tmp = xmlDocCopyNode(cur, top, 1);
4501*6777b538SAndroid Build Coastguard Worker xmlAddChild((xmlNodePtr) top, tmp);
4502*6777b538SAndroid Build Coastguard Worker cur = cur->next;
4503*6777b538SAndroid Build Coastguard Worker }
4504*6777b538SAndroid Build Coastguard Worker }
4505*6777b538SAndroid Build Coastguard Worker
4506*6777b538SAndroid Build Coastguard Worker ret->nodesetval = xmlXPathNodeSetCreate((xmlNodePtr) top);
4507*6777b538SAndroid Build Coastguard Worker } else
4508*6777b538SAndroid Build Coastguard Worker ret->nodesetval = xmlXPathNodeSetCreate(NULL);
4509*6777b538SAndroid Build Coastguard Worker /* Deallocate the copied tree value */
4510*6777b538SAndroid Build Coastguard Worker break;
4511*6777b538SAndroid Build Coastguard Worker #endif
4512*6777b538SAndroid Build Coastguard Worker case XPATH_NODESET:
4513*6777b538SAndroid Build Coastguard Worker ret->nodesetval = xmlXPathNodeSetMerge(NULL, val->nodesetval);
4514*6777b538SAndroid Build Coastguard Worker if (ret->nodesetval == NULL) {
4515*6777b538SAndroid Build Coastguard Worker xmlFree(ret);
4516*6777b538SAndroid Build Coastguard Worker return(NULL);
4517*6777b538SAndroid Build Coastguard Worker }
4518*6777b538SAndroid Build Coastguard Worker /* Do not deallocate the copied tree value */
4519*6777b538SAndroid Build Coastguard Worker ret->boolval = 0;
4520*6777b538SAndroid Build Coastguard Worker break;
4521*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
4522*6777b538SAndroid Build Coastguard Worker case XPATH_LOCATIONSET:
4523*6777b538SAndroid Build Coastguard Worker {
4524*6777b538SAndroid Build Coastguard Worker xmlLocationSetPtr loc = val->user;
4525*6777b538SAndroid Build Coastguard Worker ret->user = (void *) xmlXPtrLocationSetMerge(NULL, loc);
4526*6777b538SAndroid Build Coastguard Worker break;
4527*6777b538SAndroid Build Coastguard Worker }
4528*6777b538SAndroid Build Coastguard Worker #endif
4529*6777b538SAndroid Build Coastguard Worker case XPATH_USERS:
4530*6777b538SAndroid Build Coastguard Worker ret->user = val->user;
4531*6777b538SAndroid Build Coastguard Worker break;
4532*6777b538SAndroid Build Coastguard Worker default:
4533*6777b538SAndroid Build Coastguard Worker xmlFree(ret);
4534*6777b538SAndroid Build Coastguard Worker ret = NULL;
4535*6777b538SAndroid Build Coastguard Worker break;
4536*6777b538SAndroid Build Coastguard Worker }
4537*6777b538SAndroid Build Coastguard Worker return(ret);
4538*6777b538SAndroid Build Coastguard Worker }
4539*6777b538SAndroid Build Coastguard Worker
4540*6777b538SAndroid Build Coastguard Worker /**
4541*6777b538SAndroid Build Coastguard Worker * xmlXPathFreeObject:
4542*6777b538SAndroid Build Coastguard Worker * @obj: the object to free
4543*6777b538SAndroid Build Coastguard Worker *
4544*6777b538SAndroid Build Coastguard Worker * Free up an xmlXPathObjectPtr object.
4545*6777b538SAndroid Build Coastguard Worker */
4546*6777b538SAndroid Build Coastguard Worker void
xmlXPathFreeObject(xmlXPathObjectPtr obj)4547*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject(xmlXPathObjectPtr obj) {
4548*6777b538SAndroid Build Coastguard Worker if (obj == NULL) return;
4549*6777b538SAndroid Build Coastguard Worker if ((obj->type == XPATH_NODESET) || (obj->type == XPATH_XSLT_TREE)) {
4550*6777b538SAndroid Build Coastguard Worker if (obj->nodesetval != NULL)
4551*6777b538SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(obj->nodesetval);
4552*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
4553*6777b538SAndroid Build Coastguard Worker } else if (obj->type == XPATH_LOCATIONSET) {
4554*6777b538SAndroid Build Coastguard Worker if (obj->user != NULL)
4555*6777b538SAndroid Build Coastguard Worker xmlXPtrFreeLocationSet(obj->user);
4556*6777b538SAndroid Build Coastguard Worker #endif
4557*6777b538SAndroid Build Coastguard Worker } else if (obj->type == XPATH_STRING) {
4558*6777b538SAndroid Build Coastguard Worker if (obj->stringval != NULL)
4559*6777b538SAndroid Build Coastguard Worker xmlFree(obj->stringval);
4560*6777b538SAndroid Build Coastguard Worker }
4561*6777b538SAndroid Build Coastguard Worker xmlFree(obj);
4562*6777b538SAndroid Build Coastguard Worker }
4563*6777b538SAndroid Build Coastguard Worker
4564*6777b538SAndroid Build Coastguard Worker static void
xmlXPathFreeObjectEntry(void * obj,const xmlChar * name ATTRIBUTE_UNUSED)4565*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObjectEntry(void *obj, const xmlChar *name ATTRIBUTE_UNUSED) {
4566*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject((xmlXPathObjectPtr) obj);
4567*6777b538SAndroid Build Coastguard Worker }
4568*6777b538SAndroid Build Coastguard Worker
4569*6777b538SAndroid Build Coastguard Worker /**
4570*6777b538SAndroid Build Coastguard Worker * xmlXPathReleaseObject:
4571*6777b538SAndroid Build Coastguard Worker * @obj: the xmlXPathObjectPtr to free or to cache
4572*6777b538SAndroid Build Coastguard Worker *
4573*6777b538SAndroid Build Coastguard Worker * Depending on the state of the cache this frees the given
4574*6777b538SAndroid Build Coastguard Worker * XPath object or stores it in the cache.
4575*6777b538SAndroid Build Coastguard Worker */
4576*6777b538SAndroid Build Coastguard Worker static void
xmlXPathReleaseObject(xmlXPathContextPtr ctxt,xmlXPathObjectPtr obj)4577*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(xmlXPathContextPtr ctxt, xmlXPathObjectPtr obj)
4578*6777b538SAndroid Build Coastguard Worker {
4579*6777b538SAndroid Build Coastguard Worker if (obj == NULL)
4580*6777b538SAndroid Build Coastguard Worker return;
4581*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->cache == NULL)) {
4582*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject(obj);
4583*6777b538SAndroid Build Coastguard Worker } else {
4584*6777b538SAndroid Build Coastguard Worker xmlXPathContextCachePtr cache =
4585*6777b538SAndroid Build Coastguard Worker (xmlXPathContextCachePtr) ctxt->cache;
4586*6777b538SAndroid Build Coastguard Worker
4587*6777b538SAndroid Build Coastguard Worker switch (obj->type) {
4588*6777b538SAndroid Build Coastguard Worker case XPATH_NODESET:
4589*6777b538SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
4590*6777b538SAndroid Build Coastguard Worker if (obj->nodesetval != NULL) {
4591*6777b538SAndroid Build Coastguard Worker if ((obj->nodesetval->nodeMax <= 40) &&
4592*6777b538SAndroid Build Coastguard Worker (cache->numNodeset < cache->maxNodeset)) {
4593*6777b538SAndroid Build Coastguard Worker obj->stringval = (void *) cache->nodesetObjs;
4594*6777b538SAndroid Build Coastguard Worker cache->nodesetObjs = obj;
4595*6777b538SAndroid Build Coastguard Worker cache->numNodeset += 1;
4596*6777b538SAndroid Build Coastguard Worker goto obj_cached;
4597*6777b538SAndroid Build Coastguard Worker } else {
4598*6777b538SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(obj->nodesetval);
4599*6777b538SAndroid Build Coastguard Worker obj->nodesetval = NULL;
4600*6777b538SAndroid Build Coastguard Worker }
4601*6777b538SAndroid Build Coastguard Worker }
4602*6777b538SAndroid Build Coastguard Worker break;
4603*6777b538SAndroid Build Coastguard Worker case XPATH_STRING:
4604*6777b538SAndroid Build Coastguard Worker if (obj->stringval != NULL)
4605*6777b538SAndroid Build Coastguard Worker xmlFree(obj->stringval);
4606*6777b538SAndroid Build Coastguard Worker obj->stringval = NULL;
4607*6777b538SAndroid Build Coastguard Worker break;
4608*6777b538SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
4609*6777b538SAndroid Build Coastguard Worker case XPATH_NUMBER:
4610*6777b538SAndroid Build Coastguard Worker break;
4611*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
4612*6777b538SAndroid Build Coastguard Worker case XPATH_LOCATIONSET:
4613*6777b538SAndroid Build Coastguard Worker if (obj->user != NULL) {
4614*6777b538SAndroid Build Coastguard Worker xmlXPtrFreeLocationSet(obj->user);
4615*6777b538SAndroid Build Coastguard Worker }
4616*6777b538SAndroid Build Coastguard Worker goto free_obj;
4617*6777b538SAndroid Build Coastguard Worker #endif
4618*6777b538SAndroid Build Coastguard Worker default:
4619*6777b538SAndroid Build Coastguard Worker goto free_obj;
4620*6777b538SAndroid Build Coastguard Worker }
4621*6777b538SAndroid Build Coastguard Worker
4622*6777b538SAndroid Build Coastguard Worker /*
4623*6777b538SAndroid Build Coastguard Worker * Fallback to adding to the misc-objects slot.
4624*6777b538SAndroid Build Coastguard Worker */
4625*6777b538SAndroid Build Coastguard Worker if (cache->numMisc >= cache->maxMisc)
4626*6777b538SAndroid Build Coastguard Worker goto free_obj;
4627*6777b538SAndroid Build Coastguard Worker obj->stringval = (void *) cache->miscObjs;
4628*6777b538SAndroid Build Coastguard Worker cache->miscObjs = obj;
4629*6777b538SAndroid Build Coastguard Worker cache->numMisc += 1;
4630*6777b538SAndroid Build Coastguard Worker
4631*6777b538SAndroid Build Coastguard Worker obj_cached:
4632*6777b538SAndroid Build Coastguard Worker obj->boolval = 0;
4633*6777b538SAndroid Build Coastguard Worker if (obj->nodesetval != NULL) {
4634*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr tmpset = obj->nodesetval;
4635*6777b538SAndroid Build Coastguard Worker
4636*6777b538SAndroid Build Coastguard Worker /*
4637*6777b538SAndroid Build Coastguard Worker * Due to those nasty ns-nodes, we need to traverse
4638*6777b538SAndroid Build Coastguard Worker * the list and free the ns-nodes.
4639*6777b538SAndroid Build Coastguard Worker */
4640*6777b538SAndroid Build Coastguard Worker if (tmpset->nodeNr > 0) {
4641*6777b538SAndroid Build Coastguard Worker int i;
4642*6777b538SAndroid Build Coastguard Worker xmlNodePtr node;
4643*6777b538SAndroid Build Coastguard Worker
4644*6777b538SAndroid Build Coastguard Worker for (i = 0; i < tmpset->nodeNr; i++) {
4645*6777b538SAndroid Build Coastguard Worker node = tmpset->nodeTab[i];
4646*6777b538SAndroid Build Coastguard Worker if ((node != NULL) &&
4647*6777b538SAndroid Build Coastguard Worker (node->type == XML_NAMESPACE_DECL))
4648*6777b538SAndroid Build Coastguard Worker {
4649*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetFreeNs((xmlNsPtr) node);
4650*6777b538SAndroid Build Coastguard Worker }
4651*6777b538SAndroid Build Coastguard Worker }
4652*6777b538SAndroid Build Coastguard Worker }
4653*6777b538SAndroid Build Coastguard Worker tmpset->nodeNr = 0;
4654*6777b538SAndroid Build Coastguard Worker }
4655*6777b538SAndroid Build Coastguard Worker
4656*6777b538SAndroid Build Coastguard Worker return;
4657*6777b538SAndroid Build Coastguard Worker
4658*6777b538SAndroid Build Coastguard Worker free_obj:
4659*6777b538SAndroid Build Coastguard Worker /*
4660*6777b538SAndroid Build Coastguard Worker * Cache is full; free the object.
4661*6777b538SAndroid Build Coastguard Worker */
4662*6777b538SAndroid Build Coastguard Worker if (obj->nodesetval != NULL)
4663*6777b538SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(obj->nodesetval);
4664*6777b538SAndroid Build Coastguard Worker xmlFree(obj);
4665*6777b538SAndroid Build Coastguard Worker }
4666*6777b538SAndroid Build Coastguard Worker return;
4667*6777b538SAndroid Build Coastguard Worker }
4668*6777b538SAndroid Build Coastguard Worker
4669*6777b538SAndroid Build Coastguard Worker
4670*6777b538SAndroid Build Coastguard Worker /************************************************************************
4671*6777b538SAndroid Build Coastguard Worker * *
4672*6777b538SAndroid Build Coastguard Worker * Type Casting Routines *
4673*6777b538SAndroid Build Coastguard Worker * *
4674*6777b538SAndroid Build Coastguard Worker ************************************************************************/
4675*6777b538SAndroid Build Coastguard Worker
4676*6777b538SAndroid Build Coastguard Worker /**
4677*6777b538SAndroid Build Coastguard Worker * xmlXPathCastBooleanToString:
4678*6777b538SAndroid Build Coastguard Worker * @val: a boolean
4679*6777b538SAndroid Build Coastguard Worker *
4680*6777b538SAndroid Build Coastguard Worker * Converts a boolean to its string value.
4681*6777b538SAndroid Build Coastguard Worker *
4682*6777b538SAndroid Build Coastguard Worker * Returns a newly allocated string.
4683*6777b538SAndroid Build Coastguard Worker */
4684*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlXPathCastBooleanToString(int val)4685*6777b538SAndroid Build Coastguard Worker xmlXPathCastBooleanToString (int val) {
4686*6777b538SAndroid Build Coastguard Worker xmlChar *ret;
4687*6777b538SAndroid Build Coastguard Worker if (val)
4688*6777b538SAndroid Build Coastguard Worker ret = xmlStrdup((const xmlChar *) "true");
4689*6777b538SAndroid Build Coastguard Worker else
4690*6777b538SAndroid Build Coastguard Worker ret = xmlStrdup((const xmlChar *) "false");
4691*6777b538SAndroid Build Coastguard Worker return(ret);
4692*6777b538SAndroid Build Coastguard Worker }
4693*6777b538SAndroid Build Coastguard Worker
4694*6777b538SAndroid Build Coastguard Worker /**
4695*6777b538SAndroid Build Coastguard Worker * xmlXPathCastNumberToString:
4696*6777b538SAndroid Build Coastguard Worker * @val: a number
4697*6777b538SAndroid Build Coastguard Worker *
4698*6777b538SAndroid Build Coastguard Worker * Converts a number to its string value.
4699*6777b538SAndroid Build Coastguard Worker *
4700*6777b538SAndroid Build Coastguard Worker * Returns a newly allocated string.
4701*6777b538SAndroid Build Coastguard Worker */
4702*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlXPathCastNumberToString(double val)4703*6777b538SAndroid Build Coastguard Worker xmlXPathCastNumberToString (double val) {
4704*6777b538SAndroid Build Coastguard Worker xmlChar *ret;
4705*6777b538SAndroid Build Coastguard Worker switch (xmlXPathIsInf(val)) {
4706*6777b538SAndroid Build Coastguard Worker case 1:
4707*6777b538SAndroid Build Coastguard Worker ret = xmlStrdup((const xmlChar *) "Infinity");
4708*6777b538SAndroid Build Coastguard Worker break;
4709*6777b538SAndroid Build Coastguard Worker case -1:
4710*6777b538SAndroid Build Coastguard Worker ret = xmlStrdup((const xmlChar *) "-Infinity");
4711*6777b538SAndroid Build Coastguard Worker break;
4712*6777b538SAndroid Build Coastguard Worker default:
4713*6777b538SAndroid Build Coastguard Worker if (xmlXPathIsNaN(val)) {
4714*6777b538SAndroid Build Coastguard Worker ret = xmlStrdup((const xmlChar *) "NaN");
4715*6777b538SAndroid Build Coastguard Worker } else if (val == 0) {
4716*6777b538SAndroid Build Coastguard Worker /* Omit sign for negative zero. */
4717*6777b538SAndroid Build Coastguard Worker ret = xmlStrdup((const xmlChar *) "0");
4718*6777b538SAndroid Build Coastguard Worker } else {
4719*6777b538SAndroid Build Coastguard Worker /* could be improved */
4720*6777b538SAndroid Build Coastguard Worker char buf[100];
4721*6777b538SAndroid Build Coastguard Worker xmlXPathFormatNumber(val, buf, 99);
4722*6777b538SAndroid Build Coastguard Worker buf[99] = 0;
4723*6777b538SAndroid Build Coastguard Worker ret = xmlStrdup((const xmlChar *) buf);
4724*6777b538SAndroid Build Coastguard Worker }
4725*6777b538SAndroid Build Coastguard Worker }
4726*6777b538SAndroid Build Coastguard Worker return(ret);
4727*6777b538SAndroid Build Coastguard Worker }
4728*6777b538SAndroid Build Coastguard Worker
4729*6777b538SAndroid Build Coastguard Worker /**
4730*6777b538SAndroid Build Coastguard Worker * xmlXPathCastNodeToString:
4731*6777b538SAndroid Build Coastguard Worker * @node: a node
4732*6777b538SAndroid Build Coastguard Worker *
4733*6777b538SAndroid Build Coastguard Worker * Converts a node to its string value.
4734*6777b538SAndroid Build Coastguard Worker *
4735*6777b538SAndroid Build Coastguard Worker * Returns a newly allocated string.
4736*6777b538SAndroid Build Coastguard Worker */
4737*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlXPathCastNodeToString(xmlNodePtr node)4738*6777b538SAndroid Build Coastguard Worker xmlXPathCastNodeToString (xmlNodePtr node) {
4739*6777b538SAndroid Build Coastguard Worker return(xmlNodeGetContent(node));
4740*6777b538SAndroid Build Coastguard Worker }
4741*6777b538SAndroid Build Coastguard Worker
4742*6777b538SAndroid Build Coastguard Worker /**
4743*6777b538SAndroid Build Coastguard Worker * xmlXPathCastNodeSetToString:
4744*6777b538SAndroid Build Coastguard Worker * @ns: a node-set
4745*6777b538SAndroid Build Coastguard Worker *
4746*6777b538SAndroid Build Coastguard Worker * Converts a node-set to its string value.
4747*6777b538SAndroid Build Coastguard Worker *
4748*6777b538SAndroid Build Coastguard Worker * Returns a newly allocated string.
4749*6777b538SAndroid Build Coastguard Worker */
4750*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlXPathCastNodeSetToString(xmlNodeSetPtr ns)4751*6777b538SAndroid Build Coastguard Worker xmlXPathCastNodeSetToString (xmlNodeSetPtr ns) {
4752*6777b538SAndroid Build Coastguard Worker if ((ns == NULL) || (ns->nodeNr == 0) || (ns->nodeTab == NULL))
4753*6777b538SAndroid Build Coastguard Worker return(xmlStrdup((const xmlChar *) ""));
4754*6777b538SAndroid Build Coastguard Worker
4755*6777b538SAndroid Build Coastguard Worker if (ns->nodeNr > 1)
4756*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetSort(ns);
4757*6777b538SAndroid Build Coastguard Worker return(xmlXPathCastNodeToString(ns->nodeTab[0]));
4758*6777b538SAndroid Build Coastguard Worker }
4759*6777b538SAndroid Build Coastguard Worker
4760*6777b538SAndroid Build Coastguard Worker /**
4761*6777b538SAndroid Build Coastguard Worker * xmlXPathCastToString:
4762*6777b538SAndroid Build Coastguard Worker * @val: an XPath object
4763*6777b538SAndroid Build Coastguard Worker *
4764*6777b538SAndroid Build Coastguard Worker * Converts an existing object to its string() equivalent
4765*6777b538SAndroid Build Coastguard Worker *
4766*6777b538SAndroid Build Coastguard Worker * Returns the allocated string value of the object, NULL in case of error.
4767*6777b538SAndroid Build Coastguard Worker * It's up to the caller to free the string memory with xmlFree().
4768*6777b538SAndroid Build Coastguard Worker */
4769*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlXPathCastToString(xmlXPathObjectPtr val)4770*6777b538SAndroid Build Coastguard Worker xmlXPathCastToString(xmlXPathObjectPtr val) {
4771*6777b538SAndroid Build Coastguard Worker xmlChar *ret = NULL;
4772*6777b538SAndroid Build Coastguard Worker
4773*6777b538SAndroid Build Coastguard Worker if (val == NULL)
4774*6777b538SAndroid Build Coastguard Worker return(xmlStrdup((const xmlChar *) ""));
4775*6777b538SAndroid Build Coastguard Worker switch (val->type) {
4776*6777b538SAndroid Build Coastguard Worker case XPATH_UNDEFINED:
4777*6777b538SAndroid Build Coastguard Worker ret = xmlStrdup((const xmlChar *) "");
4778*6777b538SAndroid Build Coastguard Worker break;
4779*6777b538SAndroid Build Coastguard Worker case XPATH_NODESET:
4780*6777b538SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
4781*6777b538SAndroid Build Coastguard Worker ret = xmlXPathCastNodeSetToString(val->nodesetval);
4782*6777b538SAndroid Build Coastguard Worker break;
4783*6777b538SAndroid Build Coastguard Worker case XPATH_STRING:
4784*6777b538SAndroid Build Coastguard Worker return(xmlStrdup(val->stringval));
4785*6777b538SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
4786*6777b538SAndroid Build Coastguard Worker ret = xmlXPathCastBooleanToString(val->boolval);
4787*6777b538SAndroid Build Coastguard Worker break;
4788*6777b538SAndroid Build Coastguard Worker case XPATH_NUMBER: {
4789*6777b538SAndroid Build Coastguard Worker ret = xmlXPathCastNumberToString(val->floatval);
4790*6777b538SAndroid Build Coastguard Worker break;
4791*6777b538SAndroid Build Coastguard Worker }
4792*6777b538SAndroid Build Coastguard Worker case XPATH_USERS:
4793*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
4794*6777b538SAndroid Build Coastguard Worker case XPATH_POINT:
4795*6777b538SAndroid Build Coastguard Worker case XPATH_RANGE:
4796*6777b538SAndroid Build Coastguard Worker case XPATH_LOCATIONSET:
4797*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_XPTR_LOCS_ENABLED */
4798*6777b538SAndroid Build Coastguard Worker /* TODO */
4799*6777b538SAndroid Build Coastguard Worker ret = xmlStrdup((const xmlChar *) "");
4800*6777b538SAndroid Build Coastguard Worker break;
4801*6777b538SAndroid Build Coastguard Worker }
4802*6777b538SAndroid Build Coastguard Worker return(ret);
4803*6777b538SAndroid Build Coastguard Worker }
4804*6777b538SAndroid Build Coastguard Worker
4805*6777b538SAndroid Build Coastguard Worker /**
4806*6777b538SAndroid Build Coastguard Worker * xmlXPathConvertString:
4807*6777b538SAndroid Build Coastguard Worker * @val: an XPath object
4808*6777b538SAndroid Build Coastguard Worker *
4809*6777b538SAndroid Build Coastguard Worker * Converts an existing object to its string() equivalent
4810*6777b538SAndroid Build Coastguard Worker *
4811*6777b538SAndroid Build Coastguard Worker * Returns the new object, the old one is freed (or the operation
4812*6777b538SAndroid Build Coastguard Worker * is done directly on @val)
4813*6777b538SAndroid Build Coastguard Worker */
4814*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathConvertString(xmlXPathObjectPtr val)4815*6777b538SAndroid Build Coastguard Worker xmlXPathConvertString(xmlXPathObjectPtr val) {
4816*6777b538SAndroid Build Coastguard Worker xmlChar *res = NULL;
4817*6777b538SAndroid Build Coastguard Worker
4818*6777b538SAndroid Build Coastguard Worker if (val == NULL)
4819*6777b538SAndroid Build Coastguard Worker return(xmlXPathNewCString(""));
4820*6777b538SAndroid Build Coastguard Worker
4821*6777b538SAndroid Build Coastguard Worker switch (val->type) {
4822*6777b538SAndroid Build Coastguard Worker case XPATH_UNDEFINED:
4823*6777b538SAndroid Build Coastguard Worker break;
4824*6777b538SAndroid Build Coastguard Worker case XPATH_NODESET:
4825*6777b538SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
4826*6777b538SAndroid Build Coastguard Worker res = xmlXPathCastNodeSetToString(val->nodesetval);
4827*6777b538SAndroid Build Coastguard Worker break;
4828*6777b538SAndroid Build Coastguard Worker case XPATH_STRING:
4829*6777b538SAndroid Build Coastguard Worker return(val);
4830*6777b538SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
4831*6777b538SAndroid Build Coastguard Worker res = xmlXPathCastBooleanToString(val->boolval);
4832*6777b538SAndroid Build Coastguard Worker break;
4833*6777b538SAndroid Build Coastguard Worker case XPATH_NUMBER:
4834*6777b538SAndroid Build Coastguard Worker res = xmlXPathCastNumberToString(val->floatval);
4835*6777b538SAndroid Build Coastguard Worker break;
4836*6777b538SAndroid Build Coastguard Worker case XPATH_USERS:
4837*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
4838*6777b538SAndroid Build Coastguard Worker case XPATH_POINT:
4839*6777b538SAndroid Build Coastguard Worker case XPATH_RANGE:
4840*6777b538SAndroid Build Coastguard Worker case XPATH_LOCATIONSET:
4841*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_XPTR_LOCS_ENABLED */
4842*6777b538SAndroid Build Coastguard Worker /* TODO */
4843*6777b538SAndroid Build Coastguard Worker break;
4844*6777b538SAndroid Build Coastguard Worker }
4845*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject(val);
4846*6777b538SAndroid Build Coastguard Worker if (res == NULL)
4847*6777b538SAndroid Build Coastguard Worker return(xmlXPathNewCString(""));
4848*6777b538SAndroid Build Coastguard Worker return(xmlXPathWrapString(res));
4849*6777b538SAndroid Build Coastguard Worker }
4850*6777b538SAndroid Build Coastguard Worker
4851*6777b538SAndroid Build Coastguard Worker /**
4852*6777b538SAndroid Build Coastguard Worker * xmlXPathCastBooleanToNumber:
4853*6777b538SAndroid Build Coastguard Worker * @val: a boolean
4854*6777b538SAndroid Build Coastguard Worker *
4855*6777b538SAndroid Build Coastguard Worker * Converts a boolean to its number value
4856*6777b538SAndroid Build Coastguard Worker *
4857*6777b538SAndroid Build Coastguard Worker * Returns the number value
4858*6777b538SAndroid Build Coastguard Worker */
4859*6777b538SAndroid Build Coastguard Worker double
xmlXPathCastBooleanToNumber(int val)4860*6777b538SAndroid Build Coastguard Worker xmlXPathCastBooleanToNumber(int val) {
4861*6777b538SAndroid Build Coastguard Worker if (val)
4862*6777b538SAndroid Build Coastguard Worker return(1.0);
4863*6777b538SAndroid Build Coastguard Worker return(0.0);
4864*6777b538SAndroid Build Coastguard Worker }
4865*6777b538SAndroid Build Coastguard Worker
4866*6777b538SAndroid Build Coastguard Worker /**
4867*6777b538SAndroid Build Coastguard Worker * xmlXPathCastStringToNumber:
4868*6777b538SAndroid Build Coastguard Worker * @val: a string
4869*6777b538SAndroid Build Coastguard Worker *
4870*6777b538SAndroid Build Coastguard Worker * Converts a string to its number value
4871*6777b538SAndroid Build Coastguard Worker *
4872*6777b538SAndroid Build Coastguard Worker * Returns the number value
4873*6777b538SAndroid Build Coastguard Worker */
4874*6777b538SAndroid Build Coastguard Worker double
xmlXPathCastStringToNumber(const xmlChar * val)4875*6777b538SAndroid Build Coastguard Worker xmlXPathCastStringToNumber(const xmlChar * val) {
4876*6777b538SAndroid Build Coastguard Worker return(xmlXPathStringEvalNumber(val));
4877*6777b538SAndroid Build Coastguard Worker }
4878*6777b538SAndroid Build Coastguard Worker
4879*6777b538SAndroid Build Coastguard Worker /**
4880*6777b538SAndroid Build Coastguard Worker * xmlXPathNodeToNumberInternal:
4881*6777b538SAndroid Build Coastguard Worker * @node: a node
4882*6777b538SAndroid Build Coastguard Worker *
4883*6777b538SAndroid Build Coastguard Worker * Converts a node to its number value
4884*6777b538SAndroid Build Coastguard Worker *
4885*6777b538SAndroid Build Coastguard Worker * Returns the number value
4886*6777b538SAndroid Build Coastguard Worker */
4887*6777b538SAndroid Build Coastguard Worker static double
xmlXPathNodeToNumberInternal(xmlXPathParserContextPtr ctxt,xmlNodePtr node)4888*6777b538SAndroid Build Coastguard Worker xmlXPathNodeToNumberInternal(xmlXPathParserContextPtr ctxt, xmlNodePtr node) {
4889*6777b538SAndroid Build Coastguard Worker xmlChar *strval;
4890*6777b538SAndroid Build Coastguard Worker double ret;
4891*6777b538SAndroid Build Coastguard Worker
4892*6777b538SAndroid Build Coastguard Worker if (node == NULL)
4893*6777b538SAndroid Build Coastguard Worker return(xmlXPathNAN);
4894*6777b538SAndroid Build Coastguard Worker strval = xmlXPathCastNodeToString(node);
4895*6777b538SAndroid Build Coastguard Worker if (strval == NULL) {
4896*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
4897*6777b538SAndroid Build Coastguard Worker return(xmlXPathNAN);
4898*6777b538SAndroid Build Coastguard Worker }
4899*6777b538SAndroid Build Coastguard Worker ret = xmlXPathCastStringToNumber(strval);
4900*6777b538SAndroid Build Coastguard Worker xmlFree(strval);
4901*6777b538SAndroid Build Coastguard Worker
4902*6777b538SAndroid Build Coastguard Worker return(ret);
4903*6777b538SAndroid Build Coastguard Worker }
4904*6777b538SAndroid Build Coastguard Worker
4905*6777b538SAndroid Build Coastguard Worker /**
4906*6777b538SAndroid Build Coastguard Worker * xmlXPathCastNodeToNumber:
4907*6777b538SAndroid Build Coastguard Worker * @node: a node
4908*6777b538SAndroid Build Coastguard Worker *
4909*6777b538SAndroid Build Coastguard Worker * Converts a node to its number value
4910*6777b538SAndroid Build Coastguard Worker *
4911*6777b538SAndroid Build Coastguard Worker * Returns the number value
4912*6777b538SAndroid Build Coastguard Worker */
4913*6777b538SAndroid Build Coastguard Worker double
xmlXPathCastNodeToNumber(xmlNodePtr node)4914*6777b538SAndroid Build Coastguard Worker xmlXPathCastNodeToNumber (xmlNodePtr node) {
4915*6777b538SAndroid Build Coastguard Worker return(xmlXPathNodeToNumberInternal(NULL, node));
4916*6777b538SAndroid Build Coastguard Worker }
4917*6777b538SAndroid Build Coastguard Worker
4918*6777b538SAndroid Build Coastguard Worker /**
4919*6777b538SAndroid Build Coastguard Worker * xmlXPathCastNodeSetToNumber:
4920*6777b538SAndroid Build Coastguard Worker * @ns: a node-set
4921*6777b538SAndroid Build Coastguard Worker *
4922*6777b538SAndroid Build Coastguard Worker * Converts a node-set to its number value
4923*6777b538SAndroid Build Coastguard Worker *
4924*6777b538SAndroid Build Coastguard Worker * Returns the number value
4925*6777b538SAndroid Build Coastguard Worker */
4926*6777b538SAndroid Build Coastguard Worker double
xmlXPathCastNodeSetToNumber(xmlNodeSetPtr ns)4927*6777b538SAndroid Build Coastguard Worker xmlXPathCastNodeSetToNumber (xmlNodeSetPtr ns) {
4928*6777b538SAndroid Build Coastguard Worker xmlChar *str;
4929*6777b538SAndroid Build Coastguard Worker double ret;
4930*6777b538SAndroid Build Coastguard Worker
4931*6777b538SAndroid Build Coastguard Worker if (ns == NULL)
4932*6777b538SAndroid Build Coastguard Worker return(xmlXPathNAN);
4933*6777b538SAndroid Build Coastguard Worker str = xmlXPathCastNodeSetToString(ns);
4934*6777b538SAndroid Build Coastguard Worker ret = xmlXPathCastStringToNumber(str);
4935*6777b538SAndroid Build Coastguard Worker xmlFree(str);
4936*6777b538SAndroid Build Coastguard Worker return(ret);
4937*6777b538SAndroid Build Coastguard Worker }
4938*6777b538SAndroid Build Coastguard Worker
4939*6777b538SAndroid Build Coastguard Worker /**
4940*6777b538SAndroid Build Coastguard Worker * xmlXPathCastToNumber:
4941*6777b538SAndroid Build Coastguard Worker * @val: an XPath object
4942*6777b538SAndroid Build Coastguard Worker *
4943*6777b538SAndroid Build Coastguard Worker * Converts an XPath object to its number value
4944*6777b538SAndroid Build Coastguard Worker *
4945*6777b538SAndroid Build Coastguard Worker * Returns the number value
4946*6777b538SAndroid Build Coastguard Worker */
4947*6777b538SAndroid Build Coastguard Worker double
xmlXPathCastToNumber(xmlXPathObjectPtr val)4948*6777b538SAndroid Build Coastguard Worker xmlXPathCastToNumber(xmlXPathObjectPtr val) {
4949*6777b538SAndroid Build Coastguard Worker return(xmlXPathCastToNumberInternal(NULL, val));
4950*6777b538SAndroid Build Coastguard Worker }
4951*6777b538SAndroid Build Coastguard Worker
4952*6777b538SAndroid Build Coastguard Worker /**
4953*6777b538SAndroid Build Coastguard Worker * xmlXPathConvertNumber:
4954*6777b538SAndroid Build Coastguard Worker * @val: an XPath object
4955*6777b538SAndroid Build Coastguard Worker *
4956*6777b538SAndroid Build Coastguard Worker * Converts an existing object to its number() equivalent
4957*6777b538SAndroid Build Coastguard Worker *
4958*6777b538SAndroid Build Coastguard Worker * Returns the new object, the old one is freed (or the operation
4959*6777b538SAndroid Build Coastguard Worker * is done directly on @val)
4960*6777b538SAndroid Build Coastguard Worker */
4961*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathConvertNumber(xmlXPathObjectPtr val)4962*6777b538SAndroid Build Coastguard Worker xmlXPathConvertNumber(xmlXPathObjectPtr val) {
4963*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
4964*6777b538SAndroid Build Coastguard Worker
4965*6777b538SAndroid Build Coastguard Worker if (val == NULL)
4966*6777b538SAndroid Build Coastguard Worker return(xmlXPathNewFloat(0.0));
4967*6777b538SAndroid Build Coastguard Worker if (val->type == XPATH_NUMBER)
4968*6777b538SAndroid Build Coastguard Worker return(val);
4969*6777b538SAndroid Build Coastguard Worker ret = xmlXPathNewFloat(xmlXPathCastToNumber(val));
4970*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject(val);
4971*6777b538SAndroid Build Coastguard Worker return(ret);
4972*6777b538SAndroid Build Coastguard Worker }
4973*6777b538SAndroid Build Coastguard Worker
4974*6777b538SAndroid Build Coastguard Worker /**
4975*6777b538SAndroid Build Coastguard Worker * xmlXPathCastNumberToBoolean:
4976*6777b538SAndroid Build Coastguard Worker * @val: a number
4977*6777b538SAndroid Build Coastguard Worker *
4978*6777b538SAndroid Build Coastguard Worker * Converts a number to its boolean value
4979*6777b538SAndroid Build Coastguard Worker *
4980*6777b538SAndroid Build Coastguard Worker * Returns the boolean value
4981*6777b538SAndroid Build Coastguard Worker */
4982*6777b538SAndroid Build Coastguard Worker int
xmlXPathCastNumberToBoolean(double val)4983*6777b538SAndroid Build Coastguard Worker xmlXPathCastNumberToBoolean (double val) {
4984*6777b538SAndroid Build Coastguard Worker if (xmlXPathIsNaN(val) || (val == 0.0))
4985*6777b538SAndroid Build Coastguard Worker return(0);
4986*6777b538SAndroid Build Coastguard Worker return(1);
4987*6777b538SAndroid Build Coastguard Worker }
4988*6777b538SAndroid Build Coastguard Worker
4989*6777b538SAndroid Build Coastguard Worker /**
4990*6777b538SAndroid Build Coastguard Worker * xmlXPathCastStringToBoolean:
4991*6777b538SAndroid Build Coastguard Worker * @val: a string
4992*6777b538SAndroid Build Coastguard Worker *
4993*6777b538SAndroid Build Coastguard Worker * Converts a string to its boolean value
4994*6777b538SAndroid Build Coastguard Worker *
4995*6777b538SAndroid Build Coastguard Worker * Returns the boolean value
4996*6777b538SAndroid Build Coastguard Worker */
4997*6777b538SAndroid Build Coastguard Worker int
xmlXPathCastStringToBoolean(const xmlChar * val)4998*6777b538SAndroid Build Coastguard Worker xmlXPathCastStringToBoolean (const xmlChar *val) {
4999*6777b538SAndroid Build Coastguard Worker if ((val == NULL) || (xmlStrlen(val) == 0))
5000*6777b538SAndroid Build Coastguard Worker return(0);
5001*6777b538SAndroid Build Coastguard Worker return(1);
5002*6777b538SAndroid Build Coastguard Worker }
5003*6777b538SAndroid Build Coastguard Worker
5004*6777b538SAndroid Build Coastguard Worker /**
5005*6777b538SAndroid Build Coastguard Worker * xmlXPathCastNodeSetToBoolean:
5006*6777b538SAndroid Build Coastguard Worker * @ns: a node-set
5007*6777b538SAndroid Build Coastguard Worker *
5008*6777b538SAndroid Build Coastguard Worker * Converts a node-set to its boolean value
5009*6777b538SAndroid Build Coastguard Worker *
5010*6777b538SAndroid Build Coastguard Worker * Returns the boolean value
5011*6777b538SAndroid Build Coastguard Worker */
5012*6777b538SAndroid Build Coastguard Worker int
xmlXPathCastNodeSetToBoolean(xmlNodeSetPtr ns)5013*6777b538SAndroid Build Coastguard Worker xmlXPathCastNodeSetToBoolean (xmlNodeSetPtr ns) {
5014*6777b538SAndroid Build Coastguard Worker if ((ns == NULL) || (ns->nodeNr == 0))
5015*6777b538SAndroid Build Coastguard Worker return(0);
5016*6777b538SAndroid Build Coastguard Worker return(1);
5017*6777b538SAndroid Build Coastguard Worker }
5018*6777b538SAndroid Build Coastguard Worker
5019*6777b538SAndroid Build Coastguard Worker /**
5020*6777b538SAndroid Build Coastguard Worker * xmlXPathCastToBoolean:
5021*6777b538SAndroid Build Coastguard Worker * @val: an XPath object
5022*6777b538SAndroid Build Coastguard Worker *
5023*6777b538SAndroid Build Coastguard Worker * Converts an XPath object to its boolean value
5024*6777b538SAndroid Build Coastguard Worker *
5025*6777b538SAndroid Build Coastguard Worker * Returns the boolean value
5026*6777b538SAndroid Build Coastguard Worker */
5027*6777b538SAndroid Build Coastguard Worker int
xmlXPathCastToBoolean(xmlXPathObjectPtr val)5028*6777b538SAndroid Build Coastguard Worker xmlXPathCastToBoolean (xmlXPathObjectPtr val) {
5029*6777b538SAndroid Build Coastguard Worker int ret = 0;
5030*6777b538SAndroid Build Coastguard Worker
5031*6777b538SAndroid Build Coastguard Worker if (val == NULL)
5032*6777b538SAndroid Build Coastguard Worker return(0);
5033*6777b538SAndroid Build Coastguard Worker switch (val->type) {
5034*6777b538SAndroid Build Coastguard Worker case XPATH_UNDEFINED:
5035*6777b538SAndroid Build Coastguard Worker ret = 0;
5036*6777b538SAndroid Build Coastguard Worker break;
5037*6777b538SAndroid Build Coastguard Worker case XPATH_NODESET:
5038*6777b538SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
5039*6777b538SAndroid Build Coastguard Worker ret = xmlXPathCastNodeSetToBoolean(val->nodesetval);
5040*6777b538SAndroid Build Coastguard Worker break;
5041*6777b538SAndroid Build Coastguard Worker case XPATH_STRING:
5042*6777b538SAndroid Build Coastguard Worker ret = xmlXPathCastStringToBoolean(val->stringval);
5043*6777b538SAndroid Build Coastguard Worker break;
5044*6777b538SAndroid Build Coastguard Worker case XPATH_NUMBER:
5045*6777b538SAndroid Build Coastguard Worker ret = xmlXPathCastNumberToBoolean(val->floatval);
5046*6777b538SAndroid Build Coastguard Worker break;
5047*6777b538SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
5048*6777b538SAndroid Build Coastguard Worker ret = val->boolval;
5049*6777b538SAndroid Build Coastguard Worker break;
5050*6777b538SAndroid Build Coastguard Worker case XPATH_USERS:
5051*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
5052*6777b538SAndroid Build Coastguard Worker case XPATH_POINT:
5053*6777b538SAndroid Build Coastguard Worker case XPATH_RANGE:
5054*6777b538SAndroid Build Coastguard Worker case XPATH_LOCATIONSET:
5055*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_XPTR_LOCS_ENABLED */
5056*6777b538SAndroid Build Coastguard Worker /* TODO */
5057*6777b538SAndroid Build Coastguard Worker ret = 0;
5058*6777b538SAndroid Build Coastguard Worker break;
5059*6777b538SAndroid Build Coastguard Worker }
5060*6777b538SAndroid Build Coastguard Worker return(ret);
5061*6777b538SAndroid Build Coastguard Worker }
5062*6777b538SAndroid Build Coastguard Worker
5063*6777b538SAndroid Build Coastguard Worker
5064*6777b538SAndroid Build Coastguard Worker /**
5065*6777b538SAndroid Build Coastguard Worker * xmlXPathConvertBoolean:
5066*6777b538SAndroid Build Coastguard Worker * @val: an XPath object
5067*6777b538SAndroid Build Coastguard Worker *
5068*6777b538SAndroid Build Coastguard Worker * Converts an existing object to its boolean() equivalent
5069*6777b538SAndroid Build Coastguard Worker *
5070*6777b538SAndroid Build Coastguard Worker * Returns the new object, the old one is freed (or the operation
5071*6777b538SAndroid Build Coastguard Worker * is done directly on @val)
5072*6777b538SAndroid Build Coastguard Worker */
5073*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathConvertBoolean(xmlXPathObjectPtr val)5074*6777b538SAndroid Build Coastguard Worker xmlXPathConvertBoolean(xmlXPathObjectPtr val) {
5075*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr ret;
5076*6777b538SAndroid Build Coastguard Worker
5077*6777b538SAndroid Build Coastguard Worker if (val == NULL)
5078*6777b538SAndroid Build Coastguard Worker return(xmlXPathNewBoolean(0));
5079*6777b538SAndroid Build Coastguard Worker if (val->type == XPATH_BOOLEAN)
5080*6777b538SAndroid Build Coastguard Worker return(val);
5081*6777b538SAndroid Build Coastguard Worker ret = xmlXPathNewBoolean(xmlXPathCastToBoolean(val));
5082*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject(val);
5083*6777b538SAndroid Build Coastguard Worker return(ret);
5084*6777b538SAndroid Build Coastguard Worker }
5085*6777b538SAndroid Build Coastguard Worker
5086*6777b538SAndroid Build Coastguard Worker /************************************************************************
5087*6777b538SAndroid Build Coastguard Worker * *
5088*6777b538SAndroid Build Coastguard Worker * Routines to handle XPath contexts *
5089*6777b538SAndroid Build Coastguard Worker * *
5090*6777b538SAndroid Build Coastguard Worker ************************************************************************/
5091*6777b538SAndroid Build Coastguard Worker
5092*6777b538SAndroid Build Coastguard Worker /**
5093*6777b538SAndroid Build Coastguard Worker * xmlXPathNewContext:
5094*6777b538SAndroid Build Coastguard Worker * @doc: the XML document
5095*6777b538SAndroid Build Coastguard Worker *
5096*6777b538SAndroid Build Coastguard Worker * Create a new xmlXPathContext
5097*6777b538SAndroid Build Coastguard Worker *
5098*6777b538SAndroid Build Coastguard Worker * Returns the xmlXPathContext just allocated. The caller will need to free it.
5099*6777b538SAndroid Build Coastguard Worker */
5100*6777b538SAndroid Build Coastguard Worker xmlXPathContextPtr
xmlXPathNewContext(xmlDocPtr doc)5101*6777b538SAndroid Build Coastguard Worker xmlXPathNewContext(xmlDocPtr doc) {
5102*6777b538SAndroid Build Coastguard Worker xmlXPathContextPtr ret;
5103*6777b538SAndroid Build Coastguard Worker
5104*6777b538SAndroid Build Coastguard Worker ret = (xmlXPathContextPtr) xmlMalloc(sizeof(xmlXPathContext));
5105*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
5106*6777b538SAndroid Build Coastguard Worker return(NULL);
5107*6777b538SAndroid Build Coastguard Worker memset(ret, 0 , sizeof(xmlXPathContext));
5108*6777b538SAndroid Build Coastguard Worker ret->doc = doc;
5109*6777b538SAndroid Build Coastguard Worker ret->node = NULL;
5110*6777b538SAndroid Build Coastguard Worker
5111*6777b538SAndroid Build Coastguard Worker ret->varHash = NULL;
5112*6777b538SAndroid Build Coastguard Worker
5113*6777b538SAndroid Build Coastguard Worker ret->nb_types = 0;
5114*6777b538SAndroid Build Coastguard Worker ret->max_types = 0;
5115*6777b538SAndroid Build Coastguard Worker ret->types = NULL;
5116*6777b538SAndroid Build Coastguard Worker
5117*6777b538SAndroid Build Coastguard Worker ret->nb_axis = 0;
5118*6777b538SAndroid Build Coastguard Worker ret->max_axis = 0;
5119*6777b538SAndroid Build Coastguard Worker ret->axis = NULL;
5120*6777b538SAndroid Build Coastguard Worker
5121*6777b538SAndroid Build Coastguard Worker ret->nsHash = NULL;
5122*6777b538SAndroid Build Coastguard Worker ret->user = NULL;
5123*6777b538SAndroid Build Coastguard Worker
5124*6777b538SAndroid Build Coastguard Worker ret->contextSize = -1;
5125*6777b538SAndroid Build Coastguard Worker ret->proximityPosition = -1;
5126*6777b538SAndroid Build Coastguard Worker
5127*6777b538SAndroid Build Coastguard Worker #ifdef XP_DEFAULT_CACHE_ON
5128*6777b538SAndroid Build Coastguard Worker if (xmlXPathContextSetCache(ret, 1, -1, 0) == -1) {
5129*6777b538SAndroid Build Coastguard Worker xmlXPathFreeContext(ret);
5130*6777b538SAndroid Build Coastguard Worker return(NULL);
5131*6777b538SAndroid Build Coastguard Worker }
5132*6777b538SAndroid Build Coastguard Worker #endif
5133*6777b538SAndroid Build Coastguard Worker
5134*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterAllFunctions(ret);
5135*6777b538SAndroid Build Coastguard Worker
5136*6777b538SAndroid Build Coastguard Worker if (ret->lastError.code != XML_ERR_OK) {
5137*6777b538SAndroid Build Coastguard Worker xmlXPathFreeContext(ret);
5138*6777b538SAndroid Build Coastguard Worker return(NULL);
5139*6777b538SAndroid Build Coastguard Worker }
5140*6777b538SAndroid Build Coastguard Worker
5141*6777b538SAndroid Build Coastguard Worker return(ret);
5142*6777b538SAndroid Build Coastguard Worker }
5143*6777b538SAndroid Build Coastguard Worker
5144*6777b538SAndroid Build Coastguard Worker /**
5145*6777b538SAndroid Build Coastguard Worker * xmlXPathFreeContext:
5146*6777b538SAndroid Build Coastguard Worker * @ctxt: the context to free
5147*6777b538SAndroid Build Coastguard Worker *
5148*6777b538SAndroid Build Coastguard Worker * Free up an xmlXPathContext
5149*6777b538SAndroid Build Coastguard Worker */
5150*6777b538SAndroid Build Coastguard Worker void
xmlXPathFreeContext(xmlXPathContextPtr ctxt)5151*6777b538SAndroid Build Coastguard Worker xmlXPathFreeContext(xmlXPathContextPtr ctxt) {
5152*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL) return;
5153*6777b538SAndroid Build Coastguard Worker
5154*6777b538SAndroid Build Coastguard Worker if (ctxt->cache != NULL)
5155*6777b538SAndroid Build Coastguard Worker xmlXPathFreeCache((xmlXPathContextCachePtr) ctxt->cache);
5156*6777b538SAndroid Build Coastguard Worker xmlXPathRegisteredNsCleanup(ctxt);
5157*6777b538SAndroid Build Coastguard Worker xmlXPathRegisteredFuncsCleanup(ctxt);
5158*6777b538SAndroid Build Coastguard Worker xmlXPathRegisteredVariablesCleanup(ctxt);
5159*6777b538SAndroid Build Coastguard Worker xmlResetError(&ctxt->lastError);
5160*6777b538SAndroid Build Coastguard Worker xmlFree(ctxt);
5161*6777b538SAndroid Build Coastguard Worker }
5162*6777b538SAndroid Build Coastguard Worker
5163*6777b538SAndroid Build Coastguard Worker /**
5164*6777b538SAndroid Build Coastguard Worker * xmlXPathSetErrorHandler:
5165*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath context
5166*6777b538SAndroid Build Coastguard Worker * @handler: error handler
5167*6777b538SAndroid Build Coastguard Worker * @data: user data which will be passed to the handler
5168*6777b538SAndroid Build Coastguard Worker *
5169*6777b538SAndroid Build Coastguard Worker * Register a callback function that will be called on errors and
5170*6777b538SAndroid Build Coastguard Worker * warnings. If handler is NULL, the error handler will be deactivated.
5171*6777b538SAndroid Build Coastguard Worker *
5172*6777b538SAndroid Build Coastguard Worker * Available since 2.13.0.
5173*6777b538SAndroid Build Coastguard Worker */
5174*6777b538SAndroid Build Coastguard Worker void
xmlXPathSetErrorHandler(xmlXPathContextPtr ctxt,xmlStructuredErrorFunc handler,void * data)5175*6777b538SAndroid Build Coastguard Worker xmlXPathSetErrorHandler(xmlXPathContextPtr ctxt,
5176*6777b538SAndroid Build Coastguard Worker xmlStructuredErrorFunc handler, void *data) {
5177*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
5178*6777b538SAndroid Build Coastguard Worker return;
5179*6777b538SAndroid Build Coastguard Worker
5180*6777b538SAndroid Build Coastguard Worker ctxt->error = handler;
5181*6777b538SAndroid Build Coastguard Worker ctxt->userData = data;
5182*6777b538SAndroid Build Coastguard Worker }
5183*6777b538SAndroid Build Coastguard Worker
5184*6777b538SAndroid Build Coastguard Worker /************************************************************************
5185*6777b538SAndroid Build Coastguard Worker * *
5186*6777b538SAndroid Build Coastguard Worker * Routines to handle XPath parser contexts *
5187*6777b538SAndroid Build Coastguard Worker * *
5188*6777b538SAndroid Build Coastguard Worker ************************************************************************/
5189*6777b538SAndroid Build Coastguard Worker
5190*6777b538SAndroid Build Coastguard Worker /**
5191*6777b538SAndroid Build Coastguard Worker * xmlXPathNewParserContext:
5192*6777b538SAndroid Build Coastguard Worker * @str: the XPath expression
5193*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath context
5194*6777b538SAndroid Build Coastguard Worker *
5195*6777b538SAndroid Build Coastguard Worker * Create a new xmlXPathParserContext
5196*6777b538SAndroid Build Coastguard Worker *
5197*6777b538SAndroid Build Coastguard Worker * Returns the xmlXPathParserContext just allocated.
5198*6777b538SAndroid Build Coastguard Worker */
5199*6777b538SAndroid Build Coastguard Worker xmlXPathParserContextPtr
xmlXPathNewParserContext(const xmlChar * str,xmlXPathContextPtr ctxt)5200*6777b538SAndroid Build Coastguard Worker xmlXPathNewParserContext(const xmlChar *str, xmlXPathContextPtr ctxt) {
5201*6777b538SAndroid Build Coastguard Worker xmlXPathParserContextPtr ret;
5202*6777b538SAndroid Build Coastguard Worker
5203*6777b538SAndroid Build Coastguard Worker ret = (xmlXPathParserContextPtr) xmlMalloc(sizeof(xmlXPathParserContext));
5204*6777b538SAndroid Build Coastguard Worker if (ret == NULL) {
5205*6777b538SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt);
5206*6777b538SAndroid Build Coastguard Worker return(NULL);
5207*6777b538SAndroid Build Coastguard Worker }
5208*6777b538SAndroid Build Coastguard Worker memset(ret, 0 , sizeof(xmlXPathParserContext));
5209*6777b538SAndroid Build Coastguard Worker ret->cur = ret->base = str;
5210*6777b538SAndroid Build Coastguard Worker ret->context = ctxt;
5211*6777b538SAndroid Build Coastguard Worker
5212*6777b538SAndroid Build Coastguard Worker ret->comp = xmlXPathNewCompExpr();
5213*6777b538SAndroid Build Coastguard Worker if (ret->comp == NULL) {
5214*6777b538SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt);
5215*6777b538SAndroid Build Coastguard Worker xmlFree(ret->valueTab);
5216*6777b538SAndroid Build Coastguard Worker xmlFree(ret);
5217*6777b538SAndroid Build Coastguard Worker return(NULL);
5218*6777b538SAndroid Build Coastguard Worker }
5219*6777b538SAndroid Build Coastguard Worker if ((ctxt != NULL) && (ctxt->dict != NULL)) {
5220*6777b538SAndroid Build Coastguard Worker ret->comp->dict = ctxt->dict;
5221*6777b538SAndroid Build Coastguard Worker xmlDictReference(ret->comp->dict);
5222*6777b538SAndroid Build Coastguard Worker }
5223*6777b538SAndroid Build Coastguard Worker
5224*6777b538SAndroid Build Coastguard Worker return(ret);
5225*6777b538SAndroid Build Coastguard Worker }
5226*6777b538SAndroid Build Coastguard Worker
5227*6777b538SAndroid Build Coastguard Worker /**
5228*6777b538SAndroid Build Coastguard Worker * xmlXPathCompParserContext:
5229*6777b538SAndroid Build Coastguard Worker * @comp: the XPath compiled expression
5230*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath context
5231*6777b538SAndroid Build Coastguard Worker *
5232*6777b538SAndroid Build Coastguard Worker * Create a new xmlXPathParserContext when processing a compiled expression
5233*6777b538SAndroid Build Coastguard Worker *
5234*6777b538SAndroid Build Coastguard Worker * Returns the xmlXPathParserContext just allocated.
5235*6777b538SAndroid Build Coastguard Worker */
5236*6777b538SAndroid Build Coastguard Worker static xmlXPathParserContextPtr
xmlXPathCompParserContext(xmlXPathCompExprPtr comp,xmlXPathContextPtr ctxt)5237*6777b538SAndroid Build Coastguard Worker xmlXPathCompParserContext(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctxt) {
5238*6777b538SAndroid Build Coastguard Worker xmlXPathParserContextPtr ret;
5239*6777b538SAndroid Build Coastguard Worker
5240*6777b538SAndroid Build Coastguard Worker ret = (xmlXPathParserContextPtr) xmlMalloc(sizeof(xmlXPathParserContext));
5241*6777b538SAndroid Build Coastguard Worker if (ret == NULL) {
5242*6777b538SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt);
5243*6777b538SAndroid Build Coastguard Worker return(NULL);
5244*6777b538SAndroid Build Coastguard Worker }
5245*6777b538SAndroid Build Coastguard Worker memset(ret, 0 , sizeof(xmlXPathParserContext));
5246*6777b538SAndroid Build Coastguard Worker
5247*6777b538SAndroid Build Coastguard Worker /* Allocate the value stack */
5248*6777b538SAndroid Build Coastguard Worker ret->valueTab = (xmlXPathObjectPtr *)
5249*6777b538SAndroid Build Coastguard Worker xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
5250*6777b538SAndroid Build Coastguard Worker if (ret->valueTab == NULL) {
5251*6777b538SAndroid Build Coastguard Worker xmlFree(ret);
5252*6777b538SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt);
5253*6777b538SAndroid Build Coastguard Worker return(NULL);
5254*6777b538SAndroid Build Coastguard Worker }
5255*6777b538SAndroid Build Coastguard Worker ret->valueNr = 0;
5256*6777b538SAndroid Build Coastguard Worker ret->valueMax = 10;
5257*6777b538SAndroid Build Coastguard Worker ret->value = NULL;
5258*6777b538SAndroid Build Coastguard Worker
5259*6777b538SAndroid Build Coastguard Worker ret->context = ctxt;
5260*6777b538SAndroid Build Coastguard Worker ret->comp = comp;
5261*6777b538SAndroid Build Coastguard Worker
5262*6777b538SAndroid Build Coastguard Worker return(ret);
5263*6777b538SAndroid Build Coastguard Worker }
5264*6777b538SAndroid Build Coastguard Worker
5265*6777b538SAndroid Build Coastguard Worker /**
5266*6777b538SAndroid Build Coastguard Worker * xmlXPathFreeParserContext:
5267*6777b538SAndroid Build Coastguard Worker * @ctxt: the context to free
5268*6777b538SAndroid Build Coastguard Worker *
5269*6777b538SAndroid Build Coastguard Worker * Free up an xmlXPathParserContext
5270*6777b538SAndroid Build Coastguard Worker */
5271*6777b538SAndroid Build Coastguard Worker void
xmlXPathFreeParserContext(xmlXPathParserContextPtr ctxt)5272*6777b538SAndroid Build Coastguard Worker xmlXPathFreeParserContext(xmlXPathParserContextPtr ctxt) {
5273*6777b538SAndroid Build Coastguard Worker int i;
5274*6777b538SAndroid Build Coastguard Worker
5275*6777b538SAndroid Build Coastguard Worker if (ctxt->valueTab != NULL) {
5276*6777b538SAndroid Build Coastguard Worker for (i = 0; i < ctxt->valueNr; i++) {
5277*6777b538SAndroid Build Coastguard Worker if (ctxt->context)
5278*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, ctxt->valueTab[i]);
5279*6777b538SAndroid Build Coastguard Worker else
5280*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject(ctxt->valueTab[i]);
5281*6777b538SAndroid Build Coastguard Worker }
5282*6777b538SAndroid Build Coastguard Worker xmlFree(ctxt->valueTab);
5283*6777b538SAndroid Build Coastguard Worker }
5284*6777b538SAndroid Build Coastguard Worker if (ctxt->comp != NULL) {
5285*6777b538SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
5286*6777b538SAndroid Build Coastguard Worker if (ctxt->comp->stream != NULL) {
5287*6777b538SAndroid Build Coastguard Worker xmlFreePatternList(ctxt->comp->stream);
5288*6777b538SAndroid Build Coastguard Worker ctxt->comp->stream = NULL;
5289*6777b538SAndroid Build Coastguard Worker }
5290*6777b538SAndroid Build Coastguard Worker #endif
5291*6777b538SAndroid Build Coastguard Worker xmlXPathFreeCompExpr(ctxt->comp);
5292*6777b538SAndroid Build Coastguard Worker }
5293*6777b538SAndroid Build Coastguard Worker xmlFree(ctxt);
5294*6777b538SAndroid Build Coastguard Worker }
5295*6777b538SAndroid Build Coastguard Worker
5296*6777b538SAndroid Build Coastguard Worker /************************************************************************
5297*6777b538SAndroid Build Coastguard Worker * *
5298*6777b538SAndroid Build Coastguard Worker * The implicit core function library *
5299*6777b538SAndroid Build Coastguard Worker * *
5300*6777b538SAndroid Build Coastguard Worker ************************************************************************/
5301*6777b538SAndroid Build Coastguard Worker
5302*6777b538SAndroid Build Coastguard Worker /**
5303*6777b538SAndroid Build Coastguard Worker * xmlXPathNodeValHash:
5304*6777b538SAndroid Build Coastguard Worker * @node: a node pointer
5305*6777b538SAndroid Build Coastguard Worker *
5306*6777b538SAndroid Build Coastguard Worker * Function computing the beginning of the string value of the node,
5307*6777b538SAndroid Build Coastguard Worker * used to speed up comparisons
5308*6777b538SAndroid Build Coastguard Worker *
5309*6777b538SAndroid Build Coastguard Worker * Returns an int usable as a hash
5310*6777b538SAndroid Build Coastguard Worker */
5311*6777b538SAndroid Build Coastguard Worker static unsigned int
xmlXPathNodeValHash(xmlNodePtr node)5312*6777b538SAndroid Build Coastguard Worker xmlXPathNodeValHash(xmlNodePtr node) {
5313*6777b538SAndroid Build Coastguard Worker int len = 2;
5314*6777b538SAndroid Build Coastguard Worker const xmlChar * string = NULL;
5315*6777b538SAndroid Build Coastguard Worker xmlNodePtr tmp = NULL;
5316*6777b538SAndroid Build Coastguard Worker unsigned int ret = 0;
5317*6777b538SAndroid Build Coastguard Worker
5318*6777b538SAndroid Build Coastguard Worker if (node == NULL)
5319*6777b538SAndroid Build Coastguard Worker return(0);
5320*6777b538SAndroid Build Coastguard Worker
5321*6777b538SAndroid Build Coastguard Worker if (node->type == XML_DOCUMENT_NODE) {
5322*6777b538SAndroid Build Coastguard Worker tmp = xmlDocGetRootElement((xmlDocPtr) node);
5323*6777b538SAndroid Build Coastguard Worker if (tmp == NULL)
5324*6777b538SAndroid Build Coastguard Worker node = node->children;
5325*6777b538SAndroid Build Coastguard Worker else
5326*6777b538SAndroid Build Coastguard Worker node = tmp;
5327*6777b538SAndroid Build Coastguard Worker
5328*6777b538SAndroid Build Coastguard Worker if (node == NULL)
5329*6777b538SAndroid Build Coastguard Worker return(0);
5330*6777b538SAndroid Build Coastguard Worker }
5331*6777b538SAndroid Build Coastguard Worker
5332*6777b538SAndroid Build Coastguard Worker switch (node->type) {
5333*6777b538SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
5334*6777b538SAndroid Build Coastguard Worker case XML_PI_NODE:
5335*6777b538SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
5336*6777b538SAndroid Build Coastguard Worker case XML_TEXT_NODE:
5337*6777b538SAndroid Build Coastguard Worker string = node->content;
5338*6777b538SAndroid Build Coastguard Worker if (string == NULL)
5339*6777b538SAndroid Build Coastguard Worker return(0);
5340*6777b538SAndroid Build Coastguard Worker if (string[0] == 0)
5341*6777b538SAndroid Build Coastguard Worker return(0);
5342*6777b538SAndroid Build Coastguard Worker return(string[0] + (string[1] << 8));
5343*6777b538SAndroid Build Coastguard Worker case XML_NAMESPACE_DECL:
5344*6777b538SAndroid Build Coastguard Worker string = ((xmlNsPtr)node)->href;
5345*6777b538SAndroid Build Coastguard Worker if (string == NULL)
5346*6777b538SAndroid Build Coastguard Worker return(0);
5347*6777b538SAndroid Build Coastguard Worker if (string[0] == 0)
5348*6777b538SAndroid Build Coastguard Worker return(0);
5349*6777b538SAndroid Build Coastguard Worker return(string[0] + (string[1] << 8));
5350*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE:
5351*6777b538SAndroid Build Coastguard Worker tmp = ((xmlAttrPtr) node)->children;
5352*6777b538SAndroid Build Coastguard Worker break;
5353*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
5354*6777b538SAndroid Build Coastguard Worker tmp = node->children;
5355*6777b538SAndroid Build Coastguard Worker break;
5356*6777b538SAndroid Build Coastguard Worker default:
5357*6777b538SAndroid Build Coastguard Worker return(0);
5358*6777b538SAndroid Build Coastguard Worker }
5359*6777b538SAndroid Build Coastguard Worker while (tmp != NULL) {
5360*6777b538SAndroid Build Coastguard Worker switch (tmp->type) {
5361*6777b538SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
5362*6777b538SAndroid Build Coastguard Worker case XML_TEXT_NODE:
5363*6777b538SAndroid Build Coastguard Worker string = tmp->content;
5364*6777b538SAndroid Build Coastguard Worker break;
5365*6777b538SAndroid Build Coastguard Worker default:
5366*6777b538SAndroid Build Coastguard Worker string = NULL;
5367*6777b538SAndroid Build Coastguard Worker break;
5368*6777b538SAndroid Build Coastguard Worker }
5369*6777b538SAndroid Build Coastguard Worker if ((string != NULL) && (string[0] != 0)) {
5370*6777b538SAndroid Build Coastguard Worker if (len == 1) {
5371*6777b538SAndroid Build Coastguard Worker return(ret + (string[0] << 8));
5372*6777b538SAndroid Build Coastguard Worker }
5373*6777b538SAndroid Build Coastguard Worker if (string[1] == 0) {
5374*6777b538SAndroid Build Coastguard Worker len = 1;
5375*6777b538SAndroid Build Coastguard Worker ret = string[0];
5376*6777b538SAndroid Build Coastguard Worker } else {
5377*6777b538SAndroid Build Coastguard Worker return(string[0] + (string[1] << 8));
5378*6777b538SAndroid Build Coastguard Worker }
5379*6777b538SAndroid Build Coastguard Worker }
5380*6777b538SAndroid Build Coastguard Worker /*
5381*6777b538SAndroid Build Coastguard Worker * Skip to next node
5382*6777b538SAndroid Build Coastguard Worker */
5383*6777b538SAndroid Build Coastguard Worker if ((tmp->children != NULL) &&
5384*6777b538SAndroid Build Coastguard Worker (tmp->type != XML_DTD_NODE) &&
5385*6777b538SAndroid Build Coastguard Worker (tmp->type != XML_ENTITY_REF_NODE) &&
5386*6777b538SAndroid Build Coastguard Worker (tmp->children->type != XML_ENTITY_DECL)) {
5387*6777b538SAndroid Build Coastguard Worker tmp = tmp->children;
5388*6777b538SAndroid Build Coastguard Worker continue;
5389*6777b538SAndroid Build Coastguard Worker }
5390*6777b538SAndroid Build Coastguard Worker if (tmp == node)
5391*6777b538SAndroid Build Coastguard Worker break;
5392*6777b538SAndroid Build Coastguard Worker
5393*6777b538SAndroid Build Coastguard Worker if (tmp->next != NULL) {
5394*6777b538SAndroid Build Coastguard Worker tmp = tmp->next;
5395*6777b538SAndroid Build Coastguard Worker continue;
5396*6777b538SAndroid Build Coastguard Worker }
5397*6777b538SAndroid Build Coastguard Worker
5398*6777b538SAndroid Build Coastguard Worker do {
5399*6777b538SAndroid Build Coastguard Worker tmp = tmp->parent;
5400*6777b538SAndroid Build Coastguard Worker if (tmp == NULL)
5401*6777b538SAndroid Build Coastguard Worker break;
5402*6777b538SAndroid Build Coastguard Worker if (tmp == node) {
5403*6777b538SAndroid Build Coastguard Worker tmp = NULL;
5404*6777b538SAndroid Build Coastguard Worker break;
5405*6777b538SAndroid Build Coastguard Worker }
5406*6777b538SAndroid Build Coastguard Worker if (tmp->next != NULL) {
5407*6777b538SAndroid Build Coastguard Worker tmp = tmp->next;
5408*6777b538SAndroid Build Coastguard Worker break;
5409*6777b538SAndroid Build Coastguard Worker }
5410*6777b538SAndroid Build Coastguard Worker } while (tmp != NULL);
5411*6777b538SAndroid Build Coastguard Worker }
5412*6777b538SAndroid Build Coastguard Worker return(ret);
5413*6777b538SAndroid Build Coastguard Worker }
5414*6777b538SAndroid Build Coastguard Worker
5415*6777b538SAndroid Build Coastguard Worker /**
5416*6777b538SAndroid Build Coastguard Worker * xmlXPathStringHash:
5417*6777b538SAndroid Build Coastguard Worker * @string: a string
5418*6777b538SAndroid Build Coastguard Worker *
5419*6777b538SAndroid Build Coastguard Worker * Function computing the beginning of the string value of the node,
5420*6777b538SAndroid Build Coastguard Worker * used to speed up comparisons
5421*6777b538SAndroid Build Coastguard Worker *
5422*6777b538SAndroid Build Coastguard Worker * Returns an int usable as a hash
5423*6777b538SAndroid Build Coastguard Worker */
5424*6777b538SAndroid Build Coastguard Worker static unsigned int
xmlXPathStringHash(const xmlChar * string)5425*6777b538SAndroid Build Coastguard Worker xmlXPathStringHash(const xmlChar * string) {
5426*6777b538SAndroid Build Coastguard Worker if (string == NULL)
5427*6777b538SAndroid Build Coastguard Worker return(0);
5428*6777b538SAndroid Build Coastguard Worker if (string[0] == 0)
5429*6777b538SAndroid Build Coastguard Worker return(0);
5430*6777b538SAndroid Build Coastguard Worker return(string[0] + (string[1] << 8));
5431*6777b538SAndroid Build Coastguard Worker }
5432*6777b538SAndroid Build Coastguard Worker
5433*6777b538SAndroid Build Coastguard Worker /**
5434*6777b538SAndroid Build Coastguard Worker * xmlXPathCompareNodeSetFloat:
5435*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
5436*6777b538SAndroid Build Coastguard Worker * @inf: less than (1) or greater than (0)
5437*6777b538SAndroid Build Coastguard Worker * @strict: is the comparison strict
5438*6777b538SAndroid Build Coastguard Worker * @arg: the node set
5439*6777b538SAndroid Build Coastguard Worker * @f: the value
5440*6777b538SAndroid Build Coastguard Worker *
5441*6777b538SAndroid Build Coastguard Worker * Implement the compare operation between a nodeset and a number
5442*6777b538SAndroid Build Coastguard Worker * @ns < @val (1, 1, ...
5443*6777b538SAndroid Build Coastguard Worker * @ns <= @val (1, 0, ...
5444*6777b538SAndroid Build Coastguard Worker * @ns > @val (0, 1, ...
5445*6777b538SAndroid Build Coastguard Worker * @ns >= @val (0, 0, ...
5446*6777b538SAndroid Build Coastguard Worker *
5447*6777b538SAndroid Build Coastguard Worker * If one object to be compared is a node-set and the other is a number,
5448*6777b538SAndroid Build Coastguard Worker * then the comparison will be true if and only if there is a node in the
5449*6777b538SAndroid Build Coastguard Worker * node-set such that the result of performing the comparison on the number
5450*6777b538SAndroid Build Coastguard Worker * to be compared and on the result of converting the string-value of that
5451*6777b538SAndroid Build Coastguard Worker * node to a number using the number function is true.
5452*6777b538SAndroid Build Coastguard Worker *
5453*6777b538SAndroid Build Coastguard Worker * Returns 0 or 1 depending on the results of the test.
5454*6777b538SAndroid Build Coastguard Worker */
5455*6777b538SAndroid Build Coastguard Worker static int
xmlXPathCompareNodeSetFloat(xmlXPathParserContextPtr ctxt,int inf,int strict,xmlXPathObjectPtr arg,xmlXPathObjectPtr f)5456*6777b538SAndroid Build Coastguard Worker xmlXPathCompareNodeSetFloat(xmlXPathParserContextPtr ctxt, int inf, int strict,
5457*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr arg, xmlXPathObjectPtr f) {
5458*6777b538SAndroid Build Coastguard Worker int i, ret = 0;
5459*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr ns;
5460*6777b538SAndroid Build Coastguard Worker xmlChar *str2;
5461*6777b538SAndroid Build Coastguard Worker
5462*6777b538SAndroid Build Coastguard Worker if ((f == NULL) || (arg == NULL) ||
5463*6777b538SAndroid Build Coastguard Worker ((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE))) {
5464*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg);
5465*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, f);
5466*6777b538SAndroid Build Coastguard Worker return(0);
5467*6777b538SAndroid Build Coastguard Worker }
5468*6777b538SAndroid Build Coastguard Worker ns = arg->nodesetval;
5469*6777b538SAndroid Build Coastguard Worker if (ns != NULL) {
5470*6777b538SAndroid Build Coastguard Worker for (i = 0;i < ns->nodeNr;i++) {
5471*6777b538SAndroid Build Coastguard Worker str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
5472*6777b538SAndroid Build Coastguard Worker if (str2 != NULL) {
5473*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewString(ctxt, str2));
5474*6777b538SAndroid Build Coastguard Worker xmlFree(str2);
5475*6777b538SAndroid Build Coastguard Worker xmlXPathNumberFunction(ctxt, 1);
5476*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt, f));
5477*6777b538SAndroid Build Coastguard Worker ret = xmlXPathCompareValues(ctxt, inf, strict);
5478*6777b538SAndroid Build Coastguard Worker if (ret)
5479*6777b538SAndroid Build Coastguard Worker break;
5480*6777b538SAndroid Build Coastguard Worker } else {
5481*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
5482*6777b538SAndroid Build Coastguard Worker }
5483*6777b538SAndroid Build Coastguard Worker }
5484*6777b538SAndroid Build Coastguard Worker }
5485*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg);
5486*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, f);
5487*6777b538SAndroid Build Coastguard Worker return(ret);
5488*6777b538SAndroid Build Coastguard Worker }
5489*6777b538SAndroid Build Coastguard Worker
5490*6777b538SAndroid Build Coastguard Worker /**
5491*6777b538SAndroid Build Coastguard Worker * xmlXPathCompareNodeSetString:
5492*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
5493*6777b538SAndroid Build Coastguard Worker * @inf: less than (1) or greater than (0)
5494*6777b538SAndroid Build Coastguard Worker * @strict: is the comparison strict
5495*6777b538SAndroid Build Coastguard Worker * @arg: the node set
5496*6777b538SAndroid Build Coastguard Worker * @s: the value
5497*6777b538SAndroid Build Coastguard Worker *
5498*6777b538SAndroid Build Coastguard Worker * Implement the compare operation between a nodeset and a string
5499*6777b538SAndroid Build Coastguard Worker * @ns < @val (1, 1, ...
5500*6777b538SAndroid Build Coastguard Worker * @ns <= @val (1, 0, ...
5501*6777b538SAndroid Build Coastguard Worker * @ns > @val (0, 1, ...
5502*6777b538SAndroid Build Coastguard Worker * @ns >= @val (0, 0, ...
5503*6777b538SAndroid Build Coastguard Worker *
5504*6777b538SAndroid Build Coastguard Worker * If one object to be compared is a node-set and the other is a string,
5505*6777b538SAndroid Build Coastguard Worker * then the comparison will be true if and only if there is a node in
5506*6777b538SAndroid Build Coastguard Worker * the node-set such that the result of performing the comparison on the
5507*6777b538SAndroid Build Coastguard Worker * string-value of the node and the other string is true.
5508*6777b538SAndroid Build Coastguard Worker *
5509*6777b538SAndroid Build Coastguard Worker * Returns 0 or 1 depending on the results of the test.
5510*6777b538SAndroid Build Coastguard Worker */
5511*6777b538SAndroid Build Coastguard Worker static int
xmlXPathCompareNodeSetString(xmlXPathParserContextPtr ctxt,int inf,int strict,xmlXPathObjectPtr arg,xmlXPathObjectPtr s)5512*6777b538SAndroid Build Coastguard Worker xmlXPathCompareNodeSetString(xmlXPathParserContextPtr ctxt, int inf, int strict,
5513*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr arg, xmlXPathObjectPtr s) {
5514*6777b538SAndroid Build Coastguard Worker int i, ret = 0;
5515*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr ns;
5516*6777b538SAndroid Build Coastguard Worker xmlChar *str2;
5517*6777b538SAndroid Build Coastguard Worker
5518*6777b538SAndroid Build Coastguard Worker if ((s == NULL) || (arg == NULL) ||
5519*6777b538SAndroid Build Coastguard Worker ((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE))) {
5520*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg);
5521*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, s);
5522*6777b538SAndroid Build Coastguard Worker return(0);
5523*6777b538SAndroid Build Coastguard Worker }
5524*6777b538SAndroid Build Coastguard Worker ns = arg->nodesetval;
5525*6777b538SAndroid Build Coastguard Worker if (ns != NULL) {
5526*6777b538SAndroid Build Coastguard Worker for (i = 0;i < ns->nodeNr;i++) {
5527*6777b538SAndroid Build Coastguard Worker str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
5528*6777b538SAndroid Build Coastguard Worker if (str2 != NULL) {
5529*6777b538SAndroid Build Coastguard Worker valuePush(ctxt,
5530*6777b538SAndroid Build Coastguard Worker xmlXPathCacheNewString(ctxt, str2));
5531*6777b538SAndroid Build Coastguard Worker xmlFree(str2);
5532*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt, s));
5533*6777b538SAndroid Build Coastguard Worker ret = xmlXPathCompareValues(ctxt, inf, strict);
5534*6777b538SAndroid Build Coastguard Worker if (ret)
5535*6777b538SAndroid Build Coastguard Worker break;
5536*6777b538SAndroid Build Coastguard Worker } else {
5537*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
5538*6777b538SAndroid Build Coastguard Worker }
5539*6777b538SAndroid Build Coastguard Worker }
5540*6777b538SAndroid Build Coastguard Worker }
5541*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg);
5542*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, s);
5543*6777b538SAndroid Build Coastguard Worker return(ret);
5544*6777b538SAndroid Build Coastguard Worker }
5545*6777b538SAndroid Build Coastguard Worker
5546*6777b538SAndroid Build Coastguard Worker /**
5547*6777b538SAndroid Build Coastguard Worker * xmlXPathCompareNodeSets:
5548*6777b538SAndroid Build Coastguard Worker * @inf: less than (1) or greater than (0)
5549*6777b538SAndroid Build Coastguard Worker * @strict: is the comparison strict
5550*6777b538SAndroid Build Coastguard Worker * @arg1: the first node set object
5551*6777b538SAndroid Build Coastguard Worker * @arg2: the second node set object
5552*6777b538SAndroid Build Coastguard Worker *
5553*6777b538SAndroid Build Coastguard Worker * Implement the compare operation on nodesets:
5554*6777b538SAndroid Build Coastguard Worker *
5555*6777b538SAndroid Build Coastguard Worker * If both objects to be compared are node-sets, then the comparison
5556*6777b538SAndroid Build Coastguard Worker * will be true if and only if there is a node in the first node-set
5557*6777b538SAndroid Build Coastguard Worker * and a node in the second node-set such that the result of performing
5558*6777b538SAndroid Build Coastguard Worker * the comparison on the string-values of the two nodes is true.
5559*6777b538SAndroid Build Coastguard Worker * ....
5560*6777b538SAndroid Build Coastguard Worker * When neither object to be compared is a node-set and the operator
5561*6777b538SAndroid Build Coastguard Worker * is <=, <, >= or >, then the objects are compared by converting both
5562*6777b538SAndroid Build Coastguard Worker * objects to numbers and comparing the numbers according to IEEE 754.
5563*6777b538SAndroid Build Coastguard Worker * ....
5564*6777b538SAndroid Build Coastguard Worker * The number function converts its argument to a number as follows:
5565*6777b538SAndroid Build Coastguard Worker * - a string that consists of optional whitespace followed by an
5566*6777b538SAndroid Build Coastguard Worker * optional minus sign followed by a Number followed by whitespace
5567*6777b538SAndroid Build Coastguard Worker * is converted to the IEEE 754 number that is nearest (according
5568*6777b538SAndroid Build Coastguard Worker * to the IEEE 754 round-to-nearest rule) to the mathematical value
5569*6777b538SAndroid Build Coastguard Worker * represented by the string; any other string is converted to NaN
5570*6777b538SAndroid Build Coastguard Worker *
5571*6777b538SAndroid Build Coastguard Worker * Conclusion all nodes need to be converted first to their string value
5572*6777b538SAndroid Build Coastguard Worker * and then the comparison must be done when possible
5573*6777b538SAndroid Build Coastguard Worker */
5574*6777b538SAndroid Build Coastguard Worker static int
xmlXPathCompareNodeSets(xmlXPathParserContextPtr ctxt,int inf,int strict,xmlXPathObjectPtr arg1,xmlXPathObjectPtr arg2)5575*6777b538SAndroid Build Coastguard Worker xmlXPathCompareNodeSets(xmlXPathParserContextPtr ctxt, int inf, int strict,
5576*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2) {
5577*6777b538SAndroid Build Coastguard Worker int i, j, init = 0;
5578*6777b538SAndroid Build Coastguard Worker double val1;
5579*6777b538SAndroid Build Coastguard Worker double *values2;
5580*6777b538SAndroid Build Coastguard Worker int ret = 0;
5581*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr ns1;
5582*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr ns2;
5583*6777b538SAndroid Build Coastguard Worker
5584*6777b538SAndroid Build Coastguard Worker if ((arg1 == NULL) ||
5585*6777b538SAndroid Build Coastguard Worker ((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE))) {
5586*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject(arg2);
5587*6777b538SAndroid Build Coastguard Worker return(0);
5588*6777b538SAndroid Build Coastguard Worker }
5589*6777b538SAndroid Build Coastguard Worker if ((arg2 == NULL) ||
5590*6777b538SAndroid Build Coastguard Worker ((arg2->type != XPATH_NODESET) && (arg2->type != XPATH_XSLT_TREE))) {
5591*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject(arg1);
5592*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject(arg2);
5593*6777b538SAndroid Build Coastguard Worker return(0);
5594*6777b538SAndroid Build Coastguard Worker }
5595*6777b538SAndroid Build Coastguard Worker
5596*6777b538SAndroid Build Coastguard Worker ns1 = arg1->nodesetval;
5597*6777b538SAndroid Build Coastguard Worker ns2 = arg2->nodesetval;
5598*6777b538SAndroid Build Coastguard Worker
5599*6777b538SAndroid Build Coastguard Worker if ((ns1 == NULL) || (ns1->nodeNr <= 0)) {
5600*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject(arg1);
5601*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject(arg2);
5602*6777b538SAndroid Build Coastguard Worker return(0);
5603*6777b538SAndroid Build Coastguard Worker }
5604*6777b538SAndroid Build Coastguard Worker if ((ns2 == NULL) || (ns2->nodeNr <= 0)) {
5605*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject(arg1);
5606*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject(arg2);
5607*6777b538SAndroid Build Coastguard Worker return(0);
5608*6777b538SAndroid Build Coastguard Worker }
5609*6777b538SAndroid Build Coastguard Worker
5610*6777b538SAndroid Build Coastguard Worker values2 = (double *) xmlMalloc(ns2->nodeNr * sizeof(double));
5611*6777b538SAndroid Build Coastguard Worker if (values2 == NULL) {
5612*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
5613*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject(arg1);
5614*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject(arg2);
5615*6777b538SAndroid Build Coastguard Worker return(0);
5616*6777b538SAndroid Build Coastguard Worker }
5617*6777b538SAndroid Build Coastguard Worker for (i = 0;i < ns1->nodeNr;i++) {
5618*6777b538SAndroid Build Coastguard Worker val1 = xmlXPathNodeToNumberInternal(ctxt, ns1->nodeTab[i]);
5619*6777b538SAndroid Build Coastguard Worker if (xmlXPathIsNaN(val1))
5620*6777b538SAndroid Build Coastguard Worker continue;
5621*6777b538SAndroid Build Coastguard Worker for (j = 0;j < ns2->nodeNr;j++) {
5622*6777b538SAndroid Build Coastguard Worker if (init == 0) {
5623*6777b538SAndroid Build Coastguard Worker values2[j] = xmlXPathNodeToNumberInternal(ctxt,
5624*6777b538SAndroid Build Coastguard Worker ns2->nodeTab[j]);
5625*6777b538SAndroid Build Coastguard Worker }
5626*6777b538SAndroid Build Coastguard Worker if (xmlXPathIsNaN(values2[j]))
5627*6777b538SAndroid Build Coastguard Worker continue;
5628*6777b538SAndroid Build Coastguard Worker if (inf && strict)
5629*6777b538SAndroid Build Coastguard Worker ret = (val1 < values2[j]);
5630*6777b538SAndroid Build Coastguard Worker else if (inf && !strict)
5631*6777b538SAndroid Build Coastguard Worker ret = (val1 <= values2[j]);
5632*6777b538SAndroid Build Coastguard Worker else if (!inf && strict)
5633*6777b538SAndroid Build Coastguard Worker ret = (val1 > values2[j]);
5634*6777b538SAndroid Build Coastguard Worker else if (!inf && !strict)
5635*6777b538SAndroid Build Coastguard Worker ret = (val1 >= values2[j]);
5636*6777b538SAndroid Build Coastguard Worker if (ret)
5637*6777b538SAndroid Build Coastguard Worker break;
5638*6777b538SAndroid Build Coastguard Worker }
5639*6777b538SAndroid Build Coastguard Worker if (ret)
5640*6777b538SAndroid Build Coastguard Worker break;
5641*6777b538SAndroid Build Coastguard Worker init = 1;
5642*6777b538SAndroid Build Coastguard Worker }
5643*6777b538SAndroid Build Coastguard Worker xmlFree(values2);
5644*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject(arg1);
5645*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject(arg2);
5646*6777b538SAndroid Build Coastguard Worker return(ret);
5647*6777b538SAndroid Build Coastguard Worker }
5648*6777b538SAndroid Build Coastguard Worker
5649*6777b538SAndroid Build Coastguard Worker /**
5650*6777b538SAndroid Build Coastguard Worker * xmlXPathCompareNodeSetValue:
5651*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
5652*6777b538SAndroid Build Coastguard Worker * @inf: less than (1) or greater than (0)
5653*6777b538SAndroid Build Coastguard Worker * @strict: is the comparison strict
5654*6777b538SAndroid Build Coastguard Worker * @arg: the node set
5655*6777b538SAndroid Build Coastguard Worker * @val: the value
5656*6777b538SAndroid Build Coastguard Worker *
5657*6777b538SAndroid Build Coastguard Worker * Implement the compare operation between a nodeset and a value
5658*6777b538SAndroid Build Coastguard Worker * @ns < @val (1, 1, ...
5659*6777b538SAndroid Build Coastguard Worker * @ns <= @val (1, 0, ...
5660*6777b538SAndroid Build Coastguard Worker * @ns > @val (0, 1, ...
5661*6777b538SAndroid Build Coastguard Worker * @ns >= @val (0, 0, ...
5662*6777b538SAndroid Build Coastguard Worker *
5663*6777b538SAndroid Build Coastguard Worker * If one object to be compared is a node-set and the other is a boolean,
5664*6777b538SAndroid Build Coastguard Worker * then the comparison will be true if and only if the result of performing
5665*6777b538SAndroid Build Coastguard Worker * the comparison on the boolean and on the result of converting
5666*6777b538SAndroid Build Coastguard Worker * the node-set to a boolean using the boolean function is true.
5667*6777b538SAndroid Build Coastguard Worker *
5668*6777b538SAndroid Build Coastguard Worker * Returns 0 or 1 depending on the results of the test.
5669*6777b538SAndroid Build Coastguard Worker */
5670*6777b538SAndroid Build Coastguard Worker static int
xmlXPathCompareNodeSetValue(xmlXPathParserContextPtr ctxt,int inf,int strict,xmlXPathObjectPtr arg,xmlXPathObjectPtr val)5671*6777b538SAndroid Build Coastguard Worker xmlXPathCompareNodeSetValue(xmlXPathParserContextPtr ctxt, int inf, int strict,
5672*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr arg, xmlXPathObjectPtr val) {
5673*6777b538SAndroid Build Coastguard Worker if ((val == NULL) || (arg == NULL) ||
5674*6777b538SAndroid Build Coastguard Worker ((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE)))
5675*6777b538SAndroid Build Coastguard Worker return(0);
5676*6777b538SAndroid Build Coastguard Worker
5677*6777b538SAndroid Build Coastguard Worker switch(val->type) {
5678*6777b538SAndroid Build Coastguard Worker case XPATH_NUMBER:
5679*6777b538SAndroid Build Coastguard Worker return(xmlXPathCompareNodeSetFloat(ctxt, inf, strict, arg, val));
5680*6777b538SAndroid Build Coastguard Worker case XPATH_NODESET:
5681*6777b538SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
5682*6777b538SAndroid Build Coastguard Worker return(xmlXPathCompareNodeSets(ctxt, inf, strict, arg, val));
5683*6777b538SAndroid Build Coastguard Worker case XPATH_STRING:
5684*6777b538SAndroid Build Coastguard Worker return(xmlXPathCompareNodeSetString(ctxt, inf, strict, arg, val));
5685*6777b538SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
5686*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, arg);
5687*6777b538SAndroid Build Coastguard Worker xmlXPathBooleanFunction(ctxt, 1);
5688*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, val);
5689*6777b538SAndroid Build Coastguard Worker return(xmlXPathCompareValues(ctxt, inf, strict));
5690*6777b538SAndroid Build Coastguard Worker default:
5691*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg);
5692*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, val);
5693*6777b538SAndroid Build Coastguard Worker XP_ERROR0(XPATH_INVALID_TYPE);
5694*6777b538SAndroid Build Coastguard Worker }
5695*6777b538SAndroid Build Coastguard Worker return(0);
5696*6777b538SAndroid Build Coastguard Worker }
5697*6777b538SAndroid Build Coastguard Worker
5698*6777b538SAndroid Build Coastguard Worker /**
5699*6777b538SAndroid Build Coastguard Worker * xmlXPathEqualNodeSetString:
5700*6777b538SAndroid Build Coastguard Worker * @arg: the nodeset object argument
5701*6777b538SAndroid Build Coastguard Worker * @str: the string to compare to.
5702*6777b538SAndroid Build Coastguard Worker * @neq: flag to show whether for '=' (0) or '!=' (1)
5703*6777b538SAndroid Build Coastguard Worker *
5704*6777b538SAndroid Build Coastguard Worker * Implement the equal operation on XPath objects content: @arg1 == @arg2
5705*6777b538SAndroid Build Coastguard Worker * If one object to be compared is a node-set and the other is a string,
5706*6777b538SAndroid Build Coastguard Worker * then the comparison will be true if and only if there is a node in
5707*6777b538SAndroid Build Coastguard Worker * the node-set such that the result of performing the comparison on the
5708*6777b538SAndroid Build Coastguard Worker * string-value of the node and the other string is true.
5709*6777b538SAndroid Build Coastguard Worker *
5710*6777b538SAndroid Build Coastguard Worker * Returns 0 or 1 depending on the results of the test.
5711*6777b538SAndroid Build Coastguard Worker */
5712*6777b538SAndroid Build Coastguard Worker static int
xmlXPathEqualNodeSetString(xmlXPathParserContextPtr ctxt,xmlXPathObjectPtr arg,const xmlChar * str,int neq)5713*6777b538SAndroid Build Coastguard Worker xmlXPathEqualNodeSetString(xmlXPathParserContextPtr ctxt,
5714*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr arg, const xmlChar * str, int neq)
5715*6777b538SAndroid Build Coastguard Worker {
5716*6777b538SAndroid Build Coastguard Worker int i;
5717*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr ns;
5718*6777b538SAndroid Build Coastguard Worker xmlChar *str2;
5719*6777b538SAndroid Build Coastguard Worker unsigned int hash;
5720*6777b538SAndroid Build Coastguard Worker
5721*6777b538SAndroid Build Coastguard Worker if ((str == NULL) || (arg == NULL) ||
5722*6777b538SAndroid Build Coastguard Worker ((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE)))
5723*6777b538SAndroid Build Coastguard Worker return (0);
5724*6777b538SAndroid Build Coastguard Worker ns = arg->nodesetval;
5725*6777b538SAndroid Build Coastguard Worker /*
5726*6777b538SAndroid Build Coastguard Worker * A NULL nodeset compared with a string is always false
5727*6777b538SAndroid Build Coastguard Worker * (since there is no node equal, and no node not equal)
5728*6777b538SAndroid Build Coastguard Worker */
5729*6777b538SAndroid Build Coastguard Worker if ((ns == NULL) || (ns->nodeNr <= 0) )
5730*6777b538SAndroid Build Coastguard Worker return (0);
5731*6777b538SAndroid Build Coastguard Worker hash = xmlXPathStringHash(str);
5732*6777b538SAndroid Build Coastguard Worker for (i = 0; i < ns->nodeNr; i++) {
5733*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeValHash(ns->nodeTab[i]) == hash) {
5734*6777b538SAndroid Build Coastguard Worker str2 = xmlNodeGetContent(ns->nodeTab[i]);
5735*6777b538SAndroid Build Coastguard Worker if (str2 == NULL) {
5736*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
5737*6777b538SAndroid Build Coastguard Worker return(0);
5738*6777b538SAndroid Build Coastguard Worker }
5739*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(str, str2)) {
5740*6777b538SAndroid Build Coastguard Worker xmlFree(str2);
5741*6777b538SAndroid Build Coastguard Worker if (neq)
5742*6777b538SAndroid Build Coastguard Worker continue;
5743*6777b538SAndroid Build Coastguard Worker return (1);
5744*6777b538SAndroid Build Coastguard Worker } else if (neq) {
5745*6777b538SAndroid Build Coastguard Worker xmlFree(str2);
5746*6777b538SAndroid Build Coastguard Worker return (1);
5747*6777b538SAndroid Build Coastguard Worker }
5748*6777b538SAndroid Build Coastguard Worker xmlFree(str2);
5749*6777b538SAndroid Build Coastguard Worker } else if (neq)
5750*6777b538SAndroid Build Coastguard Worker return (1);
5751*6777b538SAndroid Build Coastguard Worker }
5752*6777b538SAndroid Build Coastguard Worker return (0);
5753*6777b538SAndroid Build Coastguard Worker }
5754*6777b538SAndroid Build Coastguard Worker
5755*6777b538SAndroid Build Coastguard Worker /**
5756*6777b538SAndroid Build Coastguard Worker * xmlXPathEqualNodeSetFloat:
5757*6777b538SAndroid Build Coastguard Worker * @arg: the nodeset object argument
5758*6777b538SAndroid Build Coastguard Worker * @f: the float to compare to
5759*6777b538SAndroid Build Coastguard Worker * @neq: flag to show whether to compare '=' (0) or '!=' (1)
5760*6777b538SAndroid Build Coastguard Worker *
5761*6777b538SAndroid Build Coastguard Worker * Implement the equal operation on XPath objects content: @arg1 == @arg2
5762*6777b538SAndroid Build Coastguard Worker * If one object to be compared is a node-set and the other is a number,
5763*6777b538SAndroid Build Coastguard Worker * then the comparison will be true if and only if there is a node in
5764*6777b538SAndroid Build Coastguard Worker * the node-set such that the result of performing the comparison on the
5765*6777b538SAndroid Build Coastguard Worker * number to be compared and on the result of converting the string-value
5766*6777b538SAndroid Build Coastguard Worker * of that node to a number using the number function is true.
5767*6777b538SAndroid Build Coastguard Worker *
5768*6777b538SAndroid Build Coastguard Worker * Returns 0 or 1 depending on the results of the test.
5769*6777b538SAndroid Build Coastguard Worker */
5770*6777b538SAndroid Build Coastguard Worker static int
xmlXPathEqualNodeSetFloat(xmlXPathParserContextPtr ctxt,xmlXPathObjectPtr arg,double f,int neq)5771*6777b538SAndroid Build Coastguard Worker xmlXPathEqualNodeSetFloat(xmlXPathParserContextPtr ctxt,
5772*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr arg, double f, int neq) {
5773*6777b538SAndroid Build Coastguard Worker int i, ret=0;
5774*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr ns;
5775*6777b538SAndroid Build Coastguard Worker xmlChar *str2;
5776*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr val;
5777*6777b538SAndroid Build Coastguard Worker double v;
5778*6777b538SAndroid Build Coastguard Worker
5779*6777b538SAndroid Build Coastguard Worker if ((arg == NULL) ||
5780*6777b538SAndroid Build Coastguard Worker ((arg->type != XPATH_NODESET) && (arg->type != XPATH_XSLT_TREE)))
5781*6777b538SAndroid Build Coastguard Worker return(0);
5782*6777b538SAndroid Build Coastguard Worker
5783*6777b538SAndroid Build Coastguard Worker ns = arg->nodesetval;
5784*6777b538SAndroid Build Coastguard Worker if (ns != NULL) {
5785*6777b538SAndroid Build Coastguard Worker for (i=0;i<ns->nodeNr;i++) {
5786*6777b538SAndroid Build Coastguard Worker str2 = xmlXPathCastNodeToString(ns->nodeTab[i]);
5787*6777b538SAndroid Build Coastguard Worker if (str2 != NULL) {
5788*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewString(ctxt, str2));
5789*6777b538SAndroid Build Coastguard Worker xmlFree(str2);
5790*6777b538SAndroid Build Coastguard Worker xmlXPathNumberFunction(ctxt, 1);
5791*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
5792*6777b538SAndroid Build Coastguard Worker val = valuePop(ctxt);
5793*6777b538SAndroid Build Coastguard Worker v = val->floatval;
5794*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, val);
5795*6777b538SAndroid Build Coastguard Worker if (!xmlXPathIsNaN(v)) {
5796*6777b538SAndroid Build Coastguard Worker if ((!neq) && (v==f)) {
5797*6777b538SAndroid Build Coastguard Worker ret = 1;
5798*6777b538SAndroid Build Coastguard Worker break;
5799*6777b538SAndroid Build Coastguard Worker } else if ((neq) && (v!=f)) {
5800*6777b538SAndroid Build Coastguard Worker ret = 1;
5801*6777b538SAndroid Build Coastguard Worker break;
5802*6777b538SAndroid Build Coastguard Worker }
5803*6777b538SAndroid Build Coastguard Worker } else { /* NaN is unequal to any value */
5804*6777b538SAndroid Build Coastguard Worker if (neq)
5805*6777b538SAndroid Build Coastguard Worker ret = 1;
5806*6777b538SAndroid Build Coastguard Worker }
5807*6777b538SAndroid Build Coastguard Worker } else {
5808*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
5809*6777b538SAndroid Build Coastguard Worker }
5810*6777b538SAndroid Build Coastguard Worker }
5811*6777b538SAndroid Build Coastguard Worker }
5812*6777b538SAndroid Build Coastguard Worker
5813*6777b538SAndroid Build Coastguard Worker return(ret);
5814*6777b538SAndroid Build Coastguard Worker }
5815*6777b538SAndroid Build Coastguard Worker
5816*6777b538SAndroid Build Coastguard Worker
5817*6777b538SAndroid Build Coastguard Worker /**
5818*6777b538SAndroid Build Coastguard Worker * xmlXPathEqualNodeSets:
5819*6777b538SAndroid Build Coastguard Worker * @arg1: first nodeset object argument
5820*6777b538SAndroid Build Coastguard Worker * @arg2: second nodeset object argument
5821*6777b538SAndroid Build Coastguard Worker * @neq: flag to show whether to test '=' (0) or '!=' (1)
5822*6777b538SAndroid Build Coastguard Worker *
5823*6777b538SAndroid Build Coastguard Worker * Implement the equal / not equal operation on XPath nodesets:
5824*6777b538SAndroid Build Coastguard Worker * @arg1 == @arg2 or @arg1 != @arg2
5825*6777b538SAndroid Build Coastguard Worker * If both objects to be compared are node-sets, then the comparison
5826*6777b538SAndroid Build Coastguard Worker * will be true if and only if there is a node in the first node-set and
5827*6777b538SAndroid Build Coastguard Worker * a node in the second node-set such that the result of performing the
5828*6777b538SAndroid Build Coastguard Worker * comparison on the string-values of the two nodes is true.
5829*6777b538SAndroid Build Coastguard Worker *
5830*6777b538SAndroid Build Coastguard Worker * (needless to say, this is a costly operation)
5831*6777b538SAndroid Build Coastguard Worker *
5832*6777b538SAndroid Build Coastguard Worker * Returns 0 or 1 depending on the results of the test.
5833*6777b538SAndroid Build Coastguard Worker */
5834*6777b538SAndroid Build Coastguard Worker static int
xmlXPathEqualNodeSets(xmlXPathParserContextPtr ctxt,xmlXPathObjectPtr arg1,xmlXPathObjectPtr arg2,int neq)5835*6777b538SAndroid Build Coastguard Worker xmlXPathEqualNodeSets(xmlXPathParserContextPtr ctxt, xmlXPathObjectPtr arg1,
5836*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr arg2, int neq) {
5837*6777b538SAndroid Build Coastguard Worker int i, j;
5838*6777b538SAndroid Build Coastguard Worker unsigned int *hashs1;
5839*6777b538SAndroid Build Coastguard Worker unsigned int *hashs2;
5840*6777b538SAndroid Build Coastguard Worker xmlChar **values1;
5841*6777b538SAndroid Build Coastguard Worker xmlChar **values2;
5842*6777b538SAndroid Build Coastguard Worker int ret = 0;
5843*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr ns1;
5844*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr ns2;
5845*6777b538SAndroid Build Coastguard Worker
5846*6777b538SAndroid Build Coastguard Worker if ((arg1 == NULL) ||
5847*6777b538SAndroid Build Coastguard Worker ((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE)))
5848*6777b538SAndroid Build Coastguard Worker return(0);
5849*6777b538SAndroid Build Coastguard Worker if ((arg2 == NULL) ||
5850*6777b538SAndroid Build Coastguard Worker ((arg2->type != XPATH_NODESET) && (arg2->type != XPATH_XSLT_TREE)))
5851*6777b538SAndroid Build Coastguard Worker return(0);
5852*6777b538SAndroid Build Coastguard Worker
5853*6777b538SAndroid Build Coastguard Worker ns1 = arg1->nodesetval;
5854*6777b538SAndroid Build Coastguard Worker ns2 = arg2->nodesetval;
5855*6777b538SAndroid Build Coastguard Worker
5856*6777b538SAndroid Build Coastguard Worker if ((ns1 == NULL) || (ns1->nodeNr <= 0))
5857*6777b538SAndroid Build Coastguard Worker return(0);
5858*6777b538SAndroid Build Coastguard Worker if ((ns2 == NULL) || (ns2->nodeNr <= 0))
5859*6777b538SAndroid Build Coastguard Worker return(0);
5860*6777b538SAndroid Build Coastguard Worker
5861*6777b538SAndroid Build Coastguard Worker /*
5862*6777b538SAndroid Build Coastguard Worker * for equal, check if there is a node pertaining to both sets
5863*6777b538SAndroid Build Coastguard Worker */
5864*6777b538SAndroid Build Coastguard Worker if (neq == 0)
5865*6777b538SAndroid Build Coastguard Worker for (i = 0;i < ns1->nodeNr;i++)
5866*6777b538SAndroid Build Coastguard Worker for (j = 0;j < ns2->nodeNr;j++)
5867*6777b538SAndroid Build Coastguard Worker if (ns1->nodeTab[i] == ns2->nodeTab[j])
5868*6777b538SAndroid Build Coastguard Worker return(1);
5869*6777b538SAndroid Build Coastguard Worker
5870*6777b538SAndroid Build Coastguard Worker values1 = (xmlChar **) xmlMalloc(ns1->nodeNr * sizeof(xmlChar *));
5871*6777b538SAndroid Build Coastguard Worker if (values1 == NULL) {
5872*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
5873*6777b538SAndroid Build Coastguard Worker return(0);
5874*6777b538SAndroid Build Coastguard Worker }
5875*6777b538SAndroid Build Coastguard Worker hashs1 = (unsigned int *) xmlMalloc(ns1->nodeNr * sizeof(unsigned int));
5876*6777b538SAndroid Build Coastguard Worker if (hashs1 == NULL) {
5877*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
5878*6777b538SAndroid Build Coastguard Worker xmlFree(values1);
5879*6777b538SAndroid Build Coastguard Worker return(0);
5880*6777b538SAndroid Build Coastguard Worker }
5881*6777b538SAndroid Build Coastguard Worker memset(values1, 0, ns1->nodeNr * sizeof(xmlChar *));
5882*6777b538SAndroid Build Coastguard Worker values2 = (xmlChar **) xmlMalloc(ns2->nodeNr * sizeof(xmlChar *));
5883*6777b538SAndroid Build Coastguard Worker if (values2 == NULL) {
5884*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
5885*6777b538SAndroid Build Coastguard Worker xmlFree(hashs1);
5886*6777b538SAndroid Build Coastguard Worker xmlFree(values1);
5887*6777b538SAndroid Build Coastguard Worker return(0);
5888*6777b538SAndroid Build Coastguard Worker }
5889*6777b538SAndroid Build Coastguard Worker hashs2 = (unsigned int *) xmlMalloc(ns2->nodeNr * sizeof(unsigned int));
5890*6777b538SAndroid Build Coastguard Worker if (hashs2 == NULL) {
5891*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
5892*6777b538SAndroid Build Coastguard Worker xmlFree(hashs1);
5893*6777b538SAndroid Build Coastguard Worker xmlFree(values1);
5894*6777b538SAndroid Build Coastguard Worker xmlFree(values2);
5895*6777b538SAndroid Build Coastguard Worker return(0);
5896*6777b538SAndroid Build Coastguard Worker }
5897*6777b538SAndroid Build Coastguard Worker memset(values2, 0, ns2->nodeNr * sizeof(xmlChar *));
5898*6777b538SAndroid Build Coastguard Worker for (i = 0;i < ns1->nodeNr;i++) {
5899*6777b538SAndroid Build Coastguard Worker hashs1[i] = xmlXPathNodeValHash(ns1->nodeTab[i]);
5900*6777b538SAndroid Build Coastguard Worker for (j = 0;j < ns2->nodeNr;j++) {
5901*6777b538SAndroid Build Coastguard Worker if (i == 0)
5902*6777b538SAndroid Build Coastguard Worker hashs2[j] = xmlXPathNodeValHash(ns2->nodeTab[j]);
5903*6777b538SAndroid Build Coastguard Worker if (hashs1[i] != hashs2[j]) {
5904*6777b538SAndroid Build Coastguard Worker if (neq) {
5905*6777b538SAndroid Build Coastguard Worker ret = 1;
5906*6777b538SAndroid Build Coastguard Worker break;
5907*6777b538SAndroid Build Coastguard Worker }
5908*6777b538SAndroid Build Coastguard Worker }
5909*6777b538SAndroid Build Coastguard Worker else {
5910*6777b538SAndroid Build Coastguard Worker if (values1[i] == NULL) {
5911*6777b538SAndroid Build Coastguard Worker values1[i] = xmlNodeGetContent(ns1->nodeTab[i]);
5912*6777b538SAndroid Build Coastguard Worker if (values1[i] == NULL)
5913*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
5914*6777b538SAndroid Build Coastguard Worker }
5915*6777b538SAndroid Build Coastguard Worker if (values2[j] == NULL) {
5916*6777b538SAndroid Build Coastguard Worker values2[j] = xmlNodeGetContent(ns2->nodeTab[j]);
5917*6777b538SAndroid Build Coastguard Worker if (values2[j] == NULL)
5918*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
5919*6777b538SAndroid Build Coastguard Worker }
5920*6777b538SAndroid Build Coastguard Worker ret = xmlStrEqual(values1[i], values2[j]) ^ neq;
5921*6777b538SAndroid Build Coastguard Worker if (ret)
5922*6777b538SAndroid Build Coastguard Worker break;
5923*6777b538SAndroid Build Coastguard Worker }
5924*6777b538SAndroid Build Coastguard Worker }
5925*6777b538SAndroid Build Coastguard Worker if (ret)
5926*6777b538SAndroid Build Coastguard Worker break;
5927*6777b538SAndroid Build Coastguard Worker }
5928*6777b538SAndroid Build Coastguard Worker for (i = 0;i < ns1->nodeNr;i++)
5929*6777b538SAndroid Build Coastguard Worker if (values1[i] != NULL)
5930*6777b538SAndroid Build Coastguard Worker xmlFree(values1[i]);
5931*6777b538SAndroid Build Coastguard Worker for (j = 0;j < ns2->nodeNr;j++)
5932*6777b538SAndroid Build Coastguard Worker if (values2[j] != NULL)
5933*6777b538SAndroid Build Coastguard Worker xmlFree(values2[j]);
5934*6777b538SAndroid Build Coastguard Worker xmlFree(values1);
5935*6777b538SAndroid Build Coastguard Worker xmlFree(values2);
5936*6777b538SAndroid Build Coastguard Worker xmlFree(hashs1);
5937*6777b538SAndroid Build Coastguard Worker xmlFree(hashs2);
5938*6777b538SAndroid Build Coastguard Worker return(ret);
5939*6777b538SAndroid Build Coastguard Worker }
5940*6777b538SAndroid Build Coastguard Worker
5941*6777b538SAndroid Build Coastguard Worker static int
xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt,xmlXPathObjectPtr arg1,xmlXPathObjectPtr arg2)5942*6777b538SAndroid Build Coastguard Worker xmlXPathEqualValuesCommon(xmlXPathParserContextPtr ctxt,
5943*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr arg1, xmlXPathObjectPtr arg2) {
5944*6777b538SAndroid Build Coastguard Worker int ret = 0;
5945*6777b538SAndroid Build Coastguard Worker /*
5946*6777b538SAndroid Build Coastguard Worker *At this point we are assured neither arg1 nor arg2
5947*6777b538SAndroid Build Coastguard Worker *is a nodeset, so we can just pick the appropriate routine.
5948*6777b538SAndroid Build Coastguard Worker */
5949*6777b538SAndroid Build Coastguard Worker switch (arg1->type) {
5950*6777b538SAndroid Build Coastguard Worker case XPATH_UNDEFINED:
5951*6777b538SAndroid Build Coastguard Worker break;
5952*6777b538SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
5953*6777b538SAndroid Build Coastguard Worker switch (arg2->type) {
5954*6777b538SAndroid Build Coastguard Worker case XPATH_UNDEFINED:
5955*6777b538SAndroid Build Coastguard Worker break;
5956*6777b538SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
5957*6777b538SAndroid Build Coastguard Worker ret = (arg1->boolval == arg2->boolval);
5958*6777b538SAndroid Build Coastguard Worker break;
5959*6777b538SAndroid Build Coastguard Worker case XPATH_NUMBER:
5960*6777b538SAndroid Build Coastguard Worker ret = (arg1->boolval ==
5961*6777b538SAndroid Build Coastguard Worker xmlXPathCastNumberToBoolean(arg2->floatval));
5962*6777b538SAndroid Build Coastguard Worker break;
5963*6777b538SAndroid Build Coastguard Worker case XPATH_STRING:
5964*6777b538SAndroid Build Coastguard Worker if ((arg2->stringval == NULL) ||
5965*6777b538SAndroid Build Coastguard Worker (arg2->stringval[0] == 0)) ret = 0;
5966*6777b538SAndroid Build Coastguard Worker else
5967*6777b538SAndroid Build Coastguard Worker ret = 1;
5968*6777b538SAndroid Build Coastguard Worker ret = (arg1->boolval == ret);
5969*6777b538SAndroid Build Coastguard Worker break;
5970*6777b538SAndroid Build Coastguard Worker case XPATH_USERS:
5971*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
5972*6777b538SAndroid Build Coastguard Worker case XPATH_POINT:
5973*6777b538SAndroid Build Coastguard Worker case XPATH_RANGE:
5974*6777b538SAndroid Build Coastguard Worker case XPATH_LOCATIONSET:
5975*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_XPTR_LOCS_ENABLED */
5976*6777b538SAndroid Build Coastguard Worker /* TODO */
5977*6777b538SAndroid Build Coastguard Worker break;
5978*6777b538SAndroid Build Coastguard Worker case XPATH_NODESET:
5979*6777b538SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
5980*6777b538SAndroid Build Coastguard Worker break;
5981*6777b538SAndroid Build Coastguard Worker }
5982*6777b538SAndroid Build Coastguard Worker break;
5983*6777b538SAndroid Build Coastguard Worker case XPATH_NUMBER:
5984*6777b538SAndroid Build Coastguard Worker switch (arg2->type) {
5985*6777b538SAndroid Build Coastguard Worker case XPATH_UNDEFINED:
5986*6777b538SAndroid Build Coastguard Worker break;
5987*6777b538SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
5988*6777b538SAndroid Build Coastguard Worker ret = (arg2->boolval==
5989*6777b538SAndroid Build Coastguard Worker xmlXPathCastNumberToBoolean(arg1->floatval));
5990*6777b538SAndroid Build Coastguard Worker break;
5991*6777b538SAndroid Build Coastguard Worker case XPATH_STRING:
5992*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, arg2);
5993*6777b538SAndroid Build Coastguard Worker xmlXPathNumberFunction(ctxt, 1);
5994*6777b538SAndroid Build Coastguard Worker arg2 = valuePop(ctxt);
5995*6777b538SAndroid Build Coastguard Worker if (ctxt->error)
5996*6777b538SAndroid Build Coastguard Worker break;
5997*6777b538SAndroid Build Coastguard Worker /* Falls through. */
5998*6777b538SAndroid Build Coastguard Worker case XPATH_NUMBER:
5999*6777b538SAndroid Build Coastguard Worker /* Hand check NaN and Infinity equalities */
6000*6777b538SAndroid Build Coastguard Worker if (xmlXPathIsNaN(arg1->floatval) ||
6001*6777b538SAndroid Build Coastguard Worker xmlXPathIsNaN(arg2->floatval)) {
6002*6777b538SAndroid Build Coastguard Worker ret = 0;
6003*6777b538SAndroid Build Coastguard Worker } else if (xmlXPathIsInf(arg1->floatval) == 1) {
6004*6777b538SAndroid Build Coastguard Worker if (xmlXPathIsInf(arg2->floatval) == 1)
6005*6777b538SAndroid Build Coastguard Worker ret = 1;
6006*6777b538SAndroid Build Coastguard Worker else
6007*6777b538SAndroid Build Coastguard Worker ret = 0;
6008*6777b538SAndroid Build Coastguard Worker } else if (xmlXPathIsInf(arg1->floatval) == -1) {
6009*6777b538SAndroid Build Coastguard Worker if (xmlXPathIsInf(arg2->floatval) == -1)
6010*6777b538SAndroid Build Coastguard Worker ret = 1;
6011*6777b538SAndroid Build Coastguard Worker else
6012*6777b538SAndroid Build Coastguard Worker ret = 0;
6013*6777b538SAndroid Build Coastguard Worker } else if (xmlXPathIsInf(arg2->floatval) == 1) {
6014*6777b538SAndroid Build Coastguard Worker if (xmlXPathIsInf(arg1->floatval) == 1)
6015*6777b538SAndroid Build Coastguard Worker ret = 1;
6016*6777b538SAndroid Build Coastguard Worker else
6017*6777b538SAndroid Build Coastguard Worker ret = 0;
6018*6777b538SAndroid Build Coastguard Worker } else if (xmlXPathIsInf(arg2->floatval) == -1) {
6019*6777b538SAndroid Build Coastguard Worker if (xmlXPathIsInf(arg1->floatval) == -1)
6020*6777b538SAndroid Build Coastguard Worker ret = 1;
6021*6777b538SAndroid Build Coastguard Worker else
6022*6777b538SAndroid Build Coastguard Worker ret = 0;
6023*6777b538SAndroid Build Coastguard Worker } else {
6024*6777b538SAndroid Build Coastguard Worker ret = (arg1->floatval == arg2->floatval);
6025*6777b538SAndroid Build Coastguard Worker }
6026*6777b538SAndroid Build Coastguard Worker break;
6027*6777b538SAndroid Build Coastguard Worker case XPATH_USERS:
6028*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
6029*6777b538SAndroid Build Coastguard Worker case XPATH_POINT:
6030*6777b538SAndroid Build Coastguard Worker case XPATH_RANGE:
6031*6777b538SAndroid Build Coastguard Worker case XPATH_LOCATIONSET:
6032*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_XPTR_LOCS_ENABLED */
6033*6777b538SAndroid Build Coastguard Worker /* TODO */
6034*6777b538SAndroid Build Coastguard Worker break;
6035*6777b538SAndroid Build Coastguard Worker case XPATH_NODESET:
6036*6777b538SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
6037*6777b538SAndroid Build Coastguard Worker break;
6038*6777b538SAndroid Build Coastguard Worker }
6039*6777b538SAndroid Build Coastguard Worker break;
6040*6777b538SAndroid Build Coastguard Worker case XPATH_STRING:
6041*6777b538SAndroid Build Coastguard Worker switch (arg2->type) {
6042*6777b538SAndroid Build Coastguard Worker case XPATH_UNDEFINED:
6043*6777b538SAndroid Build Coastguard Worker break;
6044*6777b538SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
6045*6777b538SAndroid Build Coastguard Worker if ((arg1->stringval == NULL) ||
6046*6777b538SAndroid Build Coastguard Worker (arg1->stringval[0] == 0)) ret = 0;
6047*6777b538SAndroid Build Coastguard Worker else
6048*6777b538SAndroid Build Coastguard Worker ret = 1;
6049*6777b538SAndroid Build Coastguard Worker ret = (arg2->boolval == ret);
6050*6777b538SAndroid Build Coastguard Worker break;
6051*6777b538SAndroid Build Coastguard Worker case XPATH_STRING:
6052*6777b538SAndroid Build Coastguard Worker ret = xmlStrEqual(arg1->stringval, arg2->stringval);
6053*6777b538SAndroid Build Coastguard Worker break;
6054*6777b538SAndroid Build Coastguard Worker case XPATH_NUMBER:
6055*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, arg1);
6056*6777b538SAndroid Build Coastguard Worker xmlXPathNumberFunction(ctxt, 1);
6057*6777b538SAndroid Build Coastguard Worker arg1 = valuePop(ctxt);
6058*6777b538SAndroid Build Coastguard Worker if (ctxt->error)
6059*6777b538SAndroid Build Coastguard Worker break;
6060*6777b538SAndroid Build Coastguard Worker /* Hand check NaN and Infinity equalities */
6061*6777b538SAndroid Build Coastguard Worker if (xmlXPathIsNaN(arg1->floatval) ||
6062*6777b538SAndroid Build Coastguard Worker xmlXPathIsNaN(arg2->floatval)) {
6063*6777b538SAndroid Build Coastguard Worker ret = 0;
6064*6777b538SAndroid Build Coastguard Worker } else if (xmlXPathIsInf(arg1->floatval) == 1) {
6065*6777b538SAndroid Build Coastguard Worker if (xmlXPathIsInf(arg2->floatval) == 1)
6066*6777b538SAndroid Build Coastguard Worker ret = 1;
6067*6777b538SAndroid Build Coastguard Worker else
6068*6777b538SAndroid Build Coastguard Worker ret = 0;
6069*6777b538SAndroid Build Coastguard Worker } else if (xmlXPathIsInf(arg1->floatval) == -1) {
6070*6777b538SAndroid Build Coastguard Worker if (xmlXPathIsInf(arg2->floatval) == -1)
6071*6777b538SAndroid Build Coastguard Worker ret = 1;
6072*6777b538SAndroid Build Coastguard Worker else
6073*6777b538SAndroid Build Coastguard Worker ret = 0;
6074*6777b538SAndroid Build Coastguard Worker } else if (xmlXPathIsInf(arg2->floatval) == 1) {
6075*6777b538SAndroid Build Coastguard Worker if (xmlXPathIsInf(arg1->floatval) == 1)
6076*6777b538SAndroid Build Coastguard Worker ret = 1;
6077*6777b538SAndroid Build Coastguard Worker else
6078*6777b538SAndroid Build Coastguard Worker ret = 0;
6079*6777b538SAndroid Build Coastguard Worker } else if (xmlXPathIsInf(arg2->floatval) == -1) {
6080*6777b538SAndroid Build Coastguard Worker if (xmlXPathIsInf(arg1->floatval) == -1)
6081*6777b538SAndroid Build Coastguard Worker ret = 1;
6082*6777b538SAndroid Build Coastguard Worker else
6083*6777b538SAndroid Build Coastguard Worker ret = 0;
6084*6777b538SAndroid Build Coastguard Worker } else {
6085*6777b538SAndroid Build Coastguard Worker ret = (arg1->floatval == arg2->floatval);
6086*6777b538SAndroid Build Coastguard Worker }
6087*6777b538SAndroid Build Coastguard Worker break;
6088*6777b538SAndroid Build Coastguard Worker case XPATH_USERS:
6089*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
6090*6777b538SAndroid Build Coastguard Worker case XPATH_POINT:
6091*6777b538SAndroid Build Coastguard Worker case XPATH_RANGE:
6092*6777b538SAndroid Build Coastguard Worker case XPATH_LOCATIONSET:
6093*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_XPTR_LOCS_ENABLED */
6094*6777b538SAndroid Build Coastguard Worker /* TODO */
6095*6777b538SAndroid Build Coastguard Worker break;
6096*6777b538SAndroid Build Coastguard Worker case XPATH_NODESET:
6097*6777b538SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
6098*6777b538SAndroid Build Coastguard Worker break;
6099*6777b538SAndroid Build Coastguard Worker }
6100*6777b538SAndroid Build Coastguard Worker break;
6101*6777b538SAndroid Build Coastguard Worker case XPATH_USERS:
6102*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
6103*6777b538SAndroid Build Coastguard Worker case XPATH_POINT:
6104*6777b538SAndroid Build Coastguard Worker case XPATH_RANGE:
6105*6777b538SAndroid Build Coastguard Worker case XPATH_LOCATIONSET:
6106*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_XPTR_LOCS_ENABLED */
6107*6777b538SAndroid Build Coastguard Worker /* TODO */
6108*6777b538SAndroid Build Coastguard Worker break;
6109*6777b538SAndroid Build Coastguard Worker case XPATH_NODESET:
6110*6777b538SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
6111*6777b538SAndroid Build Coastguard Worker break;
6112*6777b538SAndroid Build Coastguard Worker }
6113*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
6114*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
6115*6777b538SAndroid Build Coastguard Worker return(ret);
6116*6777b538SAndroid Build Coastguard Worker }
6117*6777b538SAndroid Build Coastguard Worker
6118*6777b538SAndroid Build Coastguard Worker /**
6119*6777b538SAndroid Build Coastguard Worker * xmlXPathEqualValues:
6120*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6121*6777b538SAndroid Build Coastguard Worker *
6122*6777b538SAndroid Build Coastguard Worker * Implement the equal operation on XPath objects content: @arg1 == @arg2
6123*6777b538SAndroid Build Coastguard Worker *
6124*6777b538SAndroid Build Coastguard Worker * Returns 0 or 1 depending on the results of the test.
6125*6777b538SAndroid Build Coastguard Worker */
6126*6777b538SAndroid Build Coastguard Worker int
xmlXPathEqualValues(xmlXPathParserContextPtr ctxt)6127*6777b538SAndroid Build Coastguard Worker xmlXPathEqualValues(xmlXPathParserContextPtr ctxt) {
6128*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr arg1, arg2, argtmp;
6129*6777b538SAndroid Build Coastguard Worker int ret = 0;
6130*6777b538SAndroid Build Coastguard Worker
6131*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(0);
6132*6777b538SAndroid Build Coastguard Worker arg2 = valuePop(ctxt);
6133*6777b538SAndroid Build Coastguard Worker arg1 = valuePop(ctxt);
6134*6777b538SAndroid Build Coastguard Worker if ((arg1 == NULL) || (arg2 == NULL)) {
6135*6777b538SAndroid Build Coastguard Worker if (arg1 != NULL)
6136*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
6137*6777b538SAndroid Build Coastguard Worker else
6138*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
6139*6777b538SAndroid Build Coastguard Worker XP_ERROR0(XPATH_INVALID_OPERAND);
6140*6777b538SAndroid Build Coastguard Worker }
6141*6777b538SAndroid Build Coastguard Worker
6142*6777b538SAndroid Build Coastguard Worker if (arg1 == arg2) {
6143*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject(arg1);
6144*6777b538SAndroid Build Coastguard Worker return(1);
6145*6777b538SAndroid Build Coastguard Worker }
6146*6777b538SAndroid Build Coastguard Worker
6147*6777b538SAndroid Build Coastguard Worker /*
6148*6777b538SAndroid Build Coastguard Worker *If either argument is a nodeset, it's a 'special case'
6149*6777b538SAndroid Build Coastguard Worker */
6150*6777b538SAndroid Build Coastguard Worker if ((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE) ||
6151*6777b538SAndroid Build Coastguard Worker (arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
6152*6777b538SAndroid Build Coastguard Worker /*
6153*6777b538SAndroid Build Coastguard Worker *Hack it to assure arg1 is the nodeset
6154*6777b538SAndroid Build Coastguard Worker */
6155*6777b538SAndroid Build Coastguard Worker if ((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE)) {
6156*6777b538SAndroid Build Coastguard Worker argtmp = arg2;
6157*6777b538SAndroid Build Coastguard Worker arg2 = arg1;
6158*6777b538SAndroid Build Coastguard Worker arg1 = argtmp;
6159*6777b538SAndroid Build Coastguard Worker }
6160*6777b538SAndroid Build Coastguard Worker switch (arg2->type) {
6161*6777b538SAndroid Build Coastguard Worker case XPATH_UNDEFINED:
6162*6777b538SAndroid Build Coastguard Worker break;
6163*6777b538SAndroid Build Coastguard Worker case XPATH_NODESET:
6164*6777b538SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
6165*6777b538SAndroid Build Coastguard Worker ret = xmlXPathEqualNodeSets(ctxt, arg1, arg2, 0);
6166*6777b538SAndroid Build Coastguard Worker break;
6167*6777b538SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
6168*6777b538SAndroid Build Coastguard Worker if ((arg1->nodesetval == NULL) ||
6169*6777b538SAndroid Build Coastguard Worker (arg1->nodesetval->nodeNr == 0)) ret = 0;
6170*6777b538SAndroid Build Coastguard Worker else
6171*6777b538SAndroid Build Coastguard Worker ret = 1;
6172*6777b538SAndroid Build Coastguard Worker ret = (ret == arg2->boolval);
6173*6777b538SAndroid Build Coastguard Worker break;
6174*6777b538SAndroid Build Coastguard Worker case XPATH_NUMBER:
6175*6777b538SAndroid Build Coastguard Worker ret = xmlXPathEqualNodeSetFloat(ctxt, arg1, arg2->floatval, 0);
6176*6777b538SAndroid Build Coastguard Worker break;
6177*6777b538SAndroid Build Coastguard Worker case XPATH_STRING:
6178*6777b538SAndroid Build Coastguard Worker ret = xmlXPathEqualNodeSetString(ctxt, arg1,
6179*6777b538SAndroid Build Coastguard Worker arg2->stringval, 0);
6180*6777b538SAndroid Build Coastguard Worker break;
6181*6777b538SAndroid Build Coastguard Worker case XPATH_USERS:
6182*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
6183*6777b538SAndroid Build Coastguard Worker case XPATH_POINT:
6184*6777b538SAndroid Build Coastguard Worker case XPATH_RANGE:
6185*6777b538SAndroid Build Coastguard Worker case XPATH_LOCATIONSET:
6186*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_XPTR_LOCS_ENABLED */
6187*6777b538SAndroid Build Coastguard Worker /* TODO */
6188*6777b538SAndroid Build Coastguard Worker break;
6189*6777b538SAndroid Build Coastguard Worker }
6190*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
6191*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
6192*6777b538SAndroid Build Coastguard Worker return(ret);
6193*6777b538SAndroid Build Coastguard Worker }
6194*6777b538SAndroid Build Coastguard Worker
6195*6777b538SAndroid Build Coastguard Worker return (xmlXPathEqualValuesCommon(ctxt, arg1, arg2));
6196*6777b538SAndroid Build Coastguard Worker }
6197*6777b538SAndroid Build Coastguard Worker
6198*6777b538SAndroid Build Coastguard Worker /**
6199*6777b538SAndroid Build Coastguard Worker * xmlXPathNotEqualValues:
6200*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6201*6777b538SAndroid Build Coastguard Worker *
6202*6777b538SAndroid Build Coastguard Worker * Implement the equal operation on XPath objects content: @arg1 == @arg2
6203*6777b538SAndroid Build Coastguard Worker *
6204*6777b538SAndroid Build Coastguard Worker * Returns 0 or 1 depending on the results of the test.
6205*6777b538SAndroid Build Coastguard Worker */
6206*6777b538SAndroid Build Coastguard Worker int
xmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt)6207*6777b538SAndroid Build Coastguard Worker xmlXPathNotEqualValues(xmlXPathParserContextPtr ctxt) {
6208*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr arg1, arg2, argtmp;
6209*6777b538SAndroid Build Coastguard Worker int ret = 0;
6210*6777b538SAndroid Build Coastguard Worker
6211*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(0);
6212*6777b538SAndroid Build Coastguard Worker arg2 = valuePop(ctxt);
6213*6777b538SAndroid Build Coastguard Worker arg1 = valuePop(ctxt);
6214*6777b538SAndroid Build Coastguard Worker if ((arg1 == NULL) || (arg2 == NULL)) {
6215*6777b538SAndroid Build Coastguard Worker if (arg1 != NULL)
6216*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
6217*6777b538SAndroid Build Coastguard Worker else
6218*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
6219*6777b538SAndroid Build Coastguard Worker XP_ERROR0(XPATH_INVALID_OPERAND);
6220*6777b538SAndroid Build Coastguard Worker }
6221*6777b538SAndroid Build Coastguard Worker
6222*6777b538SAndroid Build Coastguard Worker if (arg1 == arg2) {
6223*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
6224*6777b538SAndroid Build Coastguard Worker return(0);
6225*6777b538SAndroid Build Coastguard Worker }
6226*6777b538SAndroid Build Coastguard Worker
6227*6777b538SAndroid Build Coastguard Worker /*
6228*6777b538SAndroid Build Coastguard Worker *If either argument is a nodeset, it's a 'special case'
6229*6777b538SAndroid Build Coastguard Worker */
6230*6777b538SAndroid Build Coastguard Worker if ((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE) ||
6231*6777b538SAndroid Build Coastguard Worker (arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
6232*6777b538SAndroid Build Coastguard Worker /*
6233*6777b538SAndroid Build Coastguard Worker *Hack it to assure arg1 is the nodeset
6234*6777b538SAndroid Build Coastguard Worker */
6235*6777b538SAndroid Build Coastguard Worker if ((arg1->type != XPATH_NODESET) && (arg1->type != XPATH_XSLT_TREE)) {
6236*6777b538SAndroid Build Coastguard Worker argtmp = arg2;
6237*6777b538SAndroid Build Coastguard Worker arg2 = arg1;
6238*6777b538SAndroid Build Coastguard Worker arg1 = argtmp;
6239*6777b538SAndroid Build Coastguard Worker }
6240*6777b538SAndroid Build Coastguard Worker switch (arg2->type) {
6241*6777b538SAndroid Build Coastguard Worker case XPATH_UNDEFINED:
6242*6777b538SAndroid Build Coastguard Worker break;
6243*6777b538SAndroid Build Coastguard Worker case XPATH_NODESET:
6244*6777b538SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
6245*6777b538SAndroid Build Coastguard Worker ret = xmlXPathEqualNodeSets(ctxt, arg1, arg2, 1);
6246*6777b538SAndroid Build Coastguard Worker break;
6247*6777b538SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
6248*6777b538SAndroid Build Coastguard Worker if ((arg1->nodesetval == NULL) ||
6249*6777b538SAndroid Build Coastguard Worker (arg1->nodesetval->nodeNr == 0)) ret = 0;
6250*6777b538SAndroid Build Coastguard Worker else
6251*6777b538SAndroid Build Coastguard Worker ret = 1;
6252*6777b538SAndroid Build Coastguard Worker ret = (ret != arg2->boolval);
6253*6777b538SAndroid Build Coastguard Worker break;
6254*6777b538SAndroid Build Coastguard Worker case XPATH_NUMBER:
6255*6777b538SAndroid Build Coastguard Worker ret = xmlXPathEqualNodeSetFloat(ctxt, arg1, arg2->floatval, 1);
6256*6777b538SAndroid Build Coastguard Worker break;
6257*6777b538SAndroid Build Coastguard Worker case XPATH_STRING:
6258*6777b538SAndroid Build Coastguard Worker ret = xmlXPathEqualNodeSetString(ctxt, arg1,
6259*6777b538SAndroid Build Coastguard Worker arg2->stringval, 1);
6260*6777b538SAndroid Build Coastguard Worker break;
6261*6777b538SAndroid Build Coastguard Worker case XPATH_USERS:
6262*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
6263*6777b538SAndroid Build Coastguard Worker case XPATH_POINT:
6264*6777b538SAndroid Build Coastguard Worker case XPATH_RANGE:
6265*6777b538SAndroid Build Coastguard Worker case XPATH_LOCATIONSET:
6266*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_XPTR_LOCS_ENABLED */
6267*6777b538SAndroid Build Coastguard Worker /* TODO */
6268*6777b538SAndroid Build Coastguard Worker break;
6269*6777b538SAndroid Build Coastguard Worker }
6270*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
6271*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
6272*6777b538SAndroid Build Coastguard Worker return(ret);
6273*6777b538SAndroid Build Coastguard Worker }
6274*6777b538SAndroid Build Coastguard Worker
6275*6777b538SAndroid Build Coastguard Worker return (!xmlXPathEqualValuesCommon(ctxt, arg1, arg2));
6276*6777b538SAndroid Build Coastguard Worker }
6277*6777b538SAndroid Build Coastguard Worker
6278*6777b538SAndroid Build Coastguard Worker /**
6279*6777b538SAndroid Build Coastguard Worker * xmlXPathCompareValues:
6280*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6281*6777b538SAndroid Build Coastguard Worker * @inf: less than (1) or greater than (0)
6282*6777b538SAndroid Build Coastguard Worker * @strict: is the comparison strict
6283*6777b538SAndroid Build Coastguard Worker *
6284*6777b538SAndroid Build Coastguard Worker * Implement the compare operation on XPath objects:
6285*6777b538SAndroid Build Coastguard Worker * @arg1 < @arg2 (1, 1, ...
6286*6777b538SAndroid Build Coastguard Worker * @arg1 <= @arg2 (1, 0, ...
6287*6777b538SAndroid Build Coastguard Worker * @arg1 > @arg2 (0, 1, ...
6288*6777b538SAndroid Build Coastguard Worker * @arg1 >= @arg2 (0, 0, ...
6289*6777b538SAndroid Build Coastguard Worker *
6290*6777b538SAndroid Build Coastguard Worker * When neither object to be compared is a node-set and the operator is
6291*6777b538SAndroid Build Coastguard Worker * <=, <, >=, >, then the objects are compared by converted both objects
6292*6777b538SAndroid Build Coastguard Worker * to numbers and comparing the numbers according to IEEE 754. The <
6293*6777b538SAndroid Build Coastguard Worker * comparison will be true if and only if the first number is less than the
6294*6777b538SAndroid Build Coastguard Worker * second number. The <= comparison will be true if and only if the first
6295*6777b538SAndroid Build Coastguard Worker * number is less than or equal to the second number. The > comparison
6296*6777b538SAndroid Build Coastguard Worker * will be true if and only if the first number is greater than the second
6297*6777b538SAndroid Build Coastguard Worker * number. The >= comparison will be true if and only if the first number
6298*6777b538SAndroid Build Coastguard Worker * is greater than or equal to the second number.
6299*6777b538SAndroid Build Coastguard Worker *
6300*6777b538SAndroid Build Coastguard Worker * Returns 1 if the comparison succeeded, 0 if it failed
6301*6777b538SAndroid Build Coastguard Worker */
6302*6777b538SAndroid Build Coastguard Worker int
xmlXPathCompareValues(xmlXPathParserContextPtr ctxt,int inf,int strict)6303*6777b538SAndroid Build Coastguard Worker xmlXPathCompareValues(xmlXPathParserContextPtr ctxt, int inf, int strict) {
6304*6777b538SAndroid Build Coastguard Worker int ret = 0, arg1i = 0, arg2i = 0;
6305*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr arg1, arg2;
6306*6777b538SAndroid Build Coastguard Worker
6307*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(0);
6308*6777b538SAndroid Build Coastguard Worker arg2 = valuePop(ctxt);
6309*6777b538SAndroid Build Coastguard Worker arg1 = valuePop(ctxt);
6310*6777b538SAndroid Build Coastguard Worker if ((arg1 == NULL) || (arg2 == NULL)) {
6311*6777b538SAndroid Build Coastguard Worker if (arg1 != NULL)
6312*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
6313*6777b538SAndroid Build Coastguard Worker else
6314*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
6315*6777b538SAndroid Build Coastguard Worker XP_ERROR0(XPATH_INVALID_OPERAND);
6316*6777b538SAndroid Build Coastguard Worker }
6317*6777b538SAndroid Build Coastguard Worker
6318*6777b538SAndroid Build Coastguard Worker if ((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE) ||
6319*6777b538SAndroid Build Coastguard Worker (arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
6320*6777b538SAndroid Build Coastguard Worker /*
6321*6777b538SAndroid Build Coastguard Worker * If either argument is a XPATH_NODESET or XPATH_XSLT_TREE the two arguments
6322*6777b538SAndroid Build Coastguard Worker * are not freed from within this routine; they will be freed from the
6323*6777b538SAndroid Build Coastguard Worker * called routine, e.g. xmlXPathCompareNodeSets or xmlXPathCompareNodeSetValue
6324*6777b538SAndroid Build Coastguard Worker */
6325*6777b538SAndroid Build Coastguard Worker if (((arg2->type == XPATH_NODESET) || (arg2->type == XPATH_XSLT_TREE)) &&
6326*6777b538SAndroid Build Coastguard Worker ((arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE))){
6327*6777b538SAndroid Build Coastguard Worker ret = xmlXPathCompareNodeSets(ctxt, inf, strict, arg1, arg2);
6328*6777b538SAndroid Build Coastguard Worker } else {
6329*6777b538SAndroid Build Coastguard Worker if ((arg1->type == XPATH_NODESET) || (arg1->type == XPATH_XSLT_TREE)) {
6330*6777b538SAndroid Build Coastguard Worker ret = xmlXPathCompareNodeSetValue(ctxt, inf, strict,
6331*6777b538SAndroid Build Coastguard Worker arg1, arg2);
6332*6777b538SAndroid Build Coastguard Worker } else {
6333*6777b538SAndroid Build Coastguard Worker ret = xmlXPathCompareNodeSetValue(ctxt, !inf, strict,
6334*6777b538SAndroid Build Coastguard Worker arg2, arg1);
6335*6777b538SAndroid Build Coastguard Worker }
6336*6777b538SAndroid Build Coastguard Worker }
6337*6777b538SAndroid Build Coastguard Worker return(ret);
6338*6777b538SAndroid Build Coastguard Worker }
6339*6777b538SAndroid Build Coastguard Worker
6340*6777b538SAndroid Build Coastguard Worker if (arg1->type != XPATH_NUMBER) {
6341*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, arg1);
6342*6777b538SAndroid Build Coastguard Worker xmlXPathNumberFunction(ctxt, 1);
6343*6777b538SAndroid Build Coastguard Worker arg1 = valuePop(ctxt);
6344*6777b538SAndroid Build Coastguard Worker }
6345*6777b538SAndroid Build Coastguard Worker if (arg2->type != XPATH_NUMBER) {
6346*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, arg2);
6347*6777b538SAndroid Build Coastguard Worker xmlXPathNumberFunction(ctxt, 1);
6348*6777b538SAndroid Build Coastguard Worker arg2 = valuePop(ctxt);
6349*6777b538SAndroid Build Coastguard Worker }
6350*6777b538SAndroid Build Coastguard Worker if (ctxt->error)
6351*6777b538SAndroid Build Coastguard Worker goto error;
6352*6777b538SAndroid Build Coastguard Worker /*
6353*6777b538SAndroid Build Coastguard Worker * Add tests for infinity and nan
6354*6777b538SAndroid Build Coastguard Worker * => feedback on 3.4 for Inf and NaN
6355*6777b538SAndroid Build Coastguard Worker */
6356*6777b538SAndroid Build Coastguard Worker /* Hand check NaN and Infinity comparisons */
6357*6777b538SAndroid Build Coastguard Worker if (xmlXPathIsNaN(arg1->floatval) || xmlXPathIsNaN(arg2->floatval)) {
6358*6777b538SAndroid Build Coastguard Worker ret=0;
6359*6777b538SAndroid Build Coastguard Worker } else {
6360*6777b538SAndroid Build Coastguard Worker arg1i=xmlXPathIsInf(arg1->floatval);
6361*6777b538SAndroid Build Coastguard Worker arg2i=xmlXPathIsInf(arg2->floatval);
6362*6777b538SAndroid Build Coastguard Worker if (inf && strict) {
6363*6777b538SAndroid Build Coastguard Worker if ((arg1i == -1 && arg2i != -1) ||
6364*6777b538SAndroid Build Coastguard Worker (arg2i == 1 && arg1i != 1)) {
6365*6777b538SAndroid Build Coastguard Worker ret = 1;
6366*6777b538SAndroid Build Coastguard Worker } else if (arg1i == 0 && arg2i == 0) {
6367*6777b538SAndroid Build Coastguard Worker ret = (arg1->floatval < arg2->floatval);
6368*6777b538SAndroid Build Coastguard Worker } else {
6369*6777b538SAndroid Build Coastguard Worker ret = 0;
6370*6777b538SAndroid Build Coastguard Worker }
6371*6777b538SAndroid Build Coastguard Worker }
6372*6777b538SAndroid Build Coastguard Worker else if (inf && !strict) {
6373*6777b538SAndroid Build Coastguard Worker if (arg1i == -1 || arg2i == 1) {
6374*6777b538SAndroid Build Coastguard Worker ret = 1;
6375*6777b538SAndroid Build Coastguard Worker } else if (arg1i == 0 && arg2i == 0) {
6376*6777b538SAndroid Build Coastguard Worker ret = (arg1->floatval <= arg2->floatval);
6377*6777b538SAndroid Build Coastguard Worker } else {
6378*6777b538SAndroid Build Coastguard Worker ret = 0;
6379*6777b538SAndroid Build Coastguard Worker }
6380*6777b538SAndroid Build Coastguard Worker }
6381*6777b538SAndroid Build Coastguard Worker else if (!inf && strict) {
6382*6777b538SAndroid Build Coastguard Worker if ((arg1i == 1 && arg2i != 1) ||
6383*6777b538SAndroid Build Coastguard Worker (arg2i == -1 && arg1i != -1)) {
6384*6777b538SAndroid Build Coastguard Worker ret = 1;
6385*6777b538SAndroid Build Coastguard Worker } else if (arg1i == 0 && arg2i == 0) {
6386*6777b538SAndroid Build Coastguard Worker ret = (arg1->floatval > arg2->floatval);
6387*6777b538SAndroid Build Coastguard Worker } else {
6388*6777b538SAndroid Build Coastguard Worker ret = 0;
6389*6777b538SAndroid Build Coastguard Worker }
6390*6777b538SAndroid Build Coastguard Worker }
6391*6777b538SAndroid Build Coastguard Worker else if (!inf && !strict) {
6392*6777b538SAndroid Build Coastguard Worker if (arg1i == 1 || arg2i == -1) {
6393*6777b538SAndroid Build Coastguard Worker ret = 1;
6394*6777b538SAndroid Build Coastguard Worker } else if (arg1i == 0 && arg2i == 0) {
6395*6777b538SAndroid Build Coastguard Worker ret = (arg1->floatval >= arg2->floatval);
6396*6777b538SAndroid Build Coastguard Worker } else {
6397*6777b538SAndroid Build Coastguard Worker ret = 0;
6398*6777b538SAndroid Build Coastguard Worker }
6399*6777b538SAndroid Build Coastguard Worker }
6400*6777b538SAndroid Build Coastguard Worker }
6401*6777b538SAndroid Build Coastguard Worker error:
6402*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
6403*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
6404*6777b538SAndroid Build Coastguard Worker return(ret);
6405*6777b538SAndroid Build Coastguard Worker }
6406*6777b538SAndroid Build Coastguard Worker
6407*6777b538SAndroid Build Coastguard Worker /**
6408*6777b538SAndroid Build Coastguard Worker * xmlXPathValueFlipSign:
6409*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6410*6777b538SAndroid Build Coastguard Worker *
6411*6777b538SAndroid Build Coastguard Worker * Implement the unary - operation on an XPath object
6412*6777b538SAndroid Build Coastguard Worker * The numeric operators convert their operands to numbers as if
6413*6777b538SAndroid Build Coastguard Worker * by calling the number function.
6414*6777b538SAndroid Build Coastguard Worker */
6415*6777b538SAndroid Build Coastguard Worker void
xmlXPathValueFlipSign(xmlXPathParserContextPtr ctxt)6416*6777b538SAndroid Build Coastguard Worker xmlXPathValueFlipSign(xmlXPathParserContextPtr ctxt) {
6417*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return;
6418*6777b538SAndroid Build Coastguard Worker CAST_TO_NUMBER;
6419*6777b538SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_NUMBER);
6420*6777b538SAndroid Build Coastguard Worker ctxt->value->floatval = -ctxt->value->floatval;
6421*6777b538SAndroid Build Coastguard Worker }
6422*6777b538SAndroid Build Coastguard Worker
6423*6777b538SAndroid Build Coastguard Worker /**
6424*6777b538SAndroid Build Coastguard Worker * xmlXPathAddValues:
6425*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6426*6777b538SAndroid Build Coastguard Worker *
6427*6777b538SAndroid Build Coastguard Worker * Implement the add operation on XPath objects:
6428*6777b538SAndroid Build Coastguard Worker * The numeric operators convert their operands to numbers as if
6429*6777b538SAndroid Build Coastguard Worker * by calling the number function.
6430*6777b538SAndroid Build Coastguard Worker */
6431*6777b538SAndroid Build Coastguard Worker void
xmlXPathAddValues(xmlXPathParserContextPtr ctxt)6432*6777b538SAndroid Build Coastguard Worker xmlXPathAddValues(xmlXPathParserContextPtr ctxt) {
6433*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr arg;
6434*6777b538SAndroid Build Coastguard Worker double val;
6435*6777b538SAndroid Build Coastguard Worker
6436*6777b538SAndroid Build Coastguard Worker arg = valuePop(ctxt);
6437*6777b538SAndroid Build Coastguard Worker if (arg == NULL)
6438*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_OPERAND);
6439*6777b538SAndroid Build Coastguard Worker val = xmlXPathCastToNumberInternal(ctxt, arg);
6440*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg);
6441*6777b538SAndroid Build Coastguard Worker CAST_TO_NUMBER;
6442*6777b538SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_NUMBER);
6443*6777b538SAndroid Build Coastguard Worker ctxt->value->floatval += val;
6444*6777b538SAndroid Build Coastguard Worker }
6445*6777b538SAndroid Build Coastguard Worker
6446*6777b538SAndroid Build Coastguard Worker /**
6447*6777b538SAndroid Build Coastguard Worker * xmlXPathSubValues:
6448*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6449*6777b538SAndroid Build Coastguard Worker *
6450*6777b538SAndroid Build Coastguard Worker * Implement the subtraction operation on XPath objects:
6451*6777b538SAndroid Build Coastguard Worker * The numeric operators convert their operands to numbers as if
6452*6777b538SAndroid Build Coastguard Worker * by calling the number function.
6453*6777b538SAndroid Build Coastguard Worker */
6454*6777b538SAndroid Build Coastguard Worker void
xmlXPathSubValues(xmlXPathParserContextPtr ctxt)6455*6777b538SAndroid Build Coastguard Worker xmlXPathSubValues(xmlXPathParserContextPtr ctxt) {
6456*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr arg;
6457*6777b538SAndroid Build Coastguard Worker double val;
6458*6777b538SAndroid Build Coastguard Worker
6459*6777b538SAndroid Build Coastguard Worker arg = valuePop(ctxt);
6460*6777b538SAndroid Build Coastguard Worker if (arg == NULL)
6461*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_OPERAND);
6462*6777b538SAndroid Build Coastguard Worker val = xmlXPathCastToNumberInternal(ctxt, arg);
6463*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg);
6464*6777b538SAndroid Build Coastguard Worker CAST_TO_NUMBER;
6465*6777b538SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_NUMBER);
6466*6777b538SAndroid Build Coastguard Worker ctxt->value->floatval -= val;
6467*6777b538SAndroid Build Coastguard Worker }
6468*6777b538SAndroid Build Coastguard Worker
6469*6777b538SAndroid Build Coastguard Worker /**
6470*6777b538SAndroid Build Coastguard Worker * xmlXPathMultValues:
6471*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6472*6777b538SAndroid Build Coastguard Worker *
6473*6777b538SAndroid Build Coastguard Worker * Implement the multiply operation on XPath objects:
6474*6777b538SAndroid Build Coastguard Worker * The numeric operators convert their operands to numbers as if
6475*6777b538SAndroid Build Coastguard Worker * by calling the number function.
6476*6777b538SAndroid Build Coastguard Worker */
6477*6777b538SAndroid Build Coastguard Worker void
xmlXPathMultValues(xmlXPathParserContextPtr ctxt)6478*6777b538SAndroid Build Coastguard Worker xmlXPathMultValues(xmlXPathParserContextPtr ctxt) {
6479*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr arg;
6480*6777b538SAndroid Build Coastguard Worker double val;
6481*6777b538SAndroid Build Coastguard Worker
6482*6777b538SAndroid Build Coastguard Worker arg = valuePop(ctxt);
6483*6777b538SAndroid Build Coastguard Worker if (arg == NULL)
6484*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_OPERAND);
6485*6777b538SAndroid Build Coastguard Worker val = xmlXPathCastToNumberInternal(ctxt, arg);
6486*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg);
6487*6777b538SAndroid Build Coastguard Worker CAST_TO_NUMBER;
6488*6777b538SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_NUMBER);
6489*6777b538SAndroid Build Coastguard Worker ctxt->value->floatval *= val;
6490*6777b538SAndroid Build Coastguard Worker }
6491*6777b538SAndroid Build Coastguard Worker
6492*6777b538SAndroid Build Coastguard Worker /**
6493*6777b538SAndroid Build Coastguard Worker * xmlXPathDivValues:
6494*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6495*6777b538SAndroid Build Coastguard Worker *
6496*6777b538SAndroid Build Coastguard Worker * Implement the div operation on XPath objects @arg1 / @arg2:
6497*6777b538SAndroid Build Coastguard Worker * The numeric operators convert their operands to numbers as if
6498*6777b538SAndroid Build Coastguard Worker * by calling the number function.
6499*6777b538SAndroid Build Coastguard Worker */
6500*6777b538SAndroid Build Coastguard Worker ATTRIBUTE_NO_SANITIZE("float-divide-by-zero")
6501*6777b538SAndroid Build Coastguard Worker void
xmlXPathDivValues(xmlXPathParserContextPtr ctxt)6502*6777b538SAndroid Build Coastguard Worker xmlXPathDivValues(xmlXPathParserContextPtr ctxt) {
6503*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr arg;
6504*6777b538SAndroid Build Coastguard Worker double val;
6505*6777b538SAndroid Build Coastguard Worker
6506*6777b538SAndroid Build Coastguard Worker arg = valuePop(ctxt);
6507*6777b538SAndroid Build Coastguard Worker if (arg == NULL)
6508*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_OPERAND);
6509*6777b538SAndroid Build Coastguard Worker val = xmlXPathCastToNumberInternal(ctxt, arg);
6510*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg);
6511*6777b538SAndroid Build Coastguard Worker CAST_TO_NUMBER;
6512*6777b538SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_NUMBER);
6513*6777b538SAndroid Build Coastguard Worker ctxt->value->floatval /= val;
6514*6777b538SAndroid Build Coastguard Worker }
6515*6777b538SAndroid Build Coastguard Worker
6516*6777b538SAndroid Build Coastguard Worker /**
6517*6777b538SAndroid Build Coastguard Worker * xmlXPathModValues:
6518*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6519*6777b538SAndroid Build Coastguard Worker *
6520*6777b538SAndroid Build Coastguard Worker * Implement the mod operation on XPath objects: @arg1 / @arg2
6521*6777b538SAndroid Build Coastguard Worker * The numeric operators convert their operands to numbers as if
6522*6777b538SAndroid Build Coastguard Worker * by calling the number function.
6523*6777b538SAndroid Build Coastguard Worker */
6524*6777b538SAndroid Build Coastguard Worker void
xmlXPathModValues(xmlXPathParserContextPtr ctxt)6525*6777b538SAndroid Build Coastguard Worker xmlXPathModValues(xmlXPathParserContextPtr ctxt) {
6526*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr arg;
6527*6777b538SAndroid Build Coastguard Worker double arg1, arg2;
6528*6777b538SAndroid Build Coastguard Worker
6529*6777b538SAndroid Build Coastguard Worker arg = valuePop(ctxt);
6530*6777b538SAndroid Build Coastguard Worker if (arg == NULL)
6531*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_OPERAND);
6532*6777b538SAndroid Build Coastguard Worker arg2 = xmlXPathCastToNumberInternal(ctxt, arg);
6533*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg);
6534*6777b538SAndroid Build Coastguard Worker CAST_TO_NUMBER;
6535*6777b538SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_NUMBER);
6536*6777b538SAndroid Build Coastguard Worker arg1 = ctxt->value->floatval;
6537*6777b538SAndroid Build Coastguard Worker if (arg2 == 0)
6538*6777b538SAndroid Build Coastguard Worker ctxt->value->floatval = xmlXPathNAN;
6539*6777b538SAndroid Build Coastguard Worker else {
6540*6777b538SAndroid Build Coastguard Worker ctxt->value->floatval = fmod(arg1, arg2);
6541*6777b538SAndroid Build Coastguard Worker }
6542*6777b538SAndroid Build Coastguard Worker }
6543*6777b538SAndroid Build Coastguard Worker
6544*6777b538SAndroid Build Coastguard Worker /************************************************************************
6545*6777b538SAndroid Build Coastguard Worker * *
6546*6777b538SAndroid Build Coastguard Worker * The traversal functions *
6547*6777b538SAndroid Build Coastguard Worker * *
6548*6777b538SAndroid Build Coastguard Worker ************************************************************************/
6549*6777b538SAndroid Build Coastguard Worker
6550*6777b538SAndroid Build Coastguard Worker /*
6551*6777b538SAndroid Build Coastguard Worker * A traversal function enumerates nodes along an axis.
6552*6777b538SAndroid Build Coastguard Worker * Initially it must be called with NULL, and it indicates
6553*6777b538SAndroid Build Coastguard Worker * termination on the axis by returning NULL.
6554*6777b538SAndroid Build Coastguard Worker */
6555*6777b538SAndroid Build Coastguard Worker typedef xmlNodePtr (*xmlXPathTraversalFunction)
6556*6777b538SAndroid Build Coastguard Worker (xmlXPathParserContextPtr ctxt, xmlNodePtr cur);
6557*6777b538SAndroid Build Coastguard Worker
6558*6777b538SAndroid Build Coastguard Worker /*
6559*6777b538SAndroid Build Coastguard Worker * xmlXPathTraversalFunctionExt:
6560*6777b538SAndroid Build Coastguard Worker * A traversal function enumerates nodes along an axis.
6561*6777b538SAndroid Build Coastguard Worker * Initially it must be called with NULL, and it indicates
6562*6777b538SAndroid Build Coastguard Worker * termination on the axis by returning NULL.
6563*6777b538SAndroid Build Coastguard Worker * The context node of the traversal is specified via @contextNode.
6564*6777b538SAndroid Build Coastguard Worker */
6565*6777b538SAndroid Build Coastguard Worker typedef xmlNodePtr (*xmlXPathTraversalFunctionExt)
6566*6777b538SAndroid Build Coastguard Worker (xmlNodePtr cur, xmlNodePtr contextNode);
6567*6777b538SAndroid Build Coastguard Worker
6568*6777b538SAndroid Build Coastguard Worker /*
6569*6777b538SAndroid Build Coastguard Worker * xmlXPathNodeSetMergeFunction:
6570*6777b538SAndroid Build Coastguard Worker * Used for merging node sets in xmlXPathCollectAndTest().
6571*6777b538SAndroid Build Coastguard Worker */
6572*6777b538SAndroid Build Coastguard Worker typedef xmlNodeSetPtr (*xmlXPathNodeSetMergeFunction)
6573*6777b538SAndroid Build Coastguard Worker (xmlNodeSetPtr, xmlNodeSetPtr);
6574*6777b538SAndroid Build Coastguard Worker
6575*6777b538SAndroid Build Coastguard Worker
6576*6777b538SAndroid Build Coastguard Worker /**
6577*6777b538SAndroid Build Coastguard Worker * xmlXPathNextSelf:
6578*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6579*6777b538SAndroid Build Coastguard Worker * @cur: the current node in the traversal
6580*6777b538SAndroid Build Coastguard Worker *
6581*6777b538SAndroid Build Coastguard Worker * Traversal function for the "self" direction
6582*6777b538SAndroid Build Coastguard Worker * The self axis contains just the context node itself
6583*6777b538SAndroid Build Coastguard Worker *
6584*6777b538SAndroid Build Coastguard Worker * Returns the next element following that axis
6585*6777b538SAndroid Build Coastguard Worker */
6586*6777b538SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextSelf(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6587*6777b538SAndroid Build Coastguard Worker xmlXPathNextSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6588*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6589*6777b538SAndroid Build Coastguard Worker if (cur == NULL)
6590*6777b538SAndroid Build Coastguard Worker return(ctxt->context->node);
6591*6777b538SAndroid Build Coastguard Worker return(NULL);
6592*6777b538SAndroid Build Coastguard Worker }
6593*6777b538SAndroid Build Coastguard Worker
6594*6777b538SAndroid Build Coastguard Worker /**
6595*6777b538SAndroid Build Coastguard Worker * xmlXPathNextChild:
6596*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6597*6777b538SAndroid Build Coastguard Worker * @cur: the current node in the traversal
6598*6777b538SAndroid Build Coastguard Worker *
6599*6777b538SAndroid Build Coastguard Worker * Traversal function for the "child" direction
6600*6777b538SAndroid Build Coastguard Worker * The child axis contains the children of the context node in document order.
6601*6777b538SAndroid Build Coastguard Worker *
6602*6777b538SAndroid Build Coastguard Worker * Returns the next element following that axis
6603*6777b538SAndroid Build Coastguard Worker */
6604*6777b538SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextChild(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6605*6777b538SAndroid Build Coastguard Worker xmlXPathNextChild(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6606*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6607*6777b538SAndroid Build Coastguard Worker if (cur == NULL) {
6608*6777b538SAndroid Build Coastguard Worker if (ctxt->context->node == NULL) return(NULL);
6609*6777b538SAndroid Build Coastguard Worker switch (ctxt->context->node->type) {
6610*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
6611*6777b538SAndroid Build Coastguard Worker case XML_TEXT_NODE:
6612*6777b538SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
6613*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_REF_NODE:
6614*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_NODE:
6615*6777b538SAndroid Build Coastguard Worker case XML_PI_NODE:
6616*6777b538SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
6617*6777b538SAndroid Build Coastguard Worker case XML_NOTATION_NODE:
6618*6777b538SAndroid Build Coastguard Worker case XML_DTD_NODE:
6619*6777b538SAndroid Build Coastguard Worker return(ctxt->context->node->children);
6620*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_NODE:
6621*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_TYPE_NODE:
6622*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_FRAG_NODE:
6623*6777b538SAndroid Build Coastguard Worker case XML_HTML_DOCUMENT_NODE:
6624*6777b538SAndroid Build Coastguard Worker return(((xmlDocPtr) ctxt->context->node)->children);
6625*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_DECL:
6626*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_DECL:
6627*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_DECL:
6628*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE:
6629*6777b538SAndroid Build Coastguard Worker case XML_NAMESPACE_DECL:
6630*6777b538SAndroid Build Coastguard Worker case XML_XINCLUDE_START:
6631*6777b538SAndroid Build Coastguard Worker case XML_XINCLUDE_END:
6632*6777b538SAndroid Build Coastguard Worker return(NULL);
6633*6777b538SAndroid Build Coastguard Worker }
6634*6777b538SAndroid Build Coastguard Worker return(NULL);
6635*6777b538SAndroid Build Coastguard Worker }
6636*6777b538SAndroid Build Coastguard Worker if ((cur->type == XML_DOCUMENT_NODE) ||
6637*6777b538SAndroid Build Coastguard Worker (cur->type == XML_HTML_DOCUMENT_NODE))
6638*6777b538SAndroid Build Coastguard Worker return(NULL);
6639*6777b538SAndroid Build Coastguard Worker return(cur->next);
6640*6777b538SAndroid Build Coastguard Worker }
6641*6777b538SAndroid Build Coastguard Worker
6642*6777b538SAndroid Build Coastguard Worker /**
6643*6777b538SAndroid Build Coastguard Worker * xmlXPathNextChildElement:
6644*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6645*6777b538SAndroid Build Coastguard Worker * @cur: the current node in the traversal
6646*6777b538SAndroid Build Coastguard Worker *
6647*6777b538SAndroid Build Coastguard Worker * Traversal function for the "child" direction and nodes of type element.
6648*6777b538SAndroid Build Coastguard Worker * The child axis contains the children of the context node in document order.
6649*6777b538SAndroid Build Coastguard Worker *
6650*6777b538SAndroid Build Coastguard Worker * Returns the next element following that axis
6651*6777b538SAndroid Build Coastguard Worker */
6652*6777b538SAndroid Build Coastguard Worker static xmlNodePtr
xmlXPathNextChildElement(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6653*6777b538SAndroid Build Coastguard Worker xmlXPathNextChildElement(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6654*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6655*6777b538SAndroid Build Coastguard Worker if (cur == NULL) {
6656*6777b538SAndroid Build Coastguard Worker cur = ctxt->context->node;
6657*6777b538SAndroid Build Coastguard Worker if (cur == NULL) return(NULL);
6658*6777b538SAndroid Build Coastguard Worker /*
6659*6777b538SAndroid Build Coastguard Worker * Get the first element child.
6660*6777b538SAndroid Build Coastguard Worker */
6661*6777b538SAndroid Build Coastguard Worker switch (cur->type) {
6662*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
6663*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_FRAG_NODE:
6664*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_REF_NODE: /* URGENT TODO: entify-refs as well? */
6665*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_NODE:
6666*6777b538SAndroid Build Coastguard Worker cur = cur->children;
6667*6777b538SAndroid Build Coastguard Worker if (cur != NULL) {
6668*6777b538SAndroid Build Coastguard Worker if (cur->type == XML_ELEMENT_NODE)
6669*6777b538SAndroid Build Coastguard Worker return(cur);
6670*6777b538SAndroid Build Coastguard Worker do {
6671*6777b538SAndroid Build Coastguard Worker cur = cur->next;
6672*6777b538SAndroid Build Coastguard Worker } while ((cur != NULL) &&
6673*6777b538SAndroid Build Coastguard Worker (cur->type != XML_ELEMENT_NODE));
6674*6777b538SAndroid Build Coastguard Worker return(cur);
6675*6777b538SAndroid Build Coastguard Worker }
6676*6777b538SAndroid Build Coastguard Worker return(NULL);
6677*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_NODE:
6678*6777b538SAndroid Build Coastguard Worker case XML_HTML_DOCUMENT_NODE:
6679*6777b538SAndroid Build Coastguard Worker return(xmlDocGetRootElement((xmlDocPtr) cur));
6680*6777b538SAndroid Build Coastguard Worker default:
6681*6777b538SAndroid Build Coastguard Worker return(NULL);
6682*6777b538SAndroid Build Coastguard Worker }
6683*6777b538SAndroid Build Coastguard Worker return(NULL);
6684*6777b538SAndroid Build Coastguard Worker }
6685*6777b538SAndroid Build Coastguard Worker /*
6686*6777b538SAndroid Build Coastguard Worker * Get the next sibling element node.
6687*6777b538SAndroid Build Coastguard Worker */
6688*6777b538SAndroid Build Coastguard Worker switch (cur->type) {
6689*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
6690*6777b538SAndroid Build Coastguard Worker case XML_TEXT_NODE:
6691*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_REF_NODE:
6692*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_NODE:
6693*6777b538SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
6694*6777b538SAndroid Build Coastguard Worker case XML_PI_NODE:
6695*6777b538SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
6696*6777b538SAndroid Build Coastguard Worker case XML_XINCLUDE_END:
6697*6777b538SAndroid Build Coastguard Worker break;
6698*6777b538SAndroid Build Coastguard Worker /* case XML_DTD_NODE: */ /* URGENT TODO: DTD-node as well? */
6699*6777b538SAndroid Build Coastguard Worker default:
6700*6777b538SAndroid Build Coastguard Worker return(NULL);
6701*6777b538SAndroid Build Coastguard Worker }
6702*6777b538SAndroid Build Coastguard Worker if (cur->next != NULL) {
6703*6777b538SAndroid Build Coastguard Worker if (cur->next->type == XML_ELEMENT_NODE)
6704*6777b538SAndroid Build Coastguard Worker return(cur->next);
6705*6777b538SAndroid Build Coastguard Worker cur = cur->next;
6706*6777b538SAndroid Build Coastguard Worker do {
6707*6777b538SAndroid Build Coastguard Worker cur = cur->next;
6708*6777b538SAndroid Build Coastguard Worker } while ((cur != NULL) && (cur->type != XML_ELEMENT_NODE));
6709*6777b538SAndroid Build Coastguard Worker return(cur);
6710*6777b538SAndroid Build Coastguard Worker }
6711*6777b538SAndroid Build Coastguard Worker return(NULL);
6712*6777b538SAndroid Build Coastguard Worker }
6713*6777b538SAndroid Build Coastguard Worker
6714*6777b538SAndroid Build Coastguard Worker #if 0
6715*6777b538SAndroid Build Coastguard Worker /**
6716*6777b538SAndroid Build Coastguard Worker * xmlXPathNextDescendantOrSelfElemParent:
6717*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6718*6777b538SAndroid Build Coastguard Worker * @cur: the current node in the traversal
6719*6777b538SAndroid Build Coastguard Worker *
6720*6777b538SAndroid Build Coastguard Worker * Traversal function for the "descendant-or-self" axis.
6721*6777b538SAndroid Build Coastguard Worker * Additionally it returns only nodes which can be parents of
6722*6777b538SAndroid Build Coastguard Worker * element nodes.
6723*6777b538SAndroid Build Coastguard Worker *
6724*6777b538SAndroid Build Coastguard Worker *
6725*6777b538SAndroid Build Coastguard Worker * Returns the next element following that axis
6726*6777b538SAndroid Build Coastguard Worker */
6727*6777b538SAndroid Build Coastguard Worker static xmlNodePtr
6728*6777b538SAndroid Build Coastguard Worker xmlXPathNextDescendantOrSelfElemParent(xmlNodePtr cur,
6729*6777b538SAndroid Build Coastguard Worker xmlNodePtr contextNode)
6730*6777b538SAndroid Build Coastguard Worker {
6731*6777b538SAndroid Build Coastguard Worker if (cur == NULL) {
6732*6777b538SAndroid Build Coastguard Worker if (contextNode == NULL)
6733*6777b538SAndroid Build Coastguard Worker return(NULL);
6734*6777b538SAndroid Build Coastguard Worker switch (contextNode->type) {
6735*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
6736*6777b538SAndroid Build Coastguard Worker case XML_XINCLUDE_START:
6737*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_FRAG_NODE:
6738*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_NODE:
6739*6777b538SAndroid Build Coastguard Worker case XML_HTML_DOCUMENT_NODE:
6740*6777b538SAndroid Build Coastguard Worker return(contextNode);
6741*6777b538SAndroid Build Coastguard Worker default:
6742*6777b538SAndroid Build Coastguard Worker return(NULL);
6743*6777b538SAndroid Build Coastguard Worker }
6744*6777b538SAndroid Build Coastguard Worker return(NULL);
6745*6777b538SAndroid Build Coastguard Worker } else {
6746*6777b538SAndroid Build Coastguard Worker xmlNodePtr start = cur;
6747*6777b538SAndroid Build Coastguard Worker
6748*6777b538SAndroid Build Coastguard Worker while (cur != NULL) {
6749*6777b538SAndroid Build Coastguard Worker switch (cur->type) {
6750*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
6751*6777b538SAndroid Build Coastguard Worker /* TODO: OK to have XInclude here? */
6752*6777b538SAndroid Build Coastguard Worker case XML_XINCLUDE_START:
6753*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_FRAG_NODE:
6754*6777b538SAndroid Build Coastguard Worker if (cur != start)
6755*6777b538SAndroid Build Coastguard Worker return(cur);
6756*6777b538SAndroid Build Coastguard Worker if (cur->children != NULL) {
6757*6777b538SAndroid Build Coastguard Worker cur = cur->children;
6758*6777b538SAndroid Build Coastguard Worker continue;
6759*6777b538SAndroid Build Coastguard Worker }
6760*6777b538SAndroid Build Coastguard Worker break;
6761*6777b538SAndroid Build Coastguard Worker /* Not sure if we need those here. */
6762*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_NODE:
6763*6777b538SAndroid Build Coastguard Worker case XML_HTML_DOCUMENT_NODE:
6764*6777b538SAndroid Build Coastguard Worker if (cur != start)
6765*6777b538SAndroid Build Coastguard Worker return(cur);
6766*6777b538SAndroid Build Coastguard Worker return(xmlDocGetRootElement((xmlDocPtr) cur));
6767*6777b538SAndroid Build Coastguard Worker default:
6768*6777b538SAndroid Build Coastguard Worker break;
6769*6777b538SAndroid Build Coastguard Worker }
6770*6777b538SAndroid Build Coastguard Worker
6771*6777b538SAndroid Build Coastguard Worker next_sibling:
6772*6777b538SAndroid Build Coastguard Worker if ((cur == NULL) || (cur == contextNode))
6773*6777b538SAndroid Build Coastguard Worker return(NULL);
6774*6777b538SAndroid Build Coastguard Worker if (cur->next != NULL) {
6775*6777b538SAndroid Build Coastguard Worker cur = cur->next;
6776*6777b538SAndroid Build Coastguard Worker } else {
6777*6777b538SAndroid Build Coastguard Worker cur = cur->parent;
6778*6777b538SAndroid Build Coastguard Worker goto next_sibling;
6779*6777b538SAndroid Build Coastguard Worker }
6780*6777b538SAndroid Build Coastguard Worker }
6781*6777b538SAndroid Build Coastguard Worker }
6782*6777b538SAndroid Build Coastguard Worker return(NULL);
6783*6777b538SAndroid Build Coastguard Worker }
6784*6777b538SAndroid Build Coastguard Worker #endif
6785*6777b538SAndroid Build Coastguard Worker
6786*6777b538SAndroid Build Coastguard Worker /**
6787*6777b538SAndroid Build Coastguard Worker * xmlXPathNextDescendant:
6788*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6789*6777b538SAndroid Build Coastguard Worker * @cur: the current node in the traversal
6790*6777b538SAndroid Build Coastguard Worker *
6791*6777b538SAndroid Build Coastguard Worker * Traversal function for the "descendant" direction
6792*6777b538SAndroid Build Coastguard Worker * the descendant axis contains the descendants of the context node in document
6793*6777b538SAndroid Build Coastguard Worker * order; a descendant is a child or a child of a child and so on.
6794*6777b538SAndroid Build Coastguard Worker *
6795*6777b538SAndroid Build Coastguard Worker * Returns the next element following that axis
6796*6777b538SAndroid Build Coastguard Worker */
6797*6777b538SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextDescendant(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6798*6777b538SAndroid Build Coastguard Worker xmlXPathNextDescendant(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6799*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6800*6777b538SAndroid Build Coastguard Worker if (cur == NULL) {
6801*6777b538SAndroid Build Coastguard Worker if (ctxt->context->node == NULL)
6802*6777b538SAndroid Build Coastguard Worker return(NULL);
6803*6777b538SAndroid Build Coastguard Worker if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
6804*6777b538SAndroid Build Coastguard Worker (ctxt->context->node->type == XML_NAMESPACE_DECL))
6805*6777b538SAndroid Build Coastguard Worker return(NULL);
6806*6777b538SAndroid Build Coastguard Worker
6807*6777b538SAndroid Build Coastguard Worker if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc)
6808*6777b538SAndroid Build Coastguard Worker return(ctxt->context->doc->children);
6809*6777b538SAndroid Build Coastguard Worker return(ctxt->context->node->children);
6810*6777b538SAndroid Build Coastguard Worker }
6811*6777b538SAndroid Build Coastguard Worker
6812*6777b538SAndroid Build Coastguard Worker if (cur->type == XML_NAMESPACE_DECL)
6813*6777b538SAndroid Build Coastguard Worker return(NULL);
6814*6777b538SAndroid Build Coastguard Worker if (cur->children != NULL) {
6815*6777b538SAndroid Build Coastguard Worker /*
6816*6777b538SAndroid Build Coastguard Worker * Do not descend on entities declarations
6817*6777b538SAndroid Build Coastguard Worker */
6818*6777b538SAndroid Build Coastguard Worker if (cur->children->type != XML_ENTITY_DECL) {
6819*6777b538SAndroid Build Coastguard Worker cur = cur->children;
6820*6777b538SAndroid Build Coastguard Worker /*
6821*6777b538SAndroid Build Coastguard Worker * Skip DTDs
6822*6777b538SAndroid Build Coastguard Worker */
6823*6777b538SAndroid Build Coastguard Worker if (cur->type != XML_DTD_NODE)
6824*6777b538SAndroid Build Coastguard Worker return(cur);
6825*6777b538SAndroid Build Coastguard Worker }
6826*6777b538SAndroid Build Coastguard Worker }
6827*6777b538SAndroid Build Coastguard Worker
6828*6777b538SAndroid Build Coastguard Worker if (cur == ctxt->context->node) return(NULL);
6829*6777b538SAndroid Build Coastguard Worker
6830*6777b538SAndroid Build Coastguard Worker while (cur->next != NULL) {
6831*6777b538SAndroid Build Coastguard Worker cur = cur->next;
6832*6777b538SAndroid Build Coastguard Worker if ((cur->type != XML_ENTITY_DECL) &&
6833*6777b538SAndroid Build Coastguard Worker (cur->type != XML_DTD_NODE))
6834*6777b538SAndroid Build Coastguard Worker return(cur);
6835*6777b538SAndroid Build Coastguard Worker }
6836*6777b538SAndroid Build Coastguard Worker
6837*6777b538SAndroid Build Coastguard Worker do {
6838*6777b538SAndroid Build Coastguard Worker cur = cur->parent;
6839*6777b538SAndroid Build Coastguard Worker if (cur == NULL) break;
6840*6777b538SAndroid Build Coastguard Worker if (cur == ctxt->context->node) return(NULL);
6841*6777b538SAndroid Build Coastguard Worker if (cur->next != NULL) {
6842*6777b538SAndroid Build Coastguard Worker cur = cur->next;
6843*6777b538SAndroid Build Coastguard Worker return(cur);
6844*6777b538SAndroid Build Coastguard Worker }
6845*6777b538SAndroid Build Coastguard Worker } while (cur != NULL);
6846*6777b538SAndroid Build Coastguard Worker return(cur);
6847*6777b538SAndroid Build Coastguard Worker }
6848*6777b538SAndroid Build Coastguard Worker
6849*6777b538SAndroid Build Coastguard Worker /**
6850*6777b538SAndroid Build Coastguard Worker * xmlXPathNextDescendantOrSelf:
6851*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6852*6777b538SAndroid Build Coastguard Worker * @cur: the current node in the traversal
6853*6777b538SAndroid Build Coastguard Worker *
6854*6777b538SAndroid Build Coastguard Worker * Traversal function for the "descendant-or-self" direction
6855*6777b538SAndroid Build Coastguard Worker * the descendant-or-self axis contains the context node and the descendants
6856*6777b538SAndroid Build Coastguard Worker * of the context node in document order; thus the context node is the first
6857*6777b538SAndroid Build Coastguard Worker * node on the axis, and the first child of the context node is the second node
6858*6777b538SAndroid Build Coastguard Worker * on the axis
6859*6777b538SAndroid Build Coastguard Worker *
6860*6777b538SAndroid Build Coastguard Worker * Returns the next element following that axis
6861*6777b538SAndroid Build Coastguard Worker */
6862*6777b538SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextDescendantOrSelf(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6863*6777b538SAndroid Build Coastguard Worker xmlXPathNextDescendantOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6864*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6865*6777b538SAndroid Build Coastguard Worker if (cur == NULL)
6866*6777b538SAndroid Build Coastguard Worker return(ctxt->context->node);
6867*6777b538SAndroid Build Coastguard Worker
6868*6777b538SAndroid Build Coastguard Worker if (ctxt->context->node == NULL)
6869*6777b538SAndroid Build Coastguard Worker return(NULL);
6870*6777b538SAndroid Build Coastguard Worker if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
6871*6777b538SAndroid Build Coastguard Worker (ctxt->context->node->type == XML_NAMESPACE_DECL))
6872*6777b538SAndroid Build Coastguard Worker return(NULL);
6873*6777b538SAndroid Build Coastguard Worker
6874*6777b538SAndroid Build Coastguard Worker return(xmlXPathNextDescendant(ctxt, cur));
6875*6777b538SAndroid Build Coastguard Worker }
6876*6777b538SAndroid Build Coastguard Worker
6877*6777b538SAndroid Build Coastguard Worker /**
6878*6777b538SAndroid Build Coastguard Worker * xmlXPathNextParent:
6879*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6880*6777b538SAndroid Build Coastguard Worker * @cur: the current node in the traversal
6881*6777b538SAndroid Build Coastguard Worker *
6882*6777b538SAndroid Build Coastguard Worker * Traversal function for the "parent" direction
6883*6777b538SAndroid Build Coastguard Worker * The parent axis contains the parent of the context node, if there is one.
6884*6777b538SAndroid Build Coastguard Worker *
6885*6777b538SAndroid Build Coastguard Worker * Returns the next element following that axis
6886*6777b538SAndroid Build Coastguard Worker */
6887*6777b538SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextParent(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6888*6777b538SAndroid Build Coastguard Worker xmlXPathNextParent(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6889*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6890*6777b538SAndroid Build Coastguard Worker /*
6891*6777b538SAndroid Build Coastguard Worker * the parent of an attribute or namespace node is the element
6892*6777b538SAndroid Build Coastguard Worker * to which the attribute or namespace node is attached
6893*6777b538SAndroid Build Coastguard Worker * Namespace handling !!!
6894*6777b538SAndroid Build Coastguard Worker */
6895*6777b538SAndroid Build Coastguard Worker if (cur == NULL) {
6896*6777b538SAndroid Build Coastguard Worker if (ctxt->context->node == NULL) return(NULL);
6897*6777b538SAndroid Build Coastguard Worker switch (ctxt->context->node->type) {
6898*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
6899*6777b538SAndroid Build Coastguard Worker case XML_TEXT_NODE:
6900*6777b538SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
6901*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_REF_NODE:
6902*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_NODE:
6903*6777b538SAndroid Build Coastguard Worker case XML_PI_NODE:
6904*6777b538SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
6905*6777b538SAndroid Build Coastguard Worker case XML_NOTATION_NODE:
6906*6777b538SAndroid Build Coastguard Worker case XML_DTD_NODE:
6907*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_DECL:
6908*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_DECL:
6909*6777b538SAndroid Build Coastguard Worker case XML_XINCLUDE_START:
6910*6777b538SAndroid Build Coastguard Worker case XML_XINCLUDE_END:
6911*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_DECL:
6912*6777b538SAndroid Build Coastguard Worker if (ctxt->context->node->parent == NULL)
6913*6777b538SAndroid Build Coastguard Worker return((xmlNodePtr) ctxt->context->doc);
6914*6777b538SAndroid Build Coastguard Worker if ((ctxt->context->node->parent->type == XML_ELEMENT_NODE) &&
6915*6777b538SAndroid Build Coastguard Worker ((ctxt->context->node->parent->name[0] == ' ') ||
6916*6777b538SAndroid Build Coastguard Worker (xmlStrEqual(ctxt->context->node->parent->name,
6917*6777b538SAndroid Build Coastguard Worker BAD_CAST "fake node libxslt"))))
6918*6777b538SAndroid Build Coastguard Worker return(NULL);
6919*6777b538SAndroid Build Coastguard Worker return(ctxt->context->node->parent);
6920*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE: {
6921*6777b538SAndroid Build Coastguard Worker xmlAttrPtr att = (xmlAttrPtr) ctxt->context->node;
6922*6777b538SAndroid Build Coastguard Worker
6923*6777b538SAndroid Build Coastguard Worker return(att->parent);
6924*6777b538SAndroid Build Coastguard Worker }
6925*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_NODE:
6926*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_TYPE_NODE:
6927*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_FRAG_NODE:
6928*6777b538SAndroid Build Coastguard Worker case XML_HTML_DOCUMENT_NODE:
6929*6777b538SAndroid Build Coastguard Worker return(NULL);
6930*6777b538SAndroid Build Coastguard Worker case XML_NAMESPACE_DECL: {
6931*6777b538SAndroid Build Coastguard Worker xmlNsPtr ns = (xmlNsPtr) ctxt->context->node;
6932*6777b538SAndroid Build Coastguard Worker
6933*6777b538SAndroid Build Coastguard Worker if ((ns->next != NULL) &&
6934*6777b538SAndroid Build Coastguard Worker (ns->next->type != XML_NAMESPACE_DECL))
6935*6777b538SAndroid Build Coastguard Worker return((xmlNodePtr) ns->next);
6936*6777b538SAndroid Build Coastguard Worker return(NULL);
6937*6777b538SAndroid Build Coastguard Worker }
6938*6777b538SAndroid Build Coastguard Worker }
6939*6777b538SAndroid Build Coastguard Worker }
6940*6777b538SAndroid Build Coastguard Worker return(NULL);
6941*6777b538SAndroid Build Coastguard Worker }
6942*6777b538SAndroid Build Coastguard Worker
6943*6777b538SAndroid Build Coastguard Worker /**
6944*6777b538SAndroid Build Coastguard Worker * xmlXPathNextAncestor:
6945*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
6946*6777b538SAndroid Build Coastguard Worker * @cur: the current node in the traversal
6947*6777b538SAndroid Build Coastguard Worker *
6948*6777b538SAndroid Build Coastguard Worker * Traversal function for the "ancestor" direction
6949*6777b538SAndroid Build Coastguard Worker * the ancestor axis contains the ancestors of the context node; the ancestors
6950*6777b538SAndroid Build Coastguard Worker * of the context node consist of the parent of context node and the parent's
6951*6777b538SAndroid Build Coastguard Worker * parent and so on; the nodes are ordered in reverse document order; thus the
6952*6777b538SAndroid Build Coastguard Worker * parent is the first node on the axis, and the parent's parent is the second
6953*6777b538SAndroid Build Coastguard Worker * node on the axis
6954*6777b538SAndroid Build Coastguard Worker *
6955*6777b538SAndroid Build Coastguard Worker * Returns the next element following that axis
6956*6777b538SAndroid Build Coastguard Worker */
6957*6777b538SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextAncestor(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)6958*6777b538SAndroid Build Coastguard Worker xmlXPathNextAncestor(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
6959*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
6960*6777b538SAndroid Build Coastguard Worker /*
6961*6777b538SAndroid Build Coastguard Worker * the parent of an attribute or namespace node is the element
6962*6777b538SAndroid Build Coastguard Worker * to which the attribute or namespace node is attached
6963*6777b538SAndroid Build Coastguard Worker * !!!!!!!!!!!!!
6964*6777b538SAndroid Build Coastguard Worker */
6965*6777b538SAndroid Build Coastguard Worker if (cur == NULL) {
6966*6777b538SAndroid Build Coastguard Worker if (ctxt->context->node == NULL) return(NULL);
6967*6777b538SAndroid Build Coastguard Worker switch (ctxt->context->node->type) {
6968*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
6969*6777b538SAndroid Build Coastguard Worker case XML_TEXT_NODE:
6970*6777b538SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
6971*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_REF_NODE:
6972*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_NODE:
6973*6777b538SAndroid Build Coastguard Worker case XML_PI_NODE:
6974*6777b538SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
6975*6777b538SAndroid Build Coastguard Worker case XML_DTD_NODE:
6976*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_DECL:
6977*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_DECL:
6978*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_DECL:
6979*6777b538SAndroid Build Coastguard Worker case XML_NOTATION_NODE:
6980*6777b538SAndroid Build Coastguard Worker case XML_XINCLUDE_START:
6981*6777b538SAndroid Build Coastguard Worker case XML_XINCLUDE_END:
6982*6777b538SAndroid Build Coastguard Worker if (ctxt->context->node->parent == NULL)
6983*6777b538SAndroid Build Coastguard Worker return((xmlNodePtr) ctxt->context->doc);
6984*6777b538SAndroid Build Coastguard Worker if ((ctxt->context->node->parent->type == XML_ELEMENT_NODE) &&
6985*6777b538SAndroid Build Coastguard Worker ((ctxt->context->node->parent->name[0] == ' ') ||
6986*6777b538SAndroid Build Coastguard Worker (xmlStrEqual(ctxt->context->node->parent->name,
6987*6777b538SAndroid Build Coastguard Worker BAD_CAST "fake node libxslt"))))
6988*6777b538SAndroid Build Coastguard Worker return(NULL);
6989*6777b538SAndroid Build Coastguard Worker return(ctxt->context->node->parent);
6990*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE: {
6991*6777b538SAndroid Build Coastguard Worker xmlAttrPtr tmp = (xmlAttrPtr) ctxt->context->node;
6992*6777b538SAndroid Build Coastguard Worker
6993*6777b538SAndroid Build Coastguard Worker return(tmp->parent);
6994*6777b538SAndroid Build Coastguard Worker }
6995*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_NODE:
6996*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_TYPE_NODE:
6997*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_FRAG_NODE:
6998*6777b538SAndroid Build Coastguard Worker case XML_HTML_DOCUMENT_NODE:
6999*6777b538SAndroid Build Coastguard Worker return(NULL);
7000*6777b538SAndroid Build Coastguard Worker case XML_NAMESPACE_DECL: {
7001*6777b538SAndroid Build Coastguard Worker xmlNsPtr ns = (xmlNsPtr) ctxt->context->node;
7002*6777b538SAndroid Build Coastguard Worker
7003*6777b538SAndroid Build Coastguard Worker if ((ns->next != NULL) &&
7004*6777b538SAndroid Build Coastguard Worker (ns->next->type != XML_NAMESPACE_DECL))
7005*6777b538SAndroid Build Coastguard Worker return((xmlNodePtr) ns->next);
7006*6777b538SAndroid Build Coastguard Worker /* Bad, how did that namespace end up here ? */
7007*6777b538SAndroid Build Coastguard Worker return(NULL);
7008*6777b538SAndroid Build Coastguard Worker }
7009*6777b538SAndroid Build Coastguard Worker }
7010*6777b538SAndroid Build Coastguard Worker return(NULL);
7011*6777b538SAndroid Build Coastguard Worker }
7012*6777b538SAndroid Build Coastguard Worker if (cur == ctxt->context->doc->children)
7013*6777b538SAndroid Build Coastguard Worker return((xmlNodePtr) ctxt->context->doc);
7014*6777b538SAndroid Build Coastguard Worker if (cur == (xmlNodePtr) ctxt->context->doc)
7015*6777b538SAndroid Build Coastguard Worker return(NULL);
7016*6777b538SAndroid Build Coastguard Worker switch (cur->type) {
7017*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
7018*6777b538SAndroid Build Coastguard Worker case XML_TEXT_NODE:
7019*6777b538SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
7020*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_REF_NODE:
7021*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_NODE:
7022*6777b538SAndroid Build Coastguard Worker case XML_PI_NODE:
7023*6777b538SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
7024*6777b538SAndroid Build Coastguard Worker case XML_NOTATION_NODE:
7025*6777b538SAndroid Build Coastguard Worker case XML_DTD_NODE:
7026*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_DECL:
7027*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_DECL:
7028*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_DECL:
7029*6777b538SAndroid Build Coastguard Worker case XML_XINCLUDE_START:
7030*6777b538SAndroid Build Coastguard Worker case XML_XINCLUDE_END:
7031*6777b538SAndroid Build Coastguard Worker if (cur->parent == NULL)
7032*6777b538SAndroid Build Coastguard Worker return(NULL);
7033*6777b538SAndroid Build Coastguard Worker if ((cur->parent->type == XML_ELEMENT_NODE) &&
7034*6777b538SAndroid Build Coastguard Worker ((cur->parent->name[0] == ' ') ||
7035*6777b538SAndroid Build Coastguard Worker (xmlStrEqual(cur->parent->name,
7036*6777b538SAndroid Build Coastguard Worker BAD_CAST "fake node libxslt"))))
7037*6777b538SAndroid Build Coastguard Worker return(NULL);
7038*6777b538SAndroid Build Coastguard Worker return(cur->parent);
7039*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE: {
7040*6777b538SAndroid Build Coastguard Worker xmlAttrPtr att = (xmlAttrPtr) cur;
7041*6777b538SAndroid Build Coastguard Worker
7042*6777b538SAndroid Build Coastguard Worker return(att->parent);
7043*6777b538SAndroid Build Coastguard Worker }
7044*6777b538SAndroid Build Coastguard Worker case XML_NAMESPACE_DECL: {
7045*6777b538SAndroid Build Coastguard Worker xmlNsPtr ns = (xmlNsPtr) cur;
7046*6777b538SAndroid Build Coastguard Worker
7047*6777b538SAndroid Build Coastguard Worker if ((ns->next != NULL) &&
7048*6777b538SAndroid Build Coastguard Worker (ns->next->type != XML_NAMESPACE_DECL))
7049*6777b538SAndroid Build Coastguard Worker return((xmlNodePtr) ns->next);
7050*6777b538SAndroid Build Coastguard Worker /* Bad, how did that namespace end up here ? */
7051*6777b538SAndroid Build Coastguard Worker return(NULL);
7052*6777b538SAndroid Build Coastguard Worker }
7053*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_NODE:
7054*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_TYPE_NODE:
7055*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_FRAG_NODE:
7056*6777b538SAndroid Build Coastguard Worker case XML_HTML_DOCUMENT_NODE:
7057*6777b538SAndroid Build Coastguard Worker return(NULL);
7058*6777b538SAndroid Build Coastguard Worker }
7059*6777b538SAndroid Build Coastguard Worker return(NULL);
7060*6777b538SAndroid Build Coastguard Worker }
7061*6777b538SAndroid Build Coastguard Worker
7062*6777b538SAndroid Build Coastguard Worker /**
7063*6777b538SAndroid Build Coastguard Worker * xmlXPathNextAncestorOrSelf:
7064*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7065*6777b538SAndroid Build Coastguard Worker * @cur: the current node in the traversal
7066*6777b538SAndroid Build Coastguard Worker *
7067*6777b538SAndroid Build Coastguard Worker * Traversal function for the "ancestor-or-self" direction
7068*6777b538SAndroid Build Coastguard Worker * he ancestor-or-self axis contains the context node and ancestors of
7069*6777b538SAndroid Build Coastguard Worker * the context node in reverse document order; thus the context node is
7070*6777b538SAndroid Build Coastguard Worker * the first node on the axis, and the context node's parent the second;
7071*6777b538SAndroid Build Coastguard Worker * parent here is defined the same as with the parent axis.
7072*6777b538SAndroid Build Coastguard Worker *
7073*6777b538SAndroid Build Coastguard Worker * Returns the next element following that axis
7074*6777b538SAndroid Build Coastguard Worker */
7075*6777b538SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextAncestorOrSelf(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)7076*6777b538SAndroid Build Coastguard Worker xmlXPathNextAncestorOrSelf(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
7077*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
7078*6777b538SAndroid Build Coastguard Worker if (cur == NULL)
7079*6777b538SAndroid Build Coastguard Worker return(ctxt->context->node);
7080*6777b538SAndroid Build Coastguard Worker return(xmlXPathNextAncestor(ctxt, cur));
7081*6777b538SAndroid Build Coastguard Worker }
7082*6777b538SAndroid Build Coastguard Worker
7083*6777b538SAndroid Build Coastguard Worker /**
7084*6777b538SAndroid Build Coastguard Worker * xmlXPathNextFollowingSibling:
7085*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7086*6777b538SAndroid Build Coastguard Worker * @cur: the current node in the traversal
7087*6777b538SAndroid Build Coastguard Worker *
7088*6777b538SAndroid Build Coastguard Worker * Traversal function for the "following-sibling" direction
7089*6777b538SAndroid Build Coastguard Worker * The following-sibling axis contains the following siblings of the context
7090*6777b538SAndroid Build Coastguard Worker * node in document order.
7091*6777b538SAndroid Build Coastguard Worker *
7092*6777b538SAndroid Build Coastguard Worker * Returns the next element following that axis
7093*6777b538SAndroid Build Coastguard Worker */
7094*6777b538SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextFollowingSibling(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)7095*6777b538SAndroid Build Coastguard Worker xmlXPathNextFollowingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
7096*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
7097*6777b538SAndroid Build Coastguard Worker if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
7098*6777b538SAndroid Build Coastguard Worker (ctxt->context->node->type == XML_NAMESPACE_DECL))
7099*6777b538SAndroid Build Coastguard Worker return(NULL);
7100*6777b538SAndroid Build Coastguard Worker if (cur == (xmlNodePtr) ctxt->context->doc)
7101*6777b538SAndroid Build Coastguard Worker return(NULL);
7102*6777b538SAndroid Build Coastguard Worker if (cur == NULL)
7103*6777b538SAndroid Build Coastguard Worker return(ctxt->context->node->next);
7104*6777b538SAndroid Build Coastguard Worker return(cur->next);
7105*6777b538SAndroid Build Coastguard Worker }
7106*6777b538SAndroid Build Coastguard Worker
7107*6777b538SAndroid Build Coastguard Worker /**
7108*6777b538SAndroid Build Coastguard Worker * xmlXPathNextPrecedingSibling:
7109*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7110*6777b538SAndroid Build Coastguard Worker * @cur: the current node in the traversal
7111*6777b538SAndroid Build Coastguard Worker *
7112*6777b538SAndroid Build Coastguard Worker * Traversal function for the "preceding-sibling" direction
7113*6777b538SAndroid Build Coastguard Worker * The preceding-sibling axis contains the preceding siblings of the context
7114*6777b538SAndroid Build Coastguard Worker * node in reverse document order; the first preceding sibling is first on the
7115*6777b538SAndroid Build Coastguard Worker * axis; the sibling preceding that node is the second on the axis and so on.
7116*6777b538SAndroid Build Coastguard Worker *
7117*6777b538SAndroid Build Coastguard Worker * Returns the next element following that axis
7118*6777b538SAndroid Build Coastguard Worker */
7119*6777b538SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextPrecedingSibling(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)7120*6777b538SAndroid Build Coastguard Worker xmlXPathNextPrecedingSibling(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
7121*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
7122*6777b538SAndroid Build Coastguard Worker if ((ctxt->context->node->type == XML_ATTRIBUTE_NODE) ||
7123*6777b538SAndroid Build Coastguard Worker (ctxt->context->node->type == XML_NAMESPACE_DECL))
7124*6777b538SAndroid Build Coastguard Worker return(NULL);
7125*6777b538SAndroid Build Coastguard Worker if (cur == (xmlNodePtr) ctxt->context->doc)
7126*6777b538SAndroid Build Coastguard Worker return(NULL);
7127*6777b538SAndroid Build Coastguard Worker if (cur == NULL)
7128*6777b538SAndroid Build Coastguard Worker return(ctxt->context->node->prev);
7129*6777b538SAndroid Build Coastguard Worker if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE)) {
7130*6777b538SAndroid Build Coastguard Worker cur = cur->prev;
7131*6777b538SAndroid Build Coastguard Worker if (cur == NULL)
7132*6777b538SAndroid Build Coastguard Worker return(ctxt->context->node->prev);
7133*6777b538SAndroid Build Coastguard Worker }
7134*6777b538SAndroid Build Coastguard Worker return(cur->prev);
7135*6777b538SAndroid Build Coastguard Worker }
7136*6777b538SAndroid Build Coastguard Worker
7137*6777b538SAndroid Build Coastguard Worker /**
7138*6777b538SAndroid Build Coastguard Worker * xmlXPathNextFollowing:
7139*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7140*6777b538SAndroid Build Coastguard Worker * @cur: the current node in the traversal
7141*6777b538SAndroid Build Coastguard Worker *
7142*6777b538SAndroid Build Coastguard Worker * Traversal function for the "following" direction
7143*6777b538SAndroid Build Coastguard Worker * The following axis contains all nodes in the same document as the context
7144*6777b538SAndroid Build Coastguard Worker * node that are after the context node in document order, excluding any
7145*6777b538SAndroid Build Coastguard Worker * descendants and excluding attribute nodes and namespace nodes; the nodes
7146*6777b538SAndroid Build Coastguard Worker * are ordered in document order
7147*6777b538SAndroid Build Coastguard Worker *
7148*6777b538SAndroid Build Coastguard Worker * Returns the next element following that axis
7149*6777b538SAndroid Build Coastguard Worker */
7150*6777b538SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextFollowing(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)7151*6777b538SAndroid Build Coastguard Worker xmlXPathNextFollowing(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
7152*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
7153*6777b538SAndroid Build Coastguard Worker if ((cur != NULL) && (cur->type != XML_ATTRIBUTE_NODE) &&
7154*6777b538SAndroid Build Coastguard Worker (cur->type != XML_NAMESPACE_DECL) && (cur->children != NULL))
7155*6777b538SAndroid Build Coastguard Worker return(cur->children);
7156*6777b538SAndroid Build Coastguard Worker
7157*6777b538SAndroid Build Coastguard Worker if (cur == NULL) {
7158*6777b538SAndroid Build Coastguard Worker cur = ctxt->context->node;
7159*6777b538SAndroid Build Coastguard Worker if (cur->type == XML_ATTRIBUTE_NODE) {
7160*6777b538SAndroid Build Coastguard Worker cur = cur->parent;
7161*6777b538SAndroid Build Coastguard Worker } else if (cur->type == XML_NAMESPACE_DECL) {
7162*6777b538SAndroid Build Coastguard Worker xmlNsPtr ns = (xmlNsPtr) cur;
7163*6777b538SAndroid Build Coastguard Worker
7164*6777b538SAndroid Build Coastguard Worker if ((ns->next == NULL) ||
7165*6777b538SAndroid Build Coastguard Worker (ns->next->type == XML_NAMESPACE_DECL))
7166*6777b538SAndroid Build Coastguard Worker return (NULL);
7167*6777b538SAndroid Build Coastguard Worker cur = (xmlNodePtr) ns->next;
7168*6777b538SAndroid Build Coastguard Worker }
7169*6777b538SAndroid Build Coastguard Worker }
7170*6777b538SAndroid Build Coastguard Worker if (cur == NULL) return(NULL) ; /* ERROR */
7171*6777b538SAndroid Build Coastguard Worker if (cur->next != NULL) return(cur->next) ;
7172*6777b538SAndroid Build Coastguard Worker do {
7173*6777b538SAndroid Build Coastguard Worker cur = cur->parent;
7174*6777b538SAndroid Build Coastguard Worker if (cur == NULL) break;
7175*6777b538SAndroid Build Coastguard Worker if (cur == (xmlNodePtr) ctxt->context->doc) return(NULL);
7176*6777b538SAndroid Build Coastguard Worker if (cur->next != NULL) return(cur->next);
7177*6777b538SAndroid Build Coastguard Worker } while (cur != NULL);
7178*6777b538SAndroid Build Coastguard Worker return(cur);
7179*6777b538SAndroid Build Coastguard Worker }
7180*6777b538SAndroid Build Coastguard Worker
7181*6777b538SAndroid Build Coastguard Worker /*
7182*6777b538SAndroid Build Coastguard Worker * xmlXPathIsAncestor:
7183*6777b538SAndroid Build Coastguard Worker * @ancestor: the ancestor node
7184*6777b538SAndroid Build Coastguard Worker * @node: the current node
7185*6777b538SAndroid Build Coastguard Worker *
7186*6777b538SAndroid Build Coastguard Worker * Check that @ancestor is a @node's ancestor
7187*6777b538SAndroid Build Coastguard Worker *
7188*6777b538SAndroid Build Coastguard Worker * returns 1 if @ancestor is a @node's ancestor, 0 otherwise.
7189*6777b538SAndroid Build Coastguard Worker */
7190*6777b538SAndroid Build Coastguard Worker static int
xmlXPathIsAncestor(xmlNodePtr ancestor,xmlNodePtr node)7191*6777b538SAndroid Build Coastguard Worker xmlXPathIsAncestor(xmlNodePtr ancestor, xmlNodePtr node) {
7192*6777b538SAndroid Build Coastguard Worker if ((ancestor == NULL) || (node == NULL)) return(0);
7193*6777b538SAndroid Build Coastguard Worker if (node->type == XML_NAMESPACE_DECL)
7194*6777b538SAndroid Build Coastguard Worker return(0);
7195*6777b538SAndroid Build Coastguard Worker if (ancestor->type == XML_NAMESPACE_DECL)
7196*6777b538SAndroid Build Coastguard Worker return(0);
7197*6777b538SAndroid Build Coastguard Worker /* nodes need to be in the same document */
7198*6777b538SAndroid Build Coastguard Worker if (ancestor->doc != node->doc) return(0);
7199*6777b538SAndroid Build Coastguard Worker /* avoid searching if ancestor or node is the root node */
7200*6777b538SAndroid Build Coastguard Worker if (ancestor == (xmlNodePtr) node->doc) return(1);
7201*6777b538SAndroid Build Coastguard Worker if (node == (xmlNodePtr) ancestor->doc) return(0);
7202*6777b538SAndroid Build Coastguard Worker while (node->parent != NULL) {
7203*6777b538SAndroid Build Coastguard Worker if (node->parent == ancestor)
7204*6777b538SAndroid Build Coastguard Worker return(1);
7205*6777b538SAndroid Build Coastguard Worker node = node->parent;
7206*6777b538SAndroid Build Coastguard Worker }
7207*6777b538SAndroid Build Coastguard Worker return(0);
7208*6777b538SAndroid Build Coastguard Worker }
7209*6777b538SAndroid Build Coastguard Worker
7210*6777b538SAndroid Build Coastguard Worker /**
7211*6777b538SAndroid Build Coastguard Worker * xmlXPathNextPreceding:
7212*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7213*6777b538SAndroid Build Coastguard Worker * @cur: the current node in the traversal
7214*6777b538SAndroid Build Coastguard Worker *
7215*6777b538SAndroid Build Coastguard Worker * Traversal function for the "preceding" direction
7216*6777b538SAndroid Build Coastguard Worker * the preceding axis contains all nodes in the same document as the context
7217*6777b538SAndroid Build Coastguard Worker * node that are before the context node in document order, excluding any
7218*6777b538SAndroid Build Coastguard Worker * ancestors and excluding attribute nodes and namespace nodes; the nodes are
7219*6777b538SAndroid Build Coastguard Worker * ordered in reverse document order
7220*6777b538SAndroid Build Coastguard Worker *
7221*6777b538SAndroid Build Coastguard Worker * Returns the next element following that axis
7222*6777b538SAndroid Build Coastguard Worker */
7223*6777b538SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextPreceding(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)7224*6777b538SAndroid Build Coastguard Worker xmlXPathNextPreceding(xmlXPathParserContextPtr ctxt, xmlNodePtr cur)
7225*6777b538SAndroid Build Coastguard Worker {
7226*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
7227*6777b538SAndroid Build Coastguard Worker if (cur == NULL) {
7228*6777b538SAndroid Build Coastguard Worker cur = ctxt->context->node;
7229*6777b538SAndroid Build Coastguard Worker if (cur->type == XML_ATTRIBUTE_NODE) {
7230*6777b538SAndroid Build Coastguard Worker cur = cur->parent;
7231*6777b538SAndroid Build Coastguard Worker } else if (cur->type == XML_NAMESPACE_DECL) {
7232*6777b538SAndroid Build Coastguard Worker xmlNsPtr ns = (xmlNsPtr) cur;
7233*6777b538SAndroid Build Coastguard Worker
7234*6777b538SAndroid Build Coastguard Worker if ((ns->next == NULL) ||
7235*6777b538SAndroid Build Coastguard Worker (ns->next->type == XML_NAMESPACE_DECL))
7236*6777b538SAndroid Build Coastguard Worker return (NULL);
7237*6777b538SAndroid Build Coastguard Worker cur = (xmlNodePtr) ns->next;
7238*6777b538SAndroid Build Coastguard Worker }
7239*6777b538SAndroid Build Coastguard Worker }
7240*6777b538SAndroid Build Coastguard Worker if ((cur == NULL) || (cur->type == XML_NAMESPACE_DECL))
7241*6777b538SAndroid Build Coastguard Worker return (NULL);
7242*6777b538SAndroid Build Coastguard Worker if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE))
7243*6777b538SAndroid Build Coastguard Worker cur = cur->prev;
7244*6777b538SAndroid Build Coastguard Worker do {
7245*6777b538SAndroid Build Coastguard Worker if (cur->prev != NULL) {
7246*6777b538SAndroid Build Coastguard Worker for (cur = cur->prev; cur->last != NULL; cur = cur->last) ;
7247*6777b538SAndroid Build Coastguard Worker return (cur);
7248*6777b538SAndroid Build Coastguard Worker }
7249*6777b538SAndroid Build Coastguard Worker
7250*6777b538SAndroid Build Coastguard Worker cur = cur->parent;
7251*6777b538SAndroid Build Coastguard Worker if (cur == NULL)
7252*6777b538SAndroid Build Coastguard Worker return (NULL);
7253*6777b538SAndroid Build Coastguard Worker if (cur == ctxt->context->doc->children)
7254*6777b538SAndroid Build Coastguard Worker return (NULL);
7255*6777b538SAndroid Build Coastguard Worker } while (xmlXPathIsAncestor(cur, ctxt->context->node));
7256*6777b538SAndroid Build Coastguard Worker return (cur);
7257*6777b538SAndroid Build Coastguard Worker }
7258*6777b538SAndroid Build Coastguard Worker
7259*6777b538SAndroid Build Coastguard Worker /**
7260*6777b538SAndroid Build Coastguard Worker * xmlXPathNextPrecedingInternal:
7261*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7262*6777b538SAndroid Build Coastguard Worker * @cur: the current node in the traversal
7263*6777b538SAndroid Build Coastguard Worker *
7264*6777b538SAndroid Build Coastguard Worker * Traversal function for the "preceding" direction
7265*6777b538SAndroid Build Coastguard Worker * the preceding axis contains all nodes in the same document as the context
7266*6777b538SAndroid Build Coastguard Worker * node that are before the context node in document order, excluding any
7267*6777b538SAndroid Build Coastguard Worker * ancestors and excluding attribute nodes and namespace nodes; the nodes are
7268*6777b538SAndroid Build Coastguard Worker * ordered in reverse document order
7269*6777b538SAndroid Build Coastguard Worker * This is a faster implementation but internal only since it requires a
7270*6777b538SAndroid Build Coastguard Worker * state kept in the parser context: ctxt->ancestor.
7271*6777b538SAndroid Build Coastguard Worker *
7272*6777b538SAndroid Build Coastguard Worker * Returns the next element following that axis
7273*6777b538SAndroid Build Coastguard Worker */
7274*6777b538SAndroid Build Coastguard Worker static xmlNodePtr
xmlXPathNextPrecedingInternal(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)7275*6777b538SAndroid Build Coastguard Worker xmlXPathNextPrecedingInternal(xmlXPathParserContextPtr ctxt,
7276*6777b538SAndroid Build Coastguard Worker xmlNodePtr cur)
7277*6777b538SAndroid Build Coastguard Worker {
7278*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
7279*6777b538SAndroid Build Coastguard Worker if (cur == NULL) {
7280*6777b538SAndroid Build Coastguard Worker cur = ctxt->context->node;
7281*6777b538SAndroid Build Coastguard Worker if (cur == NULL)
7282*6777b538SAndroid Build Coastguard Worker return (NULL);
7283*6777b538SAndroid Build Coastguard Worker if (cur->type == XML_ATTRIBUTE_NODE) {
7284*6777b538SAndroid Build Coastguard Worker cur = cur->parent;
7285*6777b538SAndroid Build Coastguard Worker } else if (cur->type == XML_NAMESPACE_DECL) {
7286*6777b538SAndroid Build Coastguard Worker xmlNsPtr ns = (xmlNsPtr) cur;
7287*6777b538SAndroid Build Coastguard Worker
7288*6777b538SAndroid Build Coastguard Worker if ((ns->next == NULL) ||
7289*6777b538SAndroid Build Coastguard Worker (ns->next->type == XML_NAMESPACE_DECL))
7290*6777b538SAndroid Build Coastguard Worker return (NULL);
7291*6777b538SAndroid Build Coastguard Worker cur = (xmlNodePtr) ns->next;
7292*6777b538SAndroid Build Coastguard Worker }
7293*6777b538SAndroid Build Coastguard Worker ctxt->ancestor = cur->parent;
7294*6777b538SAndroid Build Coastguard Worker }
7295*6777b538SAndroid Build Coastguard Worker if (cur->type == XML_NAMESPACE_DECL)
7296*6777b538SAndroid Build Coastguard Worker return(NULL);
7297*6777b538SAndroid Build Coastguard Worker if ((cur->prev != NULL) && (cur->prev->type == XML_DTD_NODE))
7298*6777b538SAndroid Build Coastguard Worker cur = cur->prev;
7299*6777b538SAndroid Build Coastguard Worker while (cur->prev == NULL) {
7300*6777b538SAndroid Build Coastguard Worker cur = cur->parent;
7301*6777b538SAndroid Build Coastguard Worker if (cur == NULL)
7302*6777b538SAndroid Build Coastguard Worker return (NULL);
7303*6777b538SAndroid Build Coastguard Worker if (cur == ctxt->context->doc->children)
7304*6777b538SAndroid Build Coastguard Worker return (NULL);
7305*6777b538SAndroid Build Coastguard Worker if (cur != ctxt->ancestor)
7306*6777b538SAndroid Build Coastguard Worker return (cur);
7307*6777b538SAndroid Build Coastguard Worker ctxt->ancestor = cur->parent;
7308*6777b538SAndroid Build Coastguard Worker }
7309*6777b538SAndroid Build Coastguard Worker cur = cur->prev;
7310*6777b538SAndroid Build Coastguard Worker while (cur->last != NULL)
7311*6777b538SAndroid Build Coastguard Worker cur = cur->last;
7312*6777b538SAndroid Build Coastguard Worker return (cur);
7313*6777b538SAndroid Build Coastguard Worker }
7314*6777b538SAndroid Build Coastguard Worker
7315*6777b538SAndroid Build Coastguard Worker /**
7316*6777b538SAndroid Build Coastguard Worker * xmlXPathNextNamespace:
7317*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7318*6777b538SAndroid Build Coastguard Worker * @cur: the current attribute in the traversal
7319*6777b538SAndroid Build Coastguard Worker *
7320*6777b538SAndroid Build Coastguard Worker * Traversal function for the "namespace" direction
7321*6777b538SAndroid Build Coastguard Worker * the namespace axis contains the namespace nodes of the context node;
7322*6777b538SAndroid Build Coastguard Worker * the order of nodes on this axis is implementation-defined; the axis will
7323*6777b538SAndroid Build Coastguard Worker * be empty unless the context node is an element
7324*6777b538SAndroid Build Coastguard Worker *
7325*6777b538SAndroid Build Coastguard Worker * We keep the XML namespace node at the end of the list.
7326*6777b538SAndroid Build Coastguard Worker *
7327*6777b538SAndroid Build Coastguard Worker * Returns the next element following that axis
7328*6777b538SAndroid Build Coastguard Worker */
7329*6777b538SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)7330*6777b538SAndroid Build Coastguard Worker xmlXPathNextNamespace(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
7331*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
7332*6777b538SAndroid Build Coastguard Worker if (ctxt->context->node->type != XML_ELEMENT_NODE) return(NULL);
7333*6777b538SAndroid Build Coastguard Worker if (cur == NULL) {
7334*6777b538SAndroid Build Coastguard Worker if (ctxt->context->tmpNsList != NULL)
7335*6777b538SAndroid Build Coastguard Worker xmlFree(ctxt->context->tmpNsList);
7336*6777b538SAndroid Build Coastguard Worker ctxt->context->tmpNsNr = 0;
7337*6777b538SAndroid Build Coastguard Worker if (xmlGetNsListSafe(ctxt->context->doc, ctxt->context->node,
7338*6777b538SAndroid Build Coastguard Worker &ctxt->context->tmpNsList) < 0) {
7339*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7340*6777b538SAndroid Build Coastguard Worker return(NULL);
7341*6777b538SAndroid Build Coastguard Worker }
7342*6777b538SAndroid Build Coastguard Worker if (ctxt->context->tmpNsList != NULL) {
7343*6777b538SAndroid Build Coastguard Worker while (ctxt->context->tmpNsList[ctxt->context->tmpNsNr] != NULL) {
7344*6777b538SAndroid Build Coastguard Worker ctxt->context->tmpNsNr++;
7345*6777b538SAndroid Build Coastguard Worker }
7346*6777b538SAndroid Build Coastguard Worker }
7347*6777b538SAndroid Build Coastguard Worker return((xmlNodePtr) xmlXPathXMLNamespace);
7348*6777b538SAndroid Build Coastguard Worker }
7349*6777b538SAndroid Build Coastguard Worker if (ctxt->context->tmpNsNr > 0) {
7350*6777b538SAndroid Build Coastguard Worker return (xmlNodePtr)ctxt->context->tmpNsList[--ctxt->context->tmpNsNr];
7351*6777b538SAndroid Build Coastguard Worker } else {
7352*6777b538SAndroid Build Coastguard Worker if (ctxt->context->tmpNsList != NULL)
7353*6777b538SAndroid Build Coastguard Worker xmlFree(ctxt->context->tmpNsList);
7354*6777b538SAndroid Build Coastguard Worker ctxt->context->tmpNsList = NULL;
7355*6777b538SAndroid Build Coastguard Worker return(NULL);
7356*6777b538SAndroid Build Coastguard Worker }
7357*6777b538SAndroid Build Coastguard Worker }
7358*6777b538SAndroid Build Coastguard Worker
7359*6777b538SAndroid Build Coastguard Worker /**
7360*6777b538SAndroid Build Coastguard Worker * xmlXPathNextAttribute:
7361*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7362*6777b538SAndroid Build Coastguard Worker * @cur: the current attribute in the traversal
7363*6777b538SAndroid Build Coastguard Worker *
7364*6777b538SAndroid Build Coastguard Worker * Traversal function for the "attribute" direction
7365*6777b538SAndroid Build Coastguard Worker * TODO: support DTD inherited default attributes
7366*6777b538SAndroid Build Coastguard Worker *
7367*6777b538SAndroid Build Coastguard Worker * Returns the next element following that axis
7368*6777b538SAndroid Build Coastguard Worker */
7369*6777b538SAndroid Build Coastguard Worker xmlNodePtr
xmlXPathNextAttribute(xmlXPathParserContextPtr ctxt,xmlNodePtr cur)7370*6777b538SAndroid Build Coastguard Worker xmlXPathNextAttribute(xmlXPathParserContextPtr ctxt, xmlNodePtr cur) {
7371*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL)) return(NULL);
7372*6777b538SAndroid Build Coastguard Worker if (ctxt->context->node == NULL)
7373*6777b538SAndroid Build Coastguard Worker return(NULL);
7374*6777b538SAndroid Build Coastguard Worker if (ctxt->context->node->type != XML_ELEMENT_NODE)
7375*6777b538SAndroid Build Coastguard Worker return(NULL);
7376*6777b538SAndroid Build Coastguard Worker if (cur == NULL) {
7377*6777b538SAndroid Build Coastguard Worker if (ctxt->context->node == (xmlNodePtr) ctxt->context->doc)
7378*6777b538SAndroid Build Coastguard Worker return(NULL);
7379*6777b538SAndroid Build Coastguard Worker return((xmlNodePtr)ctxt->context->node->properties);
7380*6777b538SAndroid Build Coastguard Worker }
7381*6777b538SAndroid Build Coastguard Worker return((xmlNodePtr)cur->next);
7382*6777b538SAndroid Build Coastguard Worker }
7383*6777b538SAndroid Build Coastguard Worker
7384*6777b538SAndroid Build Coastguard Worker /************************************************************************
7385*6777b538SAndroid Build Coastguard Worker * *
7386*6777b538SAndroid Build Coastguard Worker * NodeTest Functions *
7387*6777b538SAndroid Build Coastguard Worker * *
7388*6777b538SAndroid Build Coastguard Worker ************************************************************************/
7389*6777b538SAndroid Build Coastguard Worker
7390*6777b538SAndroid Build Coastguard Worker #define IS_FUNCTION 200
7391*6777b538SAndroid Build Coastguard Worker
7392*6777b538SAndroid Build Coastguard Worker
7393*6777b538SAndroid Build Coastguard Worker /************************************************************************
7394*6777b538SAndroid Build Coastguard Worker * *
7395*6777b538SAndroid Build Coastguard Worker * Implicit tree core function library *
7396*6777b538SAndroid Build Coastguard Worker * *
7397*6777b538SAndroid Build Coastguard Worker ************************************************************************/
7398*6777b538SAndroid Build Coastguard Worker
7399*6777b538SAndroid Build Coastguard Worker /**
7400*6777b538SAndroid Build Coastguard Worker * xmlXPathRoot:
7401*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7402*6777b538SAndroid Build Coastguard Worker *
7403*6777b538SAndroid Build Coastguard Worker * Initialize the context to the root of the document
7404*6777b538SAndroid Build Coastguard Worker */
7405*6777b538SAndroid Build Coastguard Worker void
xmlXPathRoot(xmlXPathParserContextPtr ctxt)7406*6777b538SAndroid Build Coastguard Worker xmlXPathRoot(xmlXPathParserContextPtr ctxt) {
7407*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL))
7408*6777b538SAndroid Build Coastguard Worker return;
7409*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt,
7410*6777b538SAndroid Build Coastguard Worker (xmlNodePtr) ctxt->context->doc));
7411*6777b538SAndroid Build Coastguard Worker }
7412*6777b538SAndroid Build Coastguard Worker
7413*6777b538SAndroid Build Coastguard Worker /************************************************************************
7414*6777b538SAndroid Build Coastguard Worker * *
7415*6777b538SAndroid Build Coastguard Worker * The explicit core function library *
7416*6777b538SAndroid Build Coastguard Worker *http://www.w3.org/Style/XSL/Group/1999/07/xpath-19990705.html#corelib *
7417*6777b538SAndroid Build Coastguard Worker * *
7418*6777b538SAndroid Build Coastguard Worker ************************************************************************/
7419*6777b538SAndroid Build Coastguard Worker
7420*6777b538SAndroid Build Coastguard Worker
7421*6777b538SAndroid Build Coastguard Worker /**
7422*6777b538SAndroid Build Coastguard Worker * xmlXPathLastFunction:
7423*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7424*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
7425*6777b538SAndroid Build Coastguard Worker *
7426*6777b538SAndroid Build Coastguard Worker * Implement the last() XPath function
7427*6777b538SAndroid Build Coastguard Worker * number last()
7428*6777b538SAndroid Build Coastguard Worker * The last function returns the number of nodes in the context node list.
7429*6777b538SAndroid Build Coastguard Worker */
7430*6777b538SAndroid Build Coastguard Worker void
xmlXPathLastFunction(xmlXPathParserContextPtr ctxt,int nargs)7431*6777b538SAndroid Build Coastguard Worker xmlXPathLastFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7432*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(0);
7433*6777b538SAndroid Build Coastguard Worker if (ctxt->context->contextSize >= 0) {
7434*6777b538SAndroid Build Coastguard Worker valuePush(ctxt,
7435*6777b538SAndroid Build Coastguard Worker xmlXPathCacheNewFloat(ctxt, (double) ctxt->context->contextSize));
7436*6777b538SAndroid Build Coastguard Worker } else {
7437*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_CTXT_SIZE);
7438*6777b538SAndroid Build Coastguard Worker }
7439*6777b538SAndroid Build Coastguard Worker }
7440*6777b538SAndroid Build Coastguard Worker
7441*6777b538SAndroid Build Coastguard Worker /**
7442*6777b538SAndroid Build Coastguard Worker * xmlXPathPositionFunction:
7443*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7444*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
7445*6777b538SAndroid Build Coastguard Worker *
7446*6777b538SAndroid Build Coastguard Worker * Implement the position() XPath function
7447*6777b538SAndroid Build Coastguard Worker * number position()
7448*6777b538SAndroid Build Coastguard Worker * The position function returns the position of the context node in the
7449*6777b538SAndroid Build Coastguard Worker * context node list. The first position is 1, and so the last position
7450*6777b538SAndroid Build Coastguard Worker * will be equal to last().
7451*6777b538SAndroid Build Coastguard Worker */
7452*6777b538SAndroid Build Coastguard Worker void
xmlXPathPositionFunction(xmlXPathParserContextPtr ctxt,int nargs)7453*6777b538SAndroid Build Coastguard Worker xmlXPathPositionFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7454*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(0);
7455*6777b538SAndroid Build Coastguard Worker if (ctxt->context->proximityPosition >= 0) {
7456*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewFloat(ctxt,
7457*6777b538SAndroid Build Coastguard Worker (double) ctxt->context->proximityPosition));
7458*6777b538SAndroid Build Coastguard Worker } else {
7459*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_CTXT_POSITION);
7460*6777b538SAndroid Build Coastguard Worker }
7461*6777b538SAndroid Build Coastguard Worker }
7462*6777b538SAndroid Build Coastguard Worker
7463*6777b538SAndroid Build Coastguard Worker /**
7464*6777b538SAndroid Build Coastguard Worker * xmlXPathCountFunction:
7465*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7466*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
7467*6777b538SAndroid Build Coastguard Worker *
7468*6777b538SAndroid Build Coastguard Worker * Implement the count() XPath function
7469*6777b538SAndroid Build Coastguard Worker * number count(node-set)
7470*6777b538SAndroid Build Coastguard Worker */
7471*6777b538SAndroid Build Coastguard Worker void
xmlXPathCountFunction(xmlXPathParserContextPtr ctxt,int nargs)7472*6777b538SAndroid Build Coastguard Worker xmlXPathCountFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7473*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr cur;
7474*6777b538SAndroid Build Coastguard Worker
7475*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(1);
7476*6777b538SAndroid Build Coastguard Worker if ((ctxt->value == NULL) ||
7477*6777b538SAndroid Build Coastguard Worker ((ctxt->value->type != XPATH_NODESET) &&
7478*6777b538SAndroid Build Coastguard Worker (ctxt->value->type != XPATH_XSLT_TREE)))
7479*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_TYPE);
7480*6777b538SAndroid Build Coastguard Worker cur = valuePop(ctxt);
7481*6777b538SAndroid Build Coastguard Worker
7482*6777b538SAndroid Build Coastguard Worker if ((cur == NULL) || (cur->nodesetval == NULL))
7483*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, 0.0));
7484*6777b538SAndroid Build Coastguard Worker else
7485*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewFloat(ctxt,
7486*6777b538SAndroid Build Coastguard Worker (double) cur->nodesetval->nodeNr));
7487*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, cur);
7488*6777b538SAndroid Build Coastguard Worker }
7489*6777b538SAndroid Build Coastguard Worker
7490*6777b538SAndroid Build Coastguard Worker /**
7491*6777b538SAndroid Build Coastguard Worker * xmlXPathGetElementsByIds:
7492*6777b538SAndroid Build Coastguard Worker * @doc: the document
7493*6777b538SAndroid Build Coastguard Worker * @ids: a whitespace separated list of IDs
7494*6777b538SAndroid Build Coastguard Worker *
7495*6777b538SAndroid Build Coastguard Worker * Selects elements by their unique ID.
7496*6777b538SAndroid Build Coastguard Worker *
7497*6777b538SAndroid Build Coastguard Worker * Returns a node-set of selected elements.
7498*6777b538SAndroid Build Coastguard Worker */
7499*6777b538SAndroid Build Coastguard Worker static xmlNodeSetPtr
xmlXPathGetElementsByIds(xmlDocPtr doc,const xmlChar * ids)7500*6777b538SAndroid Build Coastguard Worker xmlXPathGetElementsByIds (xmlDocPtr doc, const xmlChar *ids) {
7501*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr ret;
7502*6777b538SAndroid Build Coastguard Worker const xmlChar *cur = ids;
7503*6777b538SAndroid Build Coastguard Worker xmlChar *ID;
7504*6777b538SAndroid Build Coastguard Worker xmlAttrPtr attr;
7505*6777b538SAndroid Build Coastguard Worker xmlNodePtr elem = NULL;
7506*6777b538SAndroid Build Coastguard Worker
7507*6777b538SAndroid Build Coastguard Worker if (ids == NULL) return(NULL);
7508*6777b538SAndroid Build Coastguard Worker
7509*6777b538SAndroid Build Coastguard Worker ret = xmlXPathNodeSetCreate(NULL);
7510*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
7511*6777b538SAndroid Build Coastguard Worker return(ret);
7512*6777b538SAndroid Build Coastguard Worker
7513*6777b538SAndroid Build Coastguard Worker while (IS_BLANK_CH(*cur)) cur++;
7514*6777b538SAndroid Build Coastguard Worker while (*cur != 0) {
7515*6777b538SAndroid Build Coastguard Worker while ((!IS_BLANK_CH(*cur)) && (*cur != 0))
7516*6777b538SAndroid Build Coastguard Worker cur++;
7517*6777b538SAndroid Build Coastguard Worker
7518*6777b538SAndroid Build Coastguard Worker ID = xmlStrndup(ids, cur - ids);
7519*6777b538SAndroid Build Coastguard Worker if (ID == NULL) {
7520*6777b538SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(ret);
7521*6777b538SAndroid Build Coastguard Worker return(NULL);
7522*6777b538SAndroid Build Coastguard Worker }
7523*6777b538SAndroid Build Coastguard Worker /*
7524*6777b538SAndroid Build Coastguard Worker * We used to check the fact that the value passed
7525*6777b538SAndroid Build Coastguard Worker * was an NCName, but this generated much troubles for
7526*6777b538SAndroid Build Coastguard Worker * me and Aleksey Sanin, people blatantly violated that
7527*6777b538SAndroid Build Coastguard Worker * constraint, like Visa3D spec.
7528*6777b538SAndroid Build Coastguard Worker * if (xmlValidateNCName(ID, 1) == 0)
7529*6777b538SAndroid Build Coastguard Worker */
7530*6777b538SAndroid Build Coastguard Worker attr = xmlGetID(doc, ID);
7531*6777b538SAndroid Build Coastguard Worker xmlFree(ID);
7532*6777b538SAndroid Build Coastguard Worker if (attr != NULL) {
7533*6777b538SAndroid Build Coastguard Worker if (attr->type == XML_ATTRIBUTE_NODE)
7534*6777b538SAndroid Build Coastguard Worker elem = attr->parent;
7535*6777b538SAndroid Build Coastguard Worker else if (attr->type == XML_ELEMENT_NODE)
7536*6777b538SAndroid Build Coastguard Worker elem = (xmlNodePtr) attr;
7537*6777b538SAndroid Build Coastguard Worker else
7538*6777b538SAndroid Build Coastguard Worker elem = NULL;
7539*6777b538SAndroid Build Coastguard Worker if (elem != NULL) {
7540*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetAdd(ret, elem) < 0) {
7541*6777b538SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(ret);
7542*6777b538SAndroid Build Coastguard Worker return(NULL);
7543*6777b538SAndroid Build Coastguard Worker }
7544*6777b538SAndroid Build Coastguard Worker }
7545*6777b538SAndroid Build Coastguard Worker }
7546*6777b538SAndroid Build Coastguard Worker
7547*6777b538SAndroid Build Coastguard Worker while (IS_BLANK_CH(*cur)) cur++;
7548*6777b538SAndroid Build Coastguard Worker ids = cur;
7549*6777b538SAndroid Build Coastguard Worker }
7550*6777b538SAndroid Build Coastguard Worker return(ret);
7551*6777b538SAndroid Build Coastguard Worker }
7552*6777b538SAndroid Build Coastguard Worker
7553*6777b538SAndroid Build Coastguard Worker /**
7554*6777b538SAndroid Build Coastguard Worker * xmlXPathIdFunction:
7555*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7556*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
7557*6777b538SAndroid Build Coastguard Worker *
7558*6777b538SAndroid Build Coastguard Worker * Implement the id() XPath function
7559*6777b538SAndroid Build Coastguard Worker * node-set id(object)
7560*6777b538SAndroid Build Coastguard Worker * The id function selects elements by their unique ID
7561*6777b538SAndroid Build Coastguard Worker * (see [5.2.1 Unique IDs]). When the argument to id is of type node-set,
7562*6777b538SAndroid Build Coastguard Worker * then the result is the union of the result of applying id to the
7563*6777b538SAndroid Build Coastguard Worker * string value of each of the nodes in the argument node-set. When the
7564*6777b538SAndroid Build Coastguard Worker * argument to id is of any other type, the argument is converted to a
7565*6777b538SAndroid Build Coastguard Worker * string as if by a call to the string function; the string is split
7566*6777b538SAndroid Build Coastguard Worker * into a whitespace-separated list of tokens (whitespace is any sequence
7567*6777b538SAndroid Build Coastguard Worker * of characters matching the production S); the result is a node-set
7568*6777b538SAndroid Build Coastguard Worker * containing the elements in the same document as the context node that
7569*6777b538SAndroid Build Coastguard Worker * have a unique ID equal to any of the tokens in the list.
7570*6777b538SAndroid Build Coastguard Worker */
7571*6777b538SAndroid Build Coastguard Worker void
xmlXPathIdFunction(xmlXPathParserContextPtr ctxt,int nargs)7572*6777b538SAndroid Build Coastguard Worker xmlXPathIdFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7573*6777b538SAndroid Build Coastguard Worker xmlChar *tokens;
7574*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr ret;
7575*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr obj;
7576*6777b538SAndroid Build Coastguard Worker
7577*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(1);
7578*6777b538SAndroid Build Coastguard Worker obj = valuePop(ctxt);
7579*6777b538SAndroid Build Coastguard Worker if (obj == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
7580*6777b538SAndroid Build Coastguard Worker if ((obj->type == XPATH_NODESET) || (obj->type == XPATH_XSLT_TREE)) {
7581*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr ns;
7582*6777b538SAndroid Build Coastguard Worker int i;
7583*6777b538SAndroid Build Coastguard Worker
7584*6777b538SAndroid Build Coastguard Worker ret = xmlXPathNodeSetCreate(NULL);
7585*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
7586*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7587*6777b538SAndroid Build Coastguard Worker
7588*6777b538SAndroid Build Coastguard Worker if (obj->nodesetval != NULL) {
7589*6777b538SAndroid Build Coastguard Worker for (i = 0; i < obj->nodesetval->nodeNr; i++) {
7590*6777b538SAndroid Build Coastguard Worker tokens =
7591*6777b538SAndroid Build Coastguard Worker xmlXPathCastNodeToString(obj->nodesetval->nodeTab[i]);
7592*6777b538SAndroid Build Coastguard Worker if (tokens == NULL)
7593*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7594*6777b538SAndroid Build Coastguard Worker ns = xmlXPathGetElementsByIds(ctxt->context->doc, tokens);
7595*6777b538SAndroid Build Coastguard Worker if (ns == NULL)
7596*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7597*6777b538SAndroid Build Coastguard Worker ret = xmlXPathNodeSetMerge(ret, ns);
7598*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
7599*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7600*6777b538SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(ns);
7601*6777b538SAndroid Build Coastguard Worker if (tokens != NULL)
7602*6777b538SAndroid Build Coastguard Worker xmlFree(tokens);
7603*6777b538SAndroid Build Coastguard Worker }
7604*6777b538SAndroid Build Coastguard Worker }
7605*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, obj);
7606*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt, ret));
7607*6777b538SAndroid Build Coastguard Worker return;
7608*6777b538SAndroid Build Coastguard Worker }
7609*6777b538SAndroid Build Coastguard Worker tokens = xmlXPathCastToString(obj);
7610*6777b538SAndroid Build Coastguard Worker if (tokens == NULL)
7611*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7612*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, obj);
7613*6777b538SAndroid Build Coastguard Worker ret = xmlXPathGetElementsByIds(ctxt->context->doc, tokens);
7614*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
7615*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7616*6777b538SAndroid Build Coastguard Worker xmlFree(tokens);
7617*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt, ret));
7618*6777b538SAndroid Build Coastguard Worker return;
7619*6777b538SAndroid Build Coastguard Worker }
7620*6777b538SAndroid Build Coastguard Worker
7621*6777b538SAndroid Build Coastguard Worker /**
7622*6777b538SAndroid Build Coastguard Worker * xmlXPathLocalNameFunction:
7623*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7624*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
7625*6777b538SAndroid Build Coastguard Worker *
7626*6777b538SAndroid Build Coastguard Worker * Implement the local-name() XPath function
7627*6777b538SAndroid Build Coastguard Worker * string local-name(node-set?)
7628*6777b538SAndroid Build Coastguard Worker * The local-name function returns a string containing the local part
7629*6777b538SAndroid Build Coastguard Worker * of the name of the node in the argument node-set that is first in
7630*6777b538SAndroid Build Coastguard Worker * document order. If the node-set is empty or the first node has no
7631*6777b538SAndroid Build Coastguard Worker * name, an empty string is returned. If the argument is omitted it
7632*6777b538SAndroid Build Coastguard Worker * defaults to the context node.
7633*6777b538SAndroid Build Coastguard Worker */
7634*6777b538SAndroid Build Coastguard Worker void
xmlXPathLocalNameFunction(xmlXPathParserContextPtr ctxt,int nargs)7635*6777b538SAndroid Build Coastguard Worker xmlXPathLocalNameFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7636*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr cur;
7637*6777b538SAndroid Build Coastguard Worker
7638*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL) return;
7639*6777b538SAndroid Build Coastguard Worker
7640*6777b538SAndroid Build Coastguard Worker if (nargs == 0) {
7641*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt, ctxt->context->node));
7642*6777b538SAndroid Build Coastguard Worker nargs = 1;
7643*6777b538SAndroid Build Coastguard Worker }
7644*6777b538SAndroid Build Coastguard Worker
7645*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(1);
7646*6777b538SAndroid Build Coastguard Worker if ((ctxt->value == NULL) ||
7647*6777b538SAndroid Build Coastguard Worker ((ctxt->value->type != XPATH_NODESET) &&
7648*6777b538SAndroid Build Coastguard Worker (ctxt->value->type != XPATH_XSLT_TREE)))
7649*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_TYPE);
7650*6777b538SAndroid Build Coastguard Worker cur = valuePop(ctxt);
7651*6777b538SAndroid Build Coastguard Worker
7652*6777b538SAndroid Build Coastguard Worker if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
7653*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
7654*6777b538SAndroid Build Coastguard Worker } else {
7655*6777b538SAndroid Build Coastguard Worker int i = 0; /* Should be first in document order !!!!! */
7656*6777b538SAndroid Build Coastguard Worker switch (cur->nodesetval->nodeTab[i]->type) {
7657*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
7658*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE:
7659*6777b538SAndroid Build Coastguard Worker case XML_PI_NODE:
7660*6777b538SAndroid Build Coastguard Worker if (cur->nodesetval->nodeTab[i]->name[0] == ' ')
7661*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
7662*6777b538SAndroid Build Coastguard Worker else
7663*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewString(ctxt,
7664*6777b538SAndroid Build Coastguard Worker cur->nodesetval->nodeTab[i]->name));
7665*6777b538SAndroid Build Coastguard Worker break;
7666*6777b538SAndroid Build Coastguard Worker case XML_NAMESPACE_DECL:
7667*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewString(ctxt,
7668*6777b538SAndroid Build Coastguard Worker ((xmlNsPtr)cur->nodesetval->nodeTab[i])->prefix));
7669*6777b538SAndroid Build Coastguard Worker break;
7670*6777b538SAndroid Build Coastguard Worker default:
7671*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
7672*6777b538SAndroid Build Coastguard Worker }
7673*6777b538SAndroid Build Coastguard Worker }
7674*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, cur);
7675*6777b538SAndroid Build Coastguard Worker }
7676*6777b538SAndroid Build Coastguard Worker
7677*6777b538SAndroid Build Coastguard Worker /**
7678*6777b538SAndroid Build Coastguard Worker * xmlXPathNamespaceURIFunction:
7679*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7680*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
7681*6777b538SAndroid Build Coastguard Worker *
7682*6777b538SAndroid Build Coastguard Worker * Implement the namespace-uri() XPath function
7683*6777b538SAndroid Build Coastguard Worker * string namespace-uri(node-set?)
7684*6777b538SAndroid Build Coastguard Worker * The namespace-uri function returns a string containing the
7685*6777b538SAndroid Build Coastguard Worker * namespace URI of the expanded name of the node in the argument
7686*6777b538SAndroid Build Coastguard Worker * node-set that is first in document order. If the node-set is empty,
7687*6777b538SAndroid Build Coastguard Worker * the first node has no name, or the expanded name has no namespace
7688*6777b538SAndroid Build Coastguard Worker * URI, an empty string is returned. If the argument is omitted it
7689*6777b538SAndroid Build Coastguard Worker * defaults to the context node.
7690*6777b538SAndroid Build Coastguard Worker */
7691*6777b538SAndroid Build Coastguard Worker void
xmlXPathNamespaceURIFunction(xmlXPathParserContextPtr ctxt,int nargs)7692*6777b538SAndroid Build Coastguard Worker xmlXPathNamespaceURIFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7693*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr cur;
7694*6777b538SAndroid Build Coastguard Worker
7695*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL) return;
7696*6777b538SAndroid Build Coastguard Worker
7697*6777b538SAndroid Build Coastguard Worker if (nargs == 0) {
7698*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt, ctxt->context->node));
7699*6777b538SAndroid Build Coastguard Worker nargs = 1;
7700*6777b538SAndroid Build Coastguard Worker }
7701*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(1);
7702*6777b538SAndroid Build Coastguard Worker if ((ctxt->value == NULL) ||
7703*6777b538SAndroid Build Coastguard Worker ((ctxt->value->type != XPATH_NODESET) &&
7704*6777b538SAndroid Build Coastguard Worker (ctxt->value->type != XPATH_XSLT_TREE)))
7705*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_TYPE);
7706*6777b538SAndroid Build Coastguard Worker cur = valuePop(ctxt);
7707*6777b538SAndroid Build Coastguard Worker
7708*6777b538SAndroid Build Coastguard Worker if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
7709*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
7710*6777b538SAndroid Build Coastguard Worker } else {
7711*6777b538SAndroid Build Coastguard Worker int i = 0; /* Should be first in document order !!!!! */
7712*6777b538SAndroid Build Coastguard Worker switch (cur->nodesetval->nodeTab[i]->type) {
7713*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
7714*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE:
7715*6777b538SAndroid Build Coastguard Worker if (cur->nodesetval->nodeTab[i]->ns == NULL)
7716*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
7717*6777b538SAndroid Build Coastguard Worker else
7718*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewString(ctxt,
7719*6777b538SAndroid Build Coastguard Worker cur->nodesetval->nodeTab[i]->ns->href));
7720*6777b538SAndroid Build Coastguard Worker break;
7721*6777b538SAndroid Build Coastguard Worker default:
7722*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
7723*6777b538SAndroid Build Coastguard Worker }
7724*6777b538SAndroid Build Coastguard Worker }
7725*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, cur);
7726*6777b538SAndroid Build Coastguard Worker }
7727*6777b538SAndroid Build Coastguard Worker
7728*6777b538SAndroid Build Coastguard Worker /**
7729*6777b538SAndroid Build Coastguard Worker * xmlXPathNameFunction:
7730*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7731*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
7732*6777b538SAndroid Build Coastguard Worker *
7733*6777b538SAndroid Build Coastguard Worker * Implement the name() XPath function
7734*6777b538SAndroid Build Coastguard Worker * string name(node-set?)
7735*6777b538SAndroid Build Coastguard Worker * The name function returns a string containing a QName representing
7736*6777b538SAndroid Build Coastguard Worker * the name of the node in the argument node-set that is first in document
7737*6777b538SAndroid Build Coastguard Worker * order. The QName must represent the name with respect to the namespace
7738*6777b538SAndroid Build Coastguard Worker * declarations in effect on the node whose name is being represented.
7739*6777b538SAndroid Build Coastguard Worker * Typically, this will be the form in which the name occurred in the XML
7740*6777b538SAndroid Build Coastguard Worker * source. This need not be the case if there are namespace declarations
7741*6777b538SAndroid Build Coastguard Worker * in effect on the node that associate multiple prefixes with the same
7742*6777b538SAndroid Build Coastguard Worker * namespace. However, an implementation may include information about
7743*6777b538SAndroid Build Coastguard Worker * the original prefix in its representation of nodes; in this case, an
7744*6777b538SAndroid Build Coastguard Worker * implementation can ensure that the returned string is always the same
7745*6777b538SAndroid Build Coastguard Worker * as the QName used in the XML source. If the argument it omitted it
7746*6777b538SAndroid Build Coastguard Worker * defaults to the context node.
7747*6777b538SAndroid Build Coastguard Worker * Libxml keep the original prefix so the "real qualified name" used is
7748*6777b538SAndroid Build Coastguard Worker * returned.
7749*6777b538SAndroid Build Coastguard Worker */
7750*6777b538SAndroid Build Coastguard Worker static void
xmlXPathNameFunction(xmlXPathParserContextPtr ctxt,int nargs)7751*6777b538SAndroid Build Coastguard Worker xmlXPathNameFunction(xmlXPathParserContextPtr ctxt, int nargs)
7752*6777b538SAndroid Build Coastguard Worker {
7753*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr cur;
7754*6777b538SAndroid Build Coastguard Worker
7755*6777b538SAndroid Build Coastguard Worker if (nargs == 0) {
7756*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt, ctxt->context->node));
7757*6777b538SAndroid Build Coastguard Worker nargs = 1;
7758*6777b538SAndroid Build Coastguard Worker }
7759*6777b538SAndroid Build Coastguard Worker
7760*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(1);
7761*6777b538SAndroid Build Coastguard Worker if ((ctxt->value == NULL) ||
7762*6777b538SAndroid Build Coastguard Worker ((ctxt->value->type != XPATH_NODESET) &&
7763*6777b538SAndroid Build Coastguard Worker (ctxt->value->type != XPATH_XSLT_TREE)))
7764*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_TYPE);
7765*6777b538SAndroid Build Coastguard Worker cur = valuePop(ctxt);
7766*6777b538SAndroid Build Coastguard Worker
7767*6777b538SAndroid Build Coastguard Worker if ((cur->nodesetval == NULL) || (cur->nodesetval->nodeNr == 0)) {
7768*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
7769*6777b538SAndroid Build Coastguard Worker } else {
7770*6777b538SAndroid Build Coastguard Worker int i = 0; /* Should be first in document order !!!!! */
7771*6777b538SAndroid Build Coastguard Worker
7772*6777b538SAndroid Build Coastguard Worker switch (cur->nodesetval->nodeTab[i]->type) {
7773*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
7774*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE:
7775*6777b538SAndroid Build Coastguard Worker if (cur->nodesetval->nodeTab[i]->name[0] == ' ')
7776*6777b538SAndroid Build Coastguard Worker valuePush(ctxt,
7777*6777b538SAndroid Build Coastguard Worker xmlXPathCacheNewCString(ctxt, ""));
7778*6777b538SAndroid Build Coastguard Worker else if ((cur->nodesetval->nodeTab[i]->ns == NULL) ||
7779*6777b538SAndroid Build Coastguard Worker (cur->nodesetval->nodeTab[i]->ns->prefix == NULL)) {
7780*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewString(ctxt,
7781*6777b538SAndroid Build Coastguard Worker cur->nodesetval->nodeTab[i]->name));
7782*6777b538SAndroid Build Coastguard Worker } else {
7783*6777b538SAndroid Build Coastguard Worker xmlChar *fullname;
7784*6777b538SAndroid Build Coastguard Worker
7785*6777b538SAndroid Build Coastguard Worker fullname = xmlBuildQName(cur->nodesetval->nodeTab[i]->name,
7786*6777b538SAndroid Build Coastguard Worker cur->nodesetval->nodeTab[i]->ns->prefix,
7787*6777b538SAndroid Build Coastguard Worker NULL, 0);
7788*6777b538SAndroid Build Coastguard Worker if (fullname == cur->nodesetval->nodeTab[i]->name)
7789*6777b538SAndroid Build Coastguard Worker fullname = xmlStrdup(cur->nodesetval->nodeTab[i]->name);
7790*6777b538SAndroid Build Coastguard Worker if (fullname == NULL)
7791*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7792*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheWrapString(ctxt, fullname));
7793*6777b538SAndroid Build Coastguard Worker }
7794*6777b538SAndroid Build Coastguard Worker break;
7795*6777b538SAndroid Build Coastguard Worker default:
7796*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt,
7797*6777b538SAndroid Build Coastguard Worker cur->nodesetval->nodeTab[i]));
7798*6777b538SAndroid Build Coastguard Worker xmlXPathLocalNameFunction(ctxt, 1);
7799*6777b538SAndroid Build Coastguard Worker }
7800*6777b538SAndroid Build Coastguard Worker }
7801*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, cur);
7802*6777b538SAndroid Build Coastguard Worker }
7803*6777b538SAndroid Build Coastguard Worker
7804*6777b538SAndroid Build Coastguard Worker
7805*6777b538SAndroid Build Coastguard Worker /**
7806*6777b538SAndroid Build Coastguard Worker * xmlXPathStringFunction:
7807*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7808*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
7809*6777b538SAndroid Build Coastguard Worker *
7810*6777b538SAndroid Build Coastguard Worker * Implement the string() XPath function
7811*6777b538SAndroid Build Coastguard Worker * string string(object?)
7812*6777b538SAndroid Build Coastguard Worker * The string function converts an object to a string as follows:
7813*6777b538SAndroid Build Coastguard Worker * - A node-set is converted to a string by returning the value of
7814*6777b538SAndroid Build Coastguard Worker * the node in the node-set that is first in document order.
7815*6777b538SAndroid Build Coastguard Worker * If the node-set is empty, an empty string is returned.
7816*6777b538SAndroid Build Coastguard Worker * - A number is converted to a string as follows
7817*6777b538SAndroid Build Coastguard Worker * + NaN is converted to the string NaN
7818*6777b538SAndroid Build Coastguard Worker * + positive zero is converted to the string 0
7819*6777b538SAndroid Build Coastguard Worker * + negative zero is converted to the string 0
7820*6777b538SAndroid Build Coastguard Worker * + positive infinity is converted to the string Infinity
7821*6777b538SAndroid Build Coastguard Worker * + negative infinity is converted to the string -Infinity
7822*6777b538SAndroid Build Coastguard Worker * + if the number is an integer, the number is represented in
7823*6777b538SAndroid Build Coastguard Worker * decimal form as a Number with no decimal point and no leading
7824*6777b538SAndroid Build Coastguard Worker * zeros, preceded by a minus sign (-) if the number is negative
7825*6777b538SAndroid Build Coastguard Worker * + otherwise, the number is represented in decimal form as a
7826*6777b538SAndroid Build Coastguard Worker * Number including a decimal point with at least one digit
7827*6777b538SAndroid Build Coastguard Worker * before the decimal point and at least one digit after the
7828*6777b538SAndroid Build Coastguard Worker * decimal point, preceded by a minus sign (-) if the number
7829*6777b538SAndroid Build Coastguard Worker * is negative; there must be no leading zeros before the decimal
7830*6777b538SAndroid Build Coastguard Worker * point apart possibly from the one required digit immediately
7831*6777b538SAndroid Build Coastguard Worker * before the decimal point; beyond the one required digit
7832*6777b538SAndroid Build Coastguard Worker * after the decimal point there must be as many, but only as
7833*6777b538SAndroid Build Coastguard Worker * many, more digits as are needed to uniquely distinguish the
7834*6777b538SAndroid Build Coastguard Worker * number from all other IEEE 754 numeric values.
7835*6777b538SAndroid Build Coastguard Worker * - The boolean false value is converted to the string false.
7836*6777b538SAndroid Build Coastguard Worker * The boolean true value is converted to the string true.
7837*6777b538SAndroid Build Coastguard Worker *
7838*6777b538SAndroid Build Coastguard Worker * If the argument is omitted, it defaults to a node-set with the
7839*6777b538SAndroid Build Coastguard Worker * context node as its only member.
7840*6777b538SAndroid Build Coastguard Worker */
7841*6777b538SAndroid Build Coastguard Worker void
xmlXPathStringFunction(xmlXPathParserContextPtr ctxt,int nargs)7842*6777b538SAndroid Build Coastguard Worker xmlXPathStringFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7843*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr cur;
7844*6777b538SAndroid Build Coastguard Worker xmlChar *stringval;
7845*6777b538SAndroid Build Coastguard Worker
7846*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL) return;
7847*6777b538SAndroid Build Coastguard Worker if (nargs == 0) {
7848*6777b538SAndroid Build Coastguard Worker stringval = xmlXPathCastNodeToString(ctxt->context->node);
7849*6777b538SAndroid Build Coastguard Worker if (stringval == NULL)
7850*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7851*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheWrapString(ctxt, stringval));
7852*6777b538SAndroid Build Coastguard Worker return;
7853*6777b538SAndroid Build Coastguard Worker }
7854*6777b538SAndroid Build Coastguard Worker
7855*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(1);
7856*6777b538SAndroid Build Coastguard Worker cur = valuePop(ctxt);
7857*6777b538SAndroid Build Coastguard Worker if (cur == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
7858*6777b538SAndroid Build Coastguard Worker if (cur->type != XPATH_STRING) {
7859*6777b538SAndroid Build Coastguard Worker stringval = xmlXPathCastToString(cur);
7860*6777b538SAndroid Build Coastguard Worker if (stringval == NULL)
7861*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7862*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, cur);
7863*6777b538SAndroid Build Coastguard Worker cur = xmlXPathCacheWrapString(ctxt, stringval);
7864*6777b538SAndroid Build Coastguard Worker }
7865*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, cur);
7866*6777b538SAndroid Build Coastguard Worker }
7867*6777b538SAndroid Build Coastguard Worker
7868*6777b538SAndroid Build Coastguard Worker /**
7869*6777b538SAndroid Build Coastguard Worker * xmlXPathStringLengthFunction:
7870*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7871*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
7872*6777b538SAndroid Build Coastguard Worker *
7873*6777b538SAndroid Build Coastguard Worker * Implement the string-length() XPath function
7874*6777b538SAndroid Build Coastguard Worker * number string-length(string?)
7875*6777b538SAndroid Build Coastguard Worker * The string-length returns the number of characters in the string
7876*6777b538SAndroid Build Coastguard Worker * (see [3.6 Strings]). If the argument is omitted, it defaults to
7877*6777b538SAndroid Build Coastguard Worker * the context node converted to a string, in other words the value
7878*6777b538SAndroid Build Coastguard Worker * of the context node.
7879*6777b538SAndroid Build Coastguard Worker */
7880*6777b538SAndroid Build Coastguard Worker void
xmlXPathStringLengthFunction(xmlXPathParserContextPtr ctxt,int nargs)7881*6777b538SAndroid Build Coastguard Worker xmlXPathStringLengthFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7882*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr cur;
7883*6777b538SAndroid Build Coastguard Worker
7884*6777b538SAndroid Build Coastguard Worker if (nargs == 0) {
7885*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->context == NULL))
7886*6777b538SAndroid Build Coastguard Worker return;
7887*6777b538SAndroid Build Coastguard Worker if (ctxt->context->node == NULL) {
7888*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, 0));
7889*6777b538SAndroid Build Coastguard Worker } else {
7890*6777b538SAndroid Build Coastguard Worker xmlChar *content;
7891*6777b538SAndroid Build Coastguard Worker
7892*6777b538SAndroid Build Coastguard Worker content = xmlXPathCastNodeToString(ctxt->context->node);
7893*6777b538SAndroid Build Coastguard Worker if (content == NULL)
7894*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7895*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewFloat(ctxt,
7896*6777b538SAndroid Build Coastguard Worker xmlUTF8Strlen(content)));
7897*6777b538SAndroid Build Coastguard Worker xmlFree(content);
7898*6777b538SAndroid Build Coastguard Worker }
7899*6777b538SAndroid Build Coastguard Worker return;
7900*6777b538SAndroid Build Coastguard Worker }
7901*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(1);
7902*6777b538SAndroid Build Coastguard Worker CAST_TO_STRING;
7903*6777b538SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_STRING);
7904*6777b538SAndroid Build Coastguard Worker cur = valuePop(ctxt);
7905*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewFloat(ctxt,
7906*6777b538SAndroid Build Coastguard Worker xmlUTF8Strlen(cur->stringval)));
7907*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, cur);
7908*6777b538SAndroid Build Coastguard Worker }
7909*6777b538SAndroid Build Coastguard Worker
7910*6777b538SAndroid Build Coastguard Worker /**
7911*6777b538SAndroid Build Coastguard Worker * xmlXPathConcatFunction:
7912*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7913*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
7914*6777b538SAndroid Build Coastguard Worker *
7915*6777b538SAndroid Build Coastguard Worker * Implement the concat() XPath function
7916*6777b538SAndroid Build Coastguard Worker * string concat(string, string, string*)
7917*6777b538SAndroid Build Coastguard Worker * The concat function returns the concatenation of its arguments.
7918*6777b538SAndroid Build Coastguard Worker */
7919*6777b538SAndroid Build Coastguard Worker void
xmlXPathConcatFunction(xmlXPathParserContextPtr ctxt,int nargs)7920*6777b538SAndroid Build Coastguard Worker xmlXPathConcatFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7921*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr cur, newobj;
7922*6777b538SAndroid Build Coastguard Worker xmlChar *tmp;
7923*6777b538SAndroid Build Coastguard Worker
7924*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL) return;
7925*6777b538SAndroid Build Coastguard Worker if (nargs < 2) {
7926*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(2);
7927*6777b538SAndroid Build Coastguard Worker }
7928*6777b538SAndroid Build Coastguard Worker
7929*6777b538SAndroid Build Coastguard Worker CAST_TO_STRING;
7930*6777b538SAndroid Build Coastguard Worker cur = valuePop(ctxt);
7931*6777b538SAndroid Build Coastguard Worker if ((cur == NULL) || (cur->type != XPATH_STRING)) {
7932*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, cur);
7933*6777b538SAndroid Build Coastguard Worker return;
7934*6777b538SAndroid Build Coastguard Worker }
7935*6777b538SAndroid Build Coastguard Worker nargs--;
7936*6777b538SAndroid Build Coastguard Worker
7937*6777b538SAndroid Build Coastguard Worker while (nargs > 0) {
7938*6777b538SAndroid Build Coastguard Worker CAST_TO_STRING;
7939*6777b538SAndroid Build Coastguard Worker newobj = valuePop(ctxt);
7940*6777b538SAndroid Build Coastguard Worker if ((newobj == NULL) || (newobj->type != XPATH_STRING)) {
7941*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, newobj);
7942*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, cur);
7943*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_TYPE);
7944*6777b538SAndroid Build Coastguard Worker }
7945*6777b538SAndroid Build Coastguard Worker tmp = xmlStrcat(newobj->stringval, cur->stringval);
7946*6777b538SAndroid Build Coastguard Worker if (tmp == NULL)
7947*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
7948*6777b538SAndroid Build Coastguard Worker newobj->stringval = cur->stringval;
7949*6777b538SAndroid Build Coastguard Worker cur->stringval = tmp;
7950*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, newobj);
7951*6777b538SAndroid Build Coastguard Worker nargs--;
7952*6777b538SAndroid Build Coastguard Worker }
7953*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, cur);
7954*6777b538SAndroid Build Coastguard Worker }
7955*6777b538SAndroid Build Coastguard Worker
7956*6777b538SAndroid Build Coastguard Worker /**
7957*6777b538SAndroid Build Coastguard Worker * xmlXPathContainsFunction:
7958*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7959*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
7960*6777b538SAndroid Build Coastguard Worker *
7961*6777b538SAndroid Build Coastguard Worker * Implement the contains() XPath function
7962*6777b538SAndroid Build Coastguard Worker * boolean contains(string, string)
7963*6777b538SAndroid Build Coastguard Worker * The contains function returns true if the first argument string
7964*6777b538SAndroid Build Coastguard Worker * contains the second argument string, and otherwise returns false.
7965*6777b538SAndroid Build Coastguard Worker */
7966*6777b538SAndroid Build Coastguard Worker void
xmlXPathContainsFunction(xmlXPathParserContextPtr ctxt,int nargs)7967*6777b538SAndroid Build Coastguard Worker xmlXPathContainsFunction(xmlXPathParserContextPtr ctxt, int nargs) {
7968*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr hay, needle;
7969*6777b538SAndroid Build Coastguard Worker
7970*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(2);
7971*6777b538SAndroid Build Coastguard Worker CAST_TO_STRING;
7972*6777b538SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_STRING);
7973*6777b538SAndroid Build Coastguard Worker needle = valuePop(ctxt);
7974*6777b538SAndroid Build Coastguard Worker CAST_TO_STRING;
7975*6777b538SAndroid Build Coastguard Worker hay = valuePop(ctxt);
7976*6777b538SAndroid Build Coastguard Worker
7977*6777b538SAndroid Build Coastguard Worker if ((hay == NULL) || (hay->type != XPATH_STRING)) {
7978*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, hay);
7979*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, needle);
7980*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_TYPE);
7981*6777b538SAndroid Build Coastguard Worker }
7982*6777b538SAndroid Build Coastguard Worker if (xmlStrstr(hay->stringval, needle->stringval))
7983*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 1));
7984*6777b538SAndroid Build Coastguard Worker else
7985*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 0));
7986*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, hay);
7987*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, needle);
7988*6777b538SAndroid Build Coastguard Worker }
7989*6777b538SAndroid Build Coastguard Worker
7990*6777b538SAndroid Build Coastguard Worker /**
7991*6777b538SAndroid Build Coastguard Worker * xmlXPathStartsWithFunction:
7992*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
7993*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
7994*6777b538SAndroid Build Coastguard Worker *
7995*6777b538SAndroid Build Coastguard Worker * Implement the starts-with() XPath function
7996*6777b538SAndroid Build Coastguard Worker * boolean starts-with(string, string)
7997*6777b538SAndroid Build Coastguard Worker * The starts-with function returns true if the first argument string
7998*6777b538SAndroid Build Coastguard Worker * starts with the second argument string, and otherwise returns false.
7999*6777b538SAndroid Build Coastguard Worker */
8000*6777b538SAndroid Build Coastguard Worker void
xmlXPathStartsWithFunction(xmlXPathParserContextPtr ctxt,int nargs)8001*6777b538SAndroid Build Coastguard Worker xmlXPathStartsWithFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8002*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr hay, needle;
8003*6777b538SAndroid Build Coastguard Worker int n;
8004*6777b538SAndroid Build Coastguard Worker
8005*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(2);
8006*6777b538SAndroid Build Coastguard Worker CAST_TO_STRING;
8007*6777b538SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_STRING);
8008*6777b538SAndroid Build Coastguard Worker needle = valuePop(ctxt);
8009*6777b538SAndroid Build Coastguard Worker CAST_TO_STRING;
8010*6777b538SAndroid Build Coastguard Worker hay = valuePop(ctxt);
8011*6777b538SAndroid Build Coastguard Worker
8012*6777b538SAndroid Build Coastguard Worker if ((hay == NULL) || (hay->type != XPATH_STRING)) {
8013*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, hay);
8014*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, needle);
8015*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_TYPE);
8016*6777b538SAndroid Build Coastguard Worker }
8017*6777b538SAndroid Build Coastguard Worker n = xmlStrlen(needle->stringval);
8018*6777b538SAndroid Build Coastguard Worker if (xmlStrncmp(hay->stringval, needle->stringval, n))
8019*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 0));
8020*6777b538SAndroid Build Coastguard Worker else
8021*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 1));
8022*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, hay);
8023*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, needle);
8024*6777b538SAndroid Build Coastguard Worker }
8025*6777b538SAndroid Build Coastguard Worker
8026*6777b538SAndroid Build Coastguard Worker /**
8027*6777b538SAndroid Build Coastguard Worker * xmlXPathSubstringFunction:
8028*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8029*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
8030*6777b538SAndroid Build Coastguard Worker *
8031*6777b538SAndroid Build Coastguard Worker * Implement the substring() XPath function
8032*6777b538SAndroid Build Coastguard Worker * string substring(string, number, number?)
8033*6777b538SAndroid Build Coastguard Worker * The substring function returns the substring of the first argument
8034*6777b538SAndroid Build Coastguard Worker * starting at the position specified in the second argument with
8035*6777b538SAndroid Build Coastguard Worker * length specified in the third argument. For example,
8036*6777b538SAndroid Build Coastguard Worker * substring("12345",2,3) returns "234". If the third argument is not
8037*6777b538SAndroid Build Coastguard Worker * specified, it returns the substring starting at the position specified
8038*6777b538SAndroid Build Coastguard Worker * in the second argument and continuing to the end of the string. For
8039*6777b538SAndroid Build Coastguard Worker * example, substring("12345",2) returns "2345". More precisely, each
8040*6777b538SAndroid Build Coastguard Worker * character in the string (see [3.6 Strings]) is considered to have a
8041*6777b538SAndroid Build Coastguard Worker * numeric position: the position of the first character is 1, the position
8042*6777b538SAndroid Build Coastguard Worker * of the second character is 2 and so on. The returned substring contains
8043*6777b538SAndroid Build Coastguard Worker * those characters for which the position of the character is greater than
8044*6777b538SAndroid Build Coastguard Worker * or equal to the second argument and, if the third argument is specified,
8045*6777b538SAndroid Build Coastguard Worker * less than the sum of the second and third arguments; the comparisons
8046*6777b538SAndroid Build Coastguard Worker * and addition used for the above follow the standard IEEE 754 rules. Thus:
8047*6777b538SAndroid Build Coastguard Worker * - substring("12345", 1.5, 2.6) returns "234"
8048*6777b538SAndroid Build Coastguard Worker * - substring("12345", 0, 3) returns "12"
8049*6777b538SAndroid Build Coastguard Worker * - substring("12345", 0 div 0, 3) returns ""
8050*6777b538SAndroid Build Coastguard Worker * - substring("12345", 1, 0 div 0) returns ""
8051*6777b538SAndroid Build Coastguard Worker * - substring("12345", -42, 1 div 0) returns "12345"
8052*6777b538SAndroid Build Coastguard Worker * - substring("12345", -1 div 0, 1 div 0) returns ""
8053*6777b538SAndroid Build Coastguard Worker */
8054*6777b538SAndroid Build Coastguard Worker void
xmlXPathSubstringFunction(xmlXPathParserContextPtr ctxt,int nargs)8055*6777b538SAndroid Build Coastguard Worker xmlXPathSubstringFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8056*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr str, start, len;
8057*6777b538SAndroid Build Coastguard Worker double le=0, in;
8058*6777b538SAndroid Build Coastguard Worker int i = 1, j = INT_MAX;
8059*6777b538SAndroid Build Coastguard Worker
8060*6777b538SAndroid Build Coastguard Worker if (nargs < 2) {
8061*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(2);
8062*6777b538SAndroid Build Coastguard Worker }
8063*6777b538SAndroid Build Coastguard Worker if (nargs > 3) {
8064*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(3);
8065*6777b538SAndroid Build Coastguard Worker }
8066*6777b538SAndroid Build Coastguard Worker /*
8067*6777b538SAndroid Build Coastguard Worker * take care of possible last (position) argument
8068*6777b538SAndroid Build Coastguard Worker */
8069*6777b538SAndroid Build Coastguard Worker if (nargs == 3) {
8070*6777b538SAndroid Build Coastguard Worker CAST_TO_NUMBER;
8071*6777b538SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_NUMBER);
8072*6777b538SAndroid Build Coastguard Worker len = valuePop(ctxt);
8073*6777b538SAndroid Build Coastguard Worker le = len->floatval;
8074*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, len);
8075*6777b538SAndroid Build Coastguard Worker }
8076*6777b538SAndroid Build Coastguard Worker
8077*6777b538SAndroid Build Coastguard Worker CAST_TO_NUMBER;
8078*6777b538SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_NUMBER);
8079*6777b538SAndroid Build Coastguard Worker start = valuePop(ctxt);
8080*6777b538SAndroid Build Coastguard Worker in = start->floatval;
8081*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, start);
8082*6777b538SAndroid Build Coastguard Worker CAST_TO_STRING;
8083*6777b538SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_STRING);
8084*6777b538SAndroid Build Coastguard Worker str = valuePop(ctxt);
8085*6777b538SAndroid Build Coastguard Worker
8086*6777b538SAndroid Build Coastguard Worker if (!(in < INT_MAX)) { /* Logical NOT to handle NaNs */
8087*6777b538SAndroid Build Coastguard Worker i = INT_MAX;
8088*6777b538SAndroid Build Coastguard Worker } else if (in >= 1.0) {
8089*6777b538SAndroid Build Coastguard Worker i = (int)in;
8090*6777b538SAndroid Build Coastguard Worker if (in - floor(in) >= 0.5)
8091*6777b538SAndroid Build Coastguard Worker i += 1;
8092*6777b538SAndroid Build Coastguard Worker }
8093*6777b538SAndroid Build Coastguard Worker
8094*6777b538SAndroid Build Coastguard Worker if (nargs == 3) {
8095*6777b538SAndroid Build Coastguard Worker double rin, rle, end;
8096*6777b538SAndroid Build Coastguard Worker
8097*6777b538SAndroid Build Coastguard Worker rin = floor(in);
8098*6777b538SAndroid Build Coastguard Worker if (in - rin >= 0.5)
8099*6777b538SAndroid Build Coastguard Worker rin += 1.0;
8100*6777b538SAndroid Build Coastguard Worker
8101*6777b538SAndroid Build Coastguard Worker rle = floor(le);
8102*6777b538SAndroid Build Coastguard Worker if (le - rle >= 0.5)
8103*6777b538SAndroid Build Coastguard Worker rle += 1.0;
8104*6777b538SAndroid Build Coastguard Worker
8105*6777b538SAndroid Build Coastguard Worker end = rin + rle;
8106*6777b538SAndroid Build Coastguard Worker if (!(end >= 1.0)) { /* Logical NOT to handle NaNs */
8107*6777b538SAndroid Build Coastguard Worker j = 1;
8108*6777b538SAndroid Build Coastguard Worker } else if (end < INT_MAX) {
8109*6777b538SAndroid Build Coastguard Worker j = (int)end;
8110*6777b538SAndroid Build Coastguard Worker }
8111*6777b538SAndroid Build Coastguard Worker }
8112*6777b538SAndroid Build Coastguard Worker
8113*6777b538SAndroid Build Coastguard Worker i -= 1;
8114*6777b538SAndroid Build Coastguard Worker j -= 1;
8115*6777b538SAndroid Build Coastguard Worker
8116*6777b538SAndroid Build Coastguard Worker if ((i < j) && (i < xmlUTF8Strlen(str->stringval))) {
8117*6777b538SAndroid Build Coastguard Worker xmlChar *ret = xmlUTF8Strsub(str->stringval, i, j - i);
8118*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
8119*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
8120*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewString(ctxt, ret));
8121*6777b538SAndroid Build Coastguard Worker xmlFree(ret);
8122*6777b538SAndroid Build Coastguard Worker } else {
8123*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewCString(ctxt, ""));
8124*6777b538SAndroid Build Coastguard Worker }
8125*6777b538SAndroid Build Coastguard Worker
8126*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, str);
8127*6777b538SAndroid Build Coastguard Worker }
8128*6777b538SAndroid Build Coastguard Worker
8129*6777b538SAndroid Build Coastguard Worker /**
8130*6777b538SAndroid Build Coastguard Worker * xmlXPathSubstringBeforeFunction:
8131*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8132*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
8133*6777b538SAndroid Build Coastguard Worker *
8134*6777b538SAndroid Build Coastguard Worker * Implement the substring-before() XPath function
8135*6777b538SAndroid Build Coastguard Worker * string substring-before(string, string)
8136*6777b538SAndroid Build Coastguard Worker * The substring-before function returns the substring of the first
8137*6777b538SAndroid Build Coastguard Worker * argument string that precedes the first occurrence of the second
8138*6777b538SAndroid Build Coastguard Worker * argument string in the first argument string, or the empty string
8139*6777b538SAndroid Build Coastguard Worker * if the first argument string does not contain the second argument
8140*6777b538SAndroid Build Coastguard Worker * string. For example, substring-before("1999/04/01","/") returns 1999.
8141*6777b538SAndroid Build Coastguard Worker */
8142*6777b538SAndroid Build Coastguard Worker void
xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt,int nargs)8143*6777b538SAndroid Build Coastguard Worker xmlXPathSubstringBeforeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8144*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr str = NULL;
8145*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr find = NULL;
8146*6777b538SAndroid Build Coastguard Worker const xmlChar *point;
8147*6777b538SAndroid Build Coastguard Worker xmlChar *result;
8148*6777b538SAndroid Build Coastguard Worker
8149*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(2);
8150*6777b538SAndroid Build Coastguard Worker CAST_TO_STRING;
8151*6777b538SAndroid Build Coastguard Worker find = valuePop(ctxt);
8152*6777b538SAndroid Build Coastguard Worker CAST_TO_STRING;
8153*6777b538SAndroid Build Coastguard Worker str = valuePop(ctxt);
8154*6777b538SAndroid Build Coastguard Worker if (ctxt->error != 0)
8155*6777b538SAndroid Build Coastguard Worker goto error;
8156*6777b538SAndroid Build Coastguard Worker
8157*6777b538SAndroid Build Coastguard Worker point = xmlStrstr(str->stringval, find->stringval);
8158*6777b538SAndroid Build Coastguard Worker if (point == NULL) {
8159*6777b538SAndroid Build Coastguard Worker result = xmlStrdup(BAD_CAST "");
8160*6777b538SAndroid Build Coastguard Worker } else {
8161*6777b538SAndroid Build Coastguard Worker result = xmlStrndup(str->stringval, point - str->stringval);
8162*6777b538SAndroid Build Coastguard Worker }
8163*6777b538SAndroid Build Coastguard Worker if (result == NULL) {
8164*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
8165*6777b538SAndroid Build Coastguard Worker goto error;
8166*6777b538SAndroid Build Coastguard Worker }
8167*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheWrapString(ctxt, result));
8168*6777b538SAndroid Build Coastguard Worker
8169*6777b538SAndroid Build Coastguard Worker error:
8170*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, str);
8171*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, find);
8172*6777b538SAndroid Build Coastguard Worker }
8173*6777b538SAndroid Build Coastguard Worker
8174*6777b538SAndroid Build Coastguard Worker /**
8175*6777b538SAndroid Build Coastguard Worker * xmlXPathSubstringAfterFunction:
8176*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8177*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
8178*6777b538SAndroid Build Coastguard Worker *
8179*6777b538SAndroid Build Coastguard Worker * Implement the substring-after() XPath function
8180*6777b538SAndroid Build Coastguard Worker * string substring-after(string, string)
8181*6777b538SAndroid Build Coastguard Worker * The substring-after function returns the substring of the first
8182*6777b538SAndroid Build Coastguard Worker * argument string that follows the first occurrence of the second
8183*6777b538SAndroid Build Coastguard Worker * argument string in the first argument string, or the empty string
8184*6777b538SAndroid Build Coastguard Worker * if the first argument string does not contain the second argument
8185*6777b538SAndroid Build Coastguard Worker * string. For example, substring-after("1999/04/01","/") returns 04/01,
8186*6777b538SAndroid Build Coastguard Worker * and substring-after("1999/04/01","19") returns 99/04/01.
8187*6777b538SAndroid Build Coastguard Worker */
8188*6777b538SAndroid Build Coastguard Worker void
xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt,int nargs)8189*6777b538SAndroid Build Coastguard Worker xmlXPathSubstringAfterFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8190*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr str = NULL;
8191*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr find = NULL;
8192*6777b538SAndroid Build Coastguard Worker const xmlChar *point;
8193*6777b538SAndroid Build Coastguard Worker xmlChar *result;
8194*6777b538SAndroid Build Coastguard Worker
8195*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(2);
8196*6777b538SAndroid Build Coastguard Worker CAST_TO_STRING;
8197*6777b538SAndroid Build Coastguard Worker find = valuePop(ctxt);
8198*6777b538SAndroid Build Coastguard Worker CAST_TO_STRING;
8199*6777b538SAndroid Build Coastguard Worker str = valuePop(ctxt);
8200*6777b538SAndroid Build Coastguard Worker if (ctxt->error != 0)
8201*6777b538SAndroid Build Coastguard Worker goto error;
8202*6777b538SAndroid Build Coastguard Worker
8203*6777b538SAndroid Build Coastguard Worker point = xmlStrstr(str->stringval, find->stringval);
8204*6777b538SAndroid Build Coastguard Worker if (point == NULL) {
8205*6777b538SAndroid Build Coastguard Worker result = xmlStrdup(BAD_CAST "");
8206*6777b538SAndroid Build Coastguard Worker } else {
8207*6777b538SAndroid Build Coastguard Worker result = xmlStrdup(point + xmlStrlen(find->stringval));
8208*6777b538SAndroid Build Coastguard Worker }
8209*6777b538SAndroid Build Coastguard Worker if (result == NULL) {
8210*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
8211*6777b538SAndroid Build Coastguard Worker goto error;
8212*6777b538SAndroid Build Coastguard Worker }
8213*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheWrapString(ctxt, result));
8214*6777b538SAndroid Build Coastguard Worker
8215*6777b538SAndroid Build Coastguard Worker error:
8216*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, str);
8217*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, find);
8218*6777b538SAndroid Build Coastguard Worker }
8219*6777b538SAndroid Build Coastguard Worker
8220*6777b538SAndroid Build Coastguard Worker /**
8221*6777b538SAndroid Build Coastguard Worker * xmlXPathNormalizeFunction:
8222*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8223*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
8224*6777b538SAndroid Build Coastguard Worker *
8225*6777b538SAndroid Build Coastguard Worker * Implement the normalize-space() XPath function
8226*6777b538SAndroid Build Coastguard Worker * string normalize-space(string?)
8227*6777b538SAndroid Build Coastguard Worker * The normalize-space function returns the argument string with white
8228*6777b538SAndroid Build Coastguard Worker * space normalized by stripping leading and trailing whitespace
8229*6777b538SAndroid Build Coastguard Worker * and replacing sequences of whitespace characters by a single
8230*6777b538SAndroid Build Coastguard Worker * space. Whitespace characters are the same allowed by the S production
8231*6777b538SAndroid Build Coastguard Worker * in XML. If the argument is omitted, it defaults to the context
8232*6777b538SAndroid Build Coastguard Worker * node converted to a string, in other words the value of the context node.
8233*6777b538SAndroid Build Coastguard Worker */
8234*6777b538SAndroid Build Coastguard Worker void
xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt,int nargs)8235*6777b538SAndroid Build Coastguard Worker xmlXPathNormalizeFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8236*6777b538SAndroid Build Coastguard Worker xmlChar *source, *target;
8237*6777b538SAndroid Build Coastguard Worker int blank;
8238*6777b538SAndroid Build Coastguard Worker
8239*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL) return;
8240*6777b538SAndroid Build Coastguard Worker if (nargs == 0) {
8241*6777b538SAndroid Build Coastguard Worker /* Use current context node */
8242*6777b538SAndroid Build Coastguard Worker source = xmlXPathCastNodeToString(ctxt->context->node);
8243*6777b538SAndroid Build Coastguard Worker if (source == NULL)
8244*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
8245*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheWrapString(ctxt, source));
8246*6777b538SAndroid Build Coastguard Worker nargs = 1;
8247*6777b538SAndroid Build Coastguard Worker }
8248*6777b538SAndroid Build Coastguard Worker
8249*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(1);
8250*6777b538SAndroid Build Coastguard Worker CAST_TO_STRING;
8251*6777b538SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_STRING);
8252*6777b538SAndroid Build Coastguard Worker source = ctxt->value->stringval;
8253*6777b538SAndroid Build Coastguard Worker if (source == NULL)
8254*6777b538SAndroid Build Coastguard Worker return;
8255*6777b538SAndroid Build Coastguard Worker target = source;
8256*6777b538SAndroid Build Coastguard Worker
8257*6777b538SAndroid Build Coastguard Worker /* Skip leading whitespaces */
8258*6777b538SAndroid Build Coastguard Worker while (IS_BLANK_CH(*source))
8259*6777b538SAndroid Build Coastguard Worker source++;
8260*6777b538SAndroid Build Coastguard Worker
8261*6777b538SAndroid Build Coastguard Worker /* Collapse intermediate whitespaces, and skip trailing whitespaces */
8262*6777b538SAndroid Build Coastguard Worker blank = 0;
8263*6777b538SAndroid Build Coastguard Worker while (*source) {
8264*6777b538SAndroid Build Coastguard Worker if (IS_BLANK_CH(*source)) {
8265*6777b538SAndroid Build Coastguard Worker blank = 1;
8266*6777b538SAndroid Build Coastguard Worker } else {
8267*6777b538SAndroid Build Coastguard Worker if (blank) {
8268*6777b538SAndroid Build Coastguard Worker *target++ = 0x20;
8269*6777b538SAndroid Build Coastguard Worker blank = 0;
8270*6777b538SAndroid Build Coastguard Worker }
8271*6777b538SAndroid Build Coastguard Worker *target++ = *source;
8272*6777b538SAndroid Build Coastguard Worker }
8273*6777b538SAndroid Build Coastguard Worker source++;
8274*6777b538SAndroid Build Coastguard Worker }
8275*6777b538SAndroid Build Coastguard Worker *target = 0;
8276*6777b538SAndroid Build Coastguard Worker }
8277*6777b538SAndroid Build Coastguard Worker
8278*6777b538SAndroid Build Coastguard Worker /**
8279*6777b538SAndroid Build Coastguard Worker * xmlXPathTranslateFunction:
8280*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8281*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
8282*6777b538SAndroid Build Coastguard Worker *
8283*6777b538SAndroid Build Coastguard Worker * Implement the translate() XPath function
8284*6777b538SAndroid Build Coastguard Worker * string translate(string, string, string)
8285*6777b538SAndroid Build Coastguard Worker * The translate function returns the first argument string with
8286*6777b538SAndroid Build Coastguard Worker * occurrences of characters in the second argument string replaced
8287*6777b538SAndroid Build Coastguard Worker * by the character at the corresponding position in the third argument
8288*6777b538SAndroid Build Coastguard Worker * string. For example, translate("bar","abc","ABC") returns the string
8289*6777b538SAndroid Build Coastguard Worker * BAr. If there is a character in the second argument string with no
8290*6777b538SAndroid Build Coastguard Worker * character at a corresponding position in the third argument string
8291*6777b538SAndroid Build Coastguard Worker * (because the second argument string is longer than the third argument
8292*6777b538SAndroid Build Coastguard Worker * string), then occurrences of that character in the first argument
8293*6777b538SAndroid Build Coastguard Worker * string are removed. For example, translate("--aaa--","abc-","ABC")
8294*6777b538SAndroid Build Coastguard Worker * returns "AAA". If a character occurs more than once in second
8295*6777b538SAndroid Build Coastguard Worker * argument string, then the first occurrence determines the replacement
8296*6777b538SAndroid Build Coastguard Worker * character. If the third argument string is longer than the second
8297*6777b538SAndroid Build Coastguard Worker * argument string, then excess characters are ignored.
8298*6777b538SAndroid Build Coastguard Worker */
8299*6777b538SAndroid Build Coastguard Worker void
xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt,int nargs)8300*6777b538SAndroid Build Coastguard Worker xmlXPathTranslateFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8301*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr str = NULL;
8302*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr from = NULL;
8303*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr to = NULL;
8304*6777b538SAndroid Build Coastguard Worker xmlBufPtr target;
8305*6777b538SAndroid Build Coastguard Worker int offset, max;
8306*6777b538SAndroid Build Coastguard Worker int ch;
8307*6777b538SAndroid Build Coastguard Worker const xmlChar *point;
8308*6777b538SAndroid Build Coastguard Worker xmlChar *cptr, *content;
8309*6777b538SAndroid Build Coastguard Worker
8310*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(3);
8311*6777b538SAndroid Build Coastguard Worker
8312*6777b538SAndroid Build Coastguard Worker CAST_TO_STRING;
8313*6777b538SAndroid Build Coastguard Worker to = valuePop(ctxt);
8314*6777b538SAndroid Build Coastguard Worker CAST_TO_STRING;
8315*6777b538SAndroid Build Coastguard Worker from = valuePop(ctxt);
8316*6777b538SAndroid Build Coastguard Worker CAST_TO_STRING;
8317*6777b538SAndroid Build Coastguard Worker str = valuePop(ctxt);
8318*6777b538SAndroid Build Coastguard Worker if (ctxt->error != 0)
8319*6777b538SAndroid Build Coastguard Worker goto error;
8320*6777b538SAndroid Build Coastguard Worker
8321*6777b538SAndroid Build Coastguard Worker target = xmlBufCreate();
8322*6777b538SAndroid Build Coastguard Worker if (target == NULL) {
8323*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
8324*6777b538SAndroid Build Coastguard Worker goto error;
8325*6777b538SAndroid Build Coastguard Worker }
8326*6777b538SAndroid Build Coastguard Worker
8327*6777b538SAndroid Build Coastguard Worker max = xmlUTF8Strlen(to->stringval);
8328*6777b538SAndroid Build Coastguard Worker for (cptr = str->stringval; (ch=*cptr); ) {
8329*6777b538SAndroid Build Coastguard Worker offset = xmlUTF8Strloc(from->stringval, cptr);
8330*6777b538SAndroid Build Coastguard Worker if (offset >= 0) {
8331*6777b538SAndroid Build Coastguard Worker if (offset < max) {
8332*6777b538SAndroid Build Coastguard Worker point = xmlUTF8Strpos(to->stringval, offset);
8333*6777b538SAndroid Build Coastguard Worker if (point)
8334*6777b538SAndroid Build Coastguard Worker xmlBufAdd(target, point, xmlUTF8Strsize(point, 1));
8335*6777b538SAndroid Build Coastguard Worker }
8336*6777b538SAndroid Build Coastguard Worker } else
8337*6777b538SAndroid Build Coastguard Worker xmlBufAdd(target, cptr, xmlUTF8Strsize(cptr, 1));
8338*6777b538SAndroid Build Coastguard Worker
8339*6777b538SAndroid Build Coastguard Worker /* Step to next character in input */
8340*6777b538SAndroid Build Coastguard Worker cptr++;
8341*6777b538SAndroid Build Coastguard Worker if ( ch & 0x80 ) {
8342*6777b538SAndroid Build Coastguard Worker /* if not simple ascii, verify proper format */
8343*6777b538SAndroid Build Coastguard Worker if ( (ch & 0xc0) != 0xc0 ) {
8344*6777b538SAndroid Build Coastguard Worker xmlXPathErr(ctxt, XPATH_INVALID_CHAR_ERROR);
8345*6777b538SAndroid Build Coastguard Worker break;
8346*6777b538SAndroid Build Coastguard Worker }
8347*6777b538SAndroid Build Coastguard Worker /* then skip over remaining bytes for this char */
8348*6777b538SAndroid Build Coastguard Worker while ( (ch <<= 1) & 0x80 )
8349*6777b538SAndroid Build Coastguard Worker if ( (*cptr++ & 0xc0) != 0x80 ) {
8350*6777b538SAndroid Build Coastguard Worker xmlXPathErr(ctxt, XPATH_INVALID_CHAR_ERROR);
8351*6777b538SAndroid Build Coastguard Worker break;
8352*6777b538SAndroid Build Coastguard Worker }
8353*6777b538SAndroid Build Coastguard Worker if (ch & 0x80) /* must have had error encountered */
8354*6777b538SAndroid Build Coastguard Worker break;
8355*6777b538SAndroid Build Coastguard Worker }
8356*6777b538SAndroid Build Coastguard Worker }
8357*6777b538SAndroid Build Coastguard Worker
8358*6777b538SAndroid Build Coastguard Worker content = xmlBufDetach(target);
8359*6777b538SAndroid Build Coastguard Worker if (content == NULL)
8360*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
8361*6777b538SAndroid Build Coastguard Worker else
8362*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheWrapString(ctxt, content));
8363*6777b538SAndroid Build Coastguard Worker xmlBufFree(target);
8364*6777b538SAndroid Build Coastguard Worker error:
8365*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, str);
8366*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, from);
8367*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, to);
8368*6777b538SAndroid Build Coastguard Worker }
8369*6777b538SAndroid Build Coastguard Worker
8370*6777b538SAndroid Build Coastguard Worker /**
8371*6777b538SAndroid Build Coastguard Worker * xmlXPathBooleanFunction:
8372*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8373*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
8374*6777b538SAndroid Build Coastguard Worker *
8375*6777b538SAndroid Build Coastguard Worker * Implement the boolean() XPath function
8376*6777b538SAndroid Build Coastguard Worker * boolean boolean(object)
8377*6777b538SAndroid Build Coastguard Worker * The boolean function converts its argument to a boolean as follows:
8378*6777b538SAndroid Build Coastguard Worker * - a number is true if and only if it is neither positive or
8379*6777b538SAndroid Build Coastguard Worker * negative zero nor NaN
8380*6777b538SAndroid Build Coastguard Worker * - a node-set is true if and only if it is non-empty
8381*6777b538SAndroid Build Coastguard Worker * - a string is true if and only if its length is non-zero
8382*6777b538SAndroid Build Coastguard Worker */
8383*6777b538SAndroid Build Coastguard Worker void
xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt,int nargs)8384*6777b538SAndroid Build Coastguard Worker xmlXPathBooleanFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8385*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr cur;
8386*6777b538SAndroid Build Coastguard Worker
8387*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(1);
8388*6777b538SAndroid Build Coastguard Worker cur = valuePop(ctxt);
8389*6777b538SAndroid Build Coastguard Worker if (cur == NULL) XP_ERROR(XPATH_INVALID_OPERAND);
8390*6777b538SAndroid Build Coastguard Worker if (cur->type != XPATH_BOOLEAN) {
8391*6777b538SAndroid Build Coastguard Worker int boolval = xmlXPathCastToBoolean(cur);
8392*6777b538SAndroid Build Coastguard Worker
8393*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, cur);
8394*6777b538SAndroid Build Coastguard Worker cur = xmlXPathCacheNewBoolean(ctxt, boolval);
8395*6777b538SAndroid Build Coastguard Worker }
8396*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, cur);
8397*6777b538SAndroid Build Coastguard Worker }
8398*6777b538SAndroid Build Coastguard Worker
8399*6777b538SAndroid Build Coastguard Worker /**
8400*6777b538SAndroid Build Coastguard Worker * xmlXPathNotFunction:
8401*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8402*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
8403*6777b538SAndroid Build Coastguard Worker *
8404*6777b538SAndroid Build Coastguard Worker * Implement the not() XPath function
8405*6777b538SAndroid Build Coastguard Worker * boolean not(boolean)
8406*6777b538SAndroid Build Coastguard Worker * The not function returns true if its argument is false,
8407*6777b538SAndroid Build Coastguard Worker * and false otherwise.
8408*6777b538SAndroid Build Coastguard Worker */
8409*6777b538SAndroid Build Coastguard Worker void
xmlXPathNotFunction(xmlXPathParserContextPtr ctxt,int nargs)8410*6777b538SAndroid Build Coastguard Worker xmlXPathNotFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8411*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(1);
8412*6777b538SAndroid Build Coastguard Worker CAST_TO_BOOLEAN;
8413*6777b538SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_BOOLEAN);
8414*6777b538SAndroid Build Coastguard Worker ctxt->value->boolval = ! ctxt->value->boolval;
8415*6777b538SAndroid Build Coastguard Worker }
8416*6777b538SAndroid Build Coastguard Worker
8417*6777b538SAndroid Build Coastguard Worker /**
8418*6777b538SAndroid Build Coastguard Worker * xmlXPathTrueFunction:
8419*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8420*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
8421*6777b538SAndroid Build Coastguard Worker *
8422*6777b538SAndroid Build Coastguard Worker * Implement the true() XPath function
8423*6777b538SAndroid Build Coastguard Worker * boolean true()
8424*6777b538SAndroid Build Coastguard Worker */
8425*6777b538SAndroid Build Coastguard Worker void
xmlXPathTrueFunction(xmlXPathParserContextPtr ctxt,int nargs)8426*6777b538SAndroid Build Coastguard Worker xmlXPathTrueFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8427*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(0);
8428*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 1));
8429*6777b538SAndroid Build Coastguard Worker }
8430*6777b538SAndroid Build Coastguard Worker
8431*6777b538SAndroid Build Coastguard Worker /**
8432*6777b538SAndroid Build Coastguard Worker * xmlXPathFalseFunction:
8433*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8434*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
8435*6777b538SAndroid Build Coastguard Worker *
8436*6777b538SAndroid Build Coastguard Worker * Implement the false() XPath function
8437*6777b538SAndroid Build Coastguard Worker * boolean false()
8438*6777b538SAndroid Build Coastguard Worker */
8439*6777b538SAndroid Build Coastguard Worker void
xmlXPathFalseFunction(xmlXPathParserContextPtr ctxt,int nargs)8440*6777b538SAndroid Build Coastguard Worker xmlXPathFalseFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8441*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(0);
8442*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, 0));
8443*6777b538SAndroid Build Coastguard Worker }
8444*6777b538SAndroid Build Coastguard Worker
8445*6777b538SAndroid Build Coastguard Worker /**
8446*6777b538SAndroid Build Coastguard Worker * xmlXPathLangFunction:
8447*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8448*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
8449*6777b538SAndroid Build Coastguard Worker *
8450*6777b538SAndroid Build Coastguard Worker * Implement the lang() XPath function
8451*6777b538SAndroid Build Coastguard Worker * boolean lang(string)
8452*6777b538SAndroid Build Coastguard Worker * The lang function returns true or false depending on whether the
8453*6777b538SAndroid Build Coastguard Worker * language of the context node as specified by xml:lang attributes
8454*6777b538SAndroid Build Coastguard Worker * is the same as or is a sublanguage of the language specified by
8455*6777b538SAndroid Build Coastguard Worker * the argument string. The language of the context node is determined
8456*6777b538SAndroid Build Coastguard Worker * by the value of the xml:lang attribute on the context node, or, if
8457*6777b538SAndroid Build Coastguard Worker * the context node has no xml:lang attribute, by the value of the
8458*6777b538SAndroid Build Coastguard Worker * xml:lang attribute on the nearest ancestor of the context node that
8459*6777b538SAndroid Build Coastguard Worker * has an xml:lang attribute. If there is no such attribute, then lang
8460*6777b538SAndroid Build Coastguard Worker * returns false. If there is such an attribute, then lang returns
8461*6777b538SAndroid Build Coastguard Worker * true if the attribute value is equal to the argument ignoring case,
8462*6777b538SAndroid Build Coastguard Worker * or if there is some suffix starting with - such that the attribute
8463*6777b538SAndroid Build Coastguard Worker * value is equal to the argument ignoring that suffix of the attribute
8464*6777b538SAndroid Build Coastguard Worker * value and ignoring case.
8465*6777b538SAndroid Build Coastguard Worker */
8466*6777b538SAndroid Build Coastguard Worker void
xmlXPathLangFunction(xmlXPathParserContextPtr ctxt,int nargs)8467*6777b538SAndroid Build Coastguard Worker xmlXPathLangFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8468*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr val;
8469*6777b538SAndroid Build Coastguard Worker xmlNodePtr cur;
8470*6777b538SAndroid Build Coastguard Worker xmlChar *theLang;
8471*6777b538SAndroid Build Coastguard Worker const xmlChar *lang;
8472*6777b538SAndroid Build Coastguard Worker int ret = 0;
8473*6777b538SAndroid Build Coastguard Worker int i;
8474*6777b538SAndroid Build Coastguard Worker
8475*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(1);
8476*6777b538SAndroid Build Coastguard Worker CAST_TO_STRING;
8477*6777b538SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_STRING);
8478*6777b538SAndroid Build Coastguard Worker val = valuePop(ctxt);
8479*6777b538SAndroid Build Coastguard Worker lang = val->stringval;
8480*6777b538SAndroid Build Coastguard Worker cur = ctxt->context->node;
8481*6777b538SAndroid Build Coastguard Worker while (cur != NULL) {
8482*6777b538SAndroid Build Coastguard Worker if (xmlNodeGetAttrValue(cur, BAD_CAST "lang", XML_XML_NAMESPACE,
8483*6777b538SAndroid Build Coastguard Worker &theLang) < 0)
8484*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
8485*6777b538SAndroid Build Coastguard Worker if (theLang != NULL)
8486*6777b538SAndroid Build Coastguard Worker break;
8487*6777b538SAndroid Build Coastguard Worker cur = cur->parent;
8488*6777b538SAndroid Build Coastguard Worker }
8489*6777b538SAndroid Build Coastguard Worker if ((theLang != NULL) && (lang != NULL)) {
8490*6777b538SAndroid Build Coastguard Worker for (i = 0;lang[i] != 0;i++)
8491*6777b538SAndroid Build Coastguard Worker if (toupper(lang[i]) != toupper(theLang[i]))
8492*6777b538SAndroid Build Coastguard Worker goto not_equal;
8493*6777b538SAndroid Build Coastguard Worker if ((theLang[i] == 0) || (theLang[i] == '-'))
8494*6777b538SAndroid Build Coastguard Worker ret = 1;
8495*6777b538SAndroid Build Coastguard Worker }
8496*6777b538SAndroid Build Coastguard Worker not_equal:
8497*6777b538SAndroid Build Coastguard Worker if (theLang != NULL)
8498*6777b538SAndroid Build Coastguard Worker xmlFree((void *)theLang);
8499*6777b538SAndroid Build Coastguard Worker
8500*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, val);
8501*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, ret));
8502*6777b538SAndroid Build Coastguard Worker }
8503*6777b538SAndroid Build Coastguard Worker
8504*6777b538SAndroid Build Coastguard Worker /**
8505*6777b538SAndroid Build Coastguard Worker * xmlXPathNumberFunction:
8506*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8507*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
8508*6777b538SAndroid Build Coastguard Worker *
8509*6777b538SAndroid Build Coastguard Worker * Implement the number() XPath function
8510*6777b538SAndroid Build Coastguard Worker * number number(object?)
8511*6777b538SAndroid Build Coastguard Worker */
8512*6777b538SAndroid Build Coastguard Worker void
xmlXPathNumberFunction(xmlXPathParserContextPtr ctxt,int nargs)8513*6777b538SAndroid Build Coastguard Worker xmlXPathNumberFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8514*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr cur;
8515*6777b538SAndroid Build Coastguard Worker double res;
8516*6777b538SAndroid Build Coastguard Worker
8517*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL) return;
8518*6777b538SAndroid Build Coastguard Worker if (nargs == 0) {
8519*6777b538SAndroid Build Coastguard Worker if (ctxt->context->node == NULL) {
8520*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, 0.0));
8521*6777b538SAndroid Build Coastguard Worker } else {
8522*6777b538SAndroid Build Coastguard Worker xmlChar* content = xmlNodeGetContent(ctxt->context->node);
8523*6777b538SAndroid Build Coastguard Worker if (content == NULL)
8524*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
8525*6777b538SAndroid Build Coastguard Worker
8526*6777b538SAndroid Build Coastguard Worker res = xmlXPathStringEvalNumber(content);
8527*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, res));
8528*6777b538SAndroid Build Coastguard Worker xmlFree(content);
8529*6777b538SAndroid Build Coastguard Worker }
8530*6777b538SAndroid Build Coastguard Worker return;
8531*6777b538SAndroid Build Coastguard Worker }
8532*6777b538SAndroid Build Coastguard Worker
8533*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(1);
8534*6777b538SAndroid Build Coastguard Worker cur = valuePop(ctxt);
8535*6777b538SAndroid Build Coastguard Worker if (cur->type != XPATH_NUMBER) {
8536*6777b538SAndroid Build Coastguard Worker double floatval;
8537*6777b538SAndroid Build Coastguard Worker
8538*6777b538SAndroid Build Coastguard Worker floatval = xmlXPathCastToNumberInternal(ctxt, cur);
8539*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, cur);
8540*6777b538SAndroid Build Coastguard Worker cur = xmlXPathCacheNewFloat(ctxt, floatval);
8541*6777b538SAndroid Build Coastguard Worker }
8542*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, cur);
8543*6777b538SAndroid Build Coastguard Worker }
8544*6777b538SAndroid Build Coastguard Worker
8545*6777b538SAndroid Build Coastguard Worker /**
8546*6777b538SAndroid Build Coastguard Worker * xmlXPathSumFunction:
8547*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8548*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
8549*6777b538SAndroid Build Coastguard Worker *
8550*6777b538SAndroid Build Coastguard Worker * Implement the sum() XPath function
8551*6777b538SAndroid Build Coastguard Worker * number sum(node-set)
8552*6777b538SAndroid Build Coastguard Worker * The sum function returns the sum of the values of the nodes in
8553*6777b538SAndroid Build Coastguard Worker * the argument node-set.
8554*6777b538SAndroid Build Coastguard Worker */
8555*6777b538SAndroid Build Coastguard Worker void
xmlXPathSumFunction(xmlXPathParserContextPtr ctxt,int nargs)8556*6777b538SAndroid Build Coastguard Worker xmlXPathSumFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8557*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr cur;
8558*6777b538SAndroid Build Coastguard Worker int i;
8559*6777b538SAndroid Build Coastguard Worker double res = 0.0;
8560*6777b538SAndroid Build Coastguard Worker
8561*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(1);
8562*6777b538SAndroid Build Coastguard Worker if ((ctxt->value == NULL) ||
8563*6777b538SAndroid Build Coastguard Worker ((ctxt->value->type != XPATH_NODESET) &&
8564*6777b538SAndroid Build Coastguard Worker (ctxt->value->type != XPATH_XSLT_TREE)))
8565*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_TYPE);
8566*6777b538SAndroid Build Coastguard Worker cur = valuePop(ctxt);
8567*6777b538SAndroid Build Coastguard Worker
8568*6777b538SAndroid Build Coastguard Worker if ((cur->nodesetval != NULL) && (cur->nodesetval->nodeNr != 0)) {
8569*6777b538SAndroid Build Coastguard Worker for (i = 0; i < cur->nodesetval->nodeNr; i++) {
8570*6777b538SAndroid Build Coastguard Worker res += xmlXPathNodeToNumberInternal(ctxt,
8571*6777b538SAndroid Build Coastguard Worker cur->nodesetval->nodeTab[i]);
8572*6777b538SAndroid Build Coastguard Worker }
8573*6777b538SAndroid Build Coastguard Worker }
8574*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewFloat(ctxt, res));
8575*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, cur);
8576*6777b538SAndroid Build Coastguard Worker }
8577*6777b538SAndroid Build Coastguard Worker
8578*6777b538SAndroid Build Coastguard Worker /**
8579*6777b538SAndroid Build Coastguard Worker * xmlXPathFloorFunction:
8580*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8581*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
8582*6777b538SAndroid Build Coastguard Worker *
8583*6777b538SAndroid Build Coastguard Worker * Implement the floor() XPath function
8584*6777b538SAndroid Build Coastguard Worker * number floor(number)
8585*6777b538SAndroid Build Coastguard Worker * The floor function returns the largest (closest to positive infinity)
8586*6777b538SAndroid Build Coastguard Worker * number that is not greater than the argument and that is an integer.
8587*6777b538SAndroid Build Coastguard Worker */
8588*6777b538SAndroid Build Coastguard Worker void
xmlXPathFloorFunction(xmlXPathParserContextPtr ctxt,int nargs)8589*6777b538SAndroid Build Coastguard Worker xmlXPathFloorFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8590*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(1);
8591*6777b538SAndroid Build Coastguard Worker CAST_TO_NUMBER;
8592*6777b538SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_NUMBER);
8593*6777b538SAndroid Build Coastguard Worker
8594*6777b538SAndroid Build Coastguard Worker ctxt->value->floatval = floor(ctxt->value->floatval);
8595*6777b538SAndroid Build Coastguard Worker }
8596*6777b538SAndroid Build Coastguard Worker
8597*6777b538SAndroid Build Coastguard Worker /**
8598*6777b538SAndroid Build Coastguard Worker * xmlXPathCeilingFunction:
8599*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8600*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
8601*6777b538SAndroid Build Coastguard Worker *
8602*6777b538SAndroid Build Coastguard Worker * Implement the ceiling() XPath function
8603*6777b538SAndroid Build Coastguard Worker * number ceiling(number)
8604*6777b538SAndroid Build Coastguard Worker * The ceiling function returns the smallest (closest to negative infinity)
8605*6777b538SAndroid Build Coastguard Worker * number that is not less than the argument and that is an integer.
8606*6777b538SAndroid Build Coastguard Worker */
8607*6777b538SAndroid Build Coastguard Worker void
xmlXPathCeilingFunction(xmlXPathParserContextPtr ctxt,int nargs)8608*6777b538SAndroid Build Coastguard Worker xmlXPathCeilingFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8609*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(1);
8610*6777b538SAndroid Build Coastguard Worker CAST_TO_NUMBER;
8611*6777b538SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_NUMBER);
8612*6777b538SAndroid Build Coastguard Worker
8613*6777b538SAndroid Build Coastguard Worker #ifdef _AIX
8614*6777b538SAndroid Build Coastguard Worker /* Work around buggy ceil() function on AIX */
8615*6777b538SAndroid Build Coastguard Worker ctxt->value->floatval = copysign(ceil(ctxt->value->floatval), ctxt->value->floatval);
8616*6777b538SAndroid Build Coastguard Worker #else
8617*6777b538SAndroid Build Coastguard Worker ctxt->value->floatval = ceil(ctxt->value->floatval);
8618*6777b538SAndroid Build Coastguard Worker #endif
8619*6777b538SAndroid Build Coastguard Worker }
8620*6777b538SAndroid Build Coastguard Worker
8621*6777b538SAndroid Build Coastguard Worker /**
8622*6777b538SAndroid Build Coastguard Worker * xmlXPathRoundFunction:
8623*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8624*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
8625*6777b538SAndroid Build Coastguard Worker *
8626*6777b538SAndroid Build Coastguard Worker * Implement the round() XPath function
8627*6777b538SAndroid Build Coastguard Worker * number round(number)
8628*6777b538SAndroid Build Coastguard Worker * The round function returns the number that is closest to the
8629*6777b538SAndroid Build Coastguard Worker * argument and that is an integer. If there are two such numbers,
8630*6777b538SAndroid Build Coastguard Worker * then the one that is closest to positive infinity is returned.
8631*6777b538SAndroid Build Coastguard Worker */
8632*6777b538SAndroid Build Coastguard Worker void
xmlXPathRoundFunction(xmlXPathParserContextPtr ctxt,int nargs)8633*6777b538SAndroid Build Coastguard Worker xmlXPathRoundFunction(xmlXPathParserContextPtr ctxt, int nargs) {
8634*6777b538SAndroid Build Coastguard Worker double f;
8635*6777b538SAndroid Build Coastguard Worker
8636*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(1);
8637*6777b538SAndroid Build Coastguard Worker CAST_TO_NUMBER;
8638*6777b538SAndroid Build Coastguard Worker CHECK_TYPE(XPATH_NUMBER);
8639*6777b538SAndroid Build Coastguard Worker
8640*6777b538SAndroid Build Coastguard Worker f = ctxt->value->floatval;
8641*6777b538SAndroid Build Coastguard Worker
8642*6777b538SAndroid Build Coastguard Worker if ((f >= -0.5) && (f < 0.5)) {
8643*6777b538SAndroid Build Coastguard Worker /* Handles negative zero. */
8644*6777b538SAndroid Build Coastguard Worker ctxt->value->floatval *= 0.0;
8645*6777b538SAndroid Build Coastguard Worker }
8646*6777b538SAndroid Build Coastguard Worker else {
8647*6777b538SAndroid Build Coastguard Worker double rounded = floor(f);
8648*6777b538SAndroid Build Coastguard Worker if (f - rounded >= 0.5)
8649*6777b538SAndroid Build Coastguard Worker rounded += 1.0;
8650*6777b538SAndroid Build Coastguard Worker ctxt->value->floatval = rounded;
8651*6777b538SAndroid Build Coastguard Worker }
8652*6777b538SAndroid Build Coastguard Worker }
8653*6777b538SAndroid Build Coastguard Worker
8654*6777b538SAndroid Build Coastguard Worker /************************************************************************
8655*6777b538SAndroid Build Coastguard Worker * *
8656*6777b538SAndroid Build Coastguard Worker * The Parser *
8657*6777b538SAndroid Build Coastguard Worker * *
8658*6777b538SAndroid Build Coastguard Worker ************************************************************************/
8659*6777b538SAndroid Build Coastguard Worker
8660*6777b538SAndroid Build Coastguard Worker /*
8661*6777b538SAndroid Build Coastguard Worker * a few forward declarations since we use a recursive call based
8662*6777b538SAndroid Build Coastguard Worker * implementation.
8663*6777b538SAndroid Build Coastguard Worker */
8664*6777b538SAndroid Build Coastguard Worker static void xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt, int sort);
8665*6777b538SAndroid Build Coastguard Worker static void xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter);
8666*6777b538SAndroid Build Coastguard Worker static void xmlXPathCompLocationPath(xmlXPathParserContextPtr ctxt);
8667*6777b538SAndroid Build Coastguard Worker static void xmlXPathCompRelativeLocationPath(xmlXPathParserContextPtr ctxt);
8668*6777b538SAndroid Build Coastguard Worker static xmlChar * xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt,
8669*6777b538SAndroid Build Coastguard Worker int qualified);
8670*6777b538SAndroid Build Coastguard Worker
8671*6777b538SAndroid Build Coastguard Worker /**
8672*6777b538SAndroid Build Coastguard Worker * xmlXPathCurrentChar:
8673*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath parser context
8674*6777b538SAndroid Build Coastguard Worker * @cur: pointer to the beginning of the char
8675*6777b538SAndroid Build Coastguard Worker * @len: pointer to the length of the char read
8676*6777b538SAndroid Build Coastguard Worker *
8677*6777b538SAndroid Build Coastguard Worker * The current char value, if using UTF-8 this may actually span multiple
8678*6777b538SAndroid Build Coastguard Worker * bytes in the input buffer.
8679*6777b538SAndroid Build Coastguard Worker *
8680*6777b538SAndroid Build Coastguard Worker * Returns the current char value and its length
8681*6777b538SAndroid Build Coastguard Worker */
8682*6777b538SAndroid Build Coastguard Worker
8683*6777b538SAndroid Build Coastguard Worker static int
xmlXPathCurrentChar(xmlXPathParserContextPtr ctxt,int * len)8684*6777b538SAndroid Build Coastguard Worker xmlXPathCurrentChar(xmlXPathParserContextPtr ctxt, int *len) {
8685*6777b538SAndroid Build Coastguard Worker unsigned char c;
8686*6777b538SAndroid Build Coastguard Worker unsigned int val;
8687*6777b538SAndroid Build Coastguard Worker const xmlChar *cur;
8688*6777b538SAndroid Build Coastguard Worker
8689*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
8690*6777b538SAndroid Build Coastguard Worker return(0);
8691*6777b538SAndroid Build Coastguard Worker cur = ctxt->cur;
8692*6777b538SAndroid Build Coastguard Worker
8693*6777b538SAndroid Build Coastguard Worker /*
8694*6777b538SAndroid Build Coastguard Worker * We are supposed to handle UTF8, check it's valid
8695*6777b538SAndroid Build Coastguard Worker * From rfc2044: encoding of the Unicode values on UTF-8:
8696*6777b538SAndroid Build Coastguard Worker *
8697*6777b538SAndroid Build Coastguard Worker * UCS-4 range (hex.) UTF-8 octet sequence (binary)
8698*6777b538SAndroid Build Coastguard Worker * 0000 0000-0000 007F 0xxxxxxx
8699*6777b538SAndroid Build Coastguard Worker * 0000 0080-0000 07FF 110xxxxx 10xxxxxx
8700*6777b538SAndroid Build Coastguard Worker * 0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
8701*6777b538SAndroid Build Coastguard Worker *
8702*6777b538SAndroid Build Coastguard Worker * Check for the 0x110000 limit too
8703*6777b538SAndroid Build Coastguard Worker */
8704*6777b538SAndroid Build Coastguard Worker c = *cur;
8705*6777b538SAndroid Build Coastguard Worker if (c & 0x80) {
8706*6777b538SAndroid Build Coastguard Worker if ((cur[1] & 0xc0) != 0x80)
8707*6777b538SAndroid Build Coastguard Worker goto encoding_error;
8708*6777b538SAndroid Build Coastguard Worker if ((c & 0xe0) == 0xe0) {
8709*6777b538SAndroid Build Coastguard Worker
8710*6777b538SAndroid Build Coastguard Worker if ((cur[2] & 0xc0) != 0x80)
8711*6777b538SAndroid Build Coastguard Worker goto encoding_error;
8712*6777b538SAndroid Build Coastguard Worker if ((c & 0xf0) == 0xf0) {
8713*6777b538SAndroid Build Coastguard Worker if (((c & 0xf8) != 0xf0) ||
8714*6777b538SAndroid Build Coastguard Worker ((cur[3] & 0xc0) != 0x80))
8715*6777b538SAndroid Build Coastguard Worker goto encoding_error;
8716*6777b538SAndroid Build Coastguard Worker /* 4-byte code */
8717*6777b538SAndroid Build Coastguard Worker *len = 4;
8718*6777b538SAndroid Build Coastguard Worker val = (cur[0] & 0x7) << 18;
8719*6777b538SAndroid Build Coastguard Worker val |= (cur[1] & 0x3f) << 12;
8720*6777b538SAndroid Build Coastguard Worker val |= (cur[2] & 0x3f) << 6;
8721*6777b538SAndroid Build Coastguard Worker val |= cur[3] & 0x3f;
8722*6777b538SAndroid Build Coastguard Worker } else {
8723*6777b538SAndroid Build Coastguard Worker /* 3-byte code */
8724*6777b538SAndroid Build Coastguard Worker *len = 3;
8725*6777b538SAndroid Build Coastguard Worker val = (cur[0] & 0xf) << 12;
8726*6777b538SAndroid Build Coastguard Worker val |= (cur[1] & 0x3f) << 6;
8727*6777b538SAndroid Build Coastguard Worker val |= cur[2] & 0x3f;
8728*6777b538SAndroid Build Coastguard Worker }
8729*6777b538SAndroid Build Coastguard Worker } else {
8730*6777b538SAndroid Build Coastguard Worker /* 2-byte code */
8731*6777b538SAndroid Build Coastguard Worker *len = 2;
8732*6777b538SAndroid Build Coastguard Worker val = (cur[0] & 0x1f) << 6;
8733*6777b538SAndroid Build Coastguard Worker val |= cur[1] & 0x3f;
8734*6777b538SAndroid Build Coastguard Worker }
8735*6777b538SAndroid Build Coastguard Worker if (!IS_CHAR(val)) {
8736*6777b538SAndroid Build Coastguard Worker XP_ERROR0(XPATH_INVALID_CHAR_ERROR);
8737*6777b538SAndroid Build Coastguard Worker }
8738*6777b538SAndroid Build Coastguard Worker return(val);
8739*6777b538SAndroid Build Coastguard Worker } else {
8740*6777b538SAndroid Build Coastguard Worker /* 1-byte code */
8741*6777b538SAndroid Build Coastguard Worker *len = 1;
8742*6777b538SAndroid Build Coastguard Worker return(*cur);
8743*6777b538SAndroid Build Coastguard Worker }
8744*6777b538SAndroid Build Coastguard Worker encoding_error:
8745*6777b538SAndroid Build Coastguard Worker /*
8746*6777b538SAndroid Build Coastguard Worker * If we detect an UTF8 error that probably means that the
8747*6777b538SAndroid Build Coastguard Worker * input encoding didn't get properly advertised in the
8748*6777b538SAndroid Build Coastguard Worker * declaration header. Report the error and switch the encoding
8749*6777b538SAndroid Build Coastguard Worker * to ISO-Latin-1 (if you don't like this policy, just declare the
8750*6777b538SAndroid Build Coastguard Worker * encoding !)
8751*6777b538SAndroid Build Coastguard Worker */
8752*6777b538SAndroid Build Coastguard Worker *len = 0;
8753*6777b538SAndroid Build Coastguard Worker XP_ERROR0(XPATH_ENCODING_ERROR);
8754*6777b538SAndroid Build Coastguard Worker }
8755*6777b538SAndroid Build Coastguard Worker
8756*6777b538SAndroid Build Coastguard Worker /**
8757*6777b538SAndroid Build Coastguard Worker * xmlXPathParseNCName:
8758*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8759*6777b538SAndroid Build Coastguard Worker *
8760*6777b538SAndroid Build Coastguard Worker * parse an XML namespace non qualified name.
8761*6777b538SAndroid Build Coastguard Worker *
8762*6777b538SAndroid Build Coastguard Worker * [NS 3] NCName ::= (Letter | '_') (NCNameChar)*
8763*6777b538SAndroid Build Coastguard Worker *
8764*6777b538SAndroid Build Coastguard Worker * [NS 4] NCNameChar ::= Letter | Digit | '.' | '-' | '_' |
8765*6777b538SAndroid Build Coastguard Worker * CombiningChar | Extender
8766*6777b538SAndroid Build Coastguard Worker *
8767*6777b538SAndroid Build Coastguard Worker * Returns the namespace name or NULL
8768*6777b538SAndroid Build Coastguard Worker */
8769*6777b538SAndroid Build Coastguard Worker
8770*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlXPathParseNCName(xmlXPathParserContextPtr ctxt)8771*6777b538SAndroid Build Coastguard Worker xmlXPathParseNCName(xmlXPathParserContextPtr ctxt) {
8772*6777b538SAndroid Build Coastguard Worker const xmlChar *in;
8773*6777b538SAndroid Build Coastguard Worker xmlChar *ret;
8774*6777b538SAndroid Build Coastguard Worker int count = 0;
8775*6777b538SAndroid Build Coastguard Worker
8776*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->cur == NULL)) return(NULL);
8777*6777b538SAndroid Build Coastguard Worker /*
8778*6777b538SAndroid Build Coastguard Worker * Accelerator for simple ASCII names
8779*6777b538SAndroid Build Coastguard Worker */
8780*6777b538SAndroid Build Coastguard Worker in = ctxt->cur;
8781*6777b538SAndroid Build Coastguard Worker if (((*in >= 0x61) && (*in <= 0x7A)) ||
8782*6777b538SAndroid Build Coastguard Worker ((*in >= 0x41) && (*in <= 0x5A)) ||
8783*6777b538SAndroid Build Coastguard Worker (*in == '_')) {
8784*6777b538SAndroid Build Coastguard Worker in++;
8785*6777b538SAndroid Build Coastguard Worker while (((*in >= 0x61) && (*in <= 0x7A)) ||
8786*6777b538SAndroid Build Coastguard Worker ((*in >= 0x41) && (*in <= 0x5A)) ||
8787*6777b538SAndroid Build Coastguard Worker ((*in >= 0x30) && (*in <= 0x39)) ||
8788*6777b538SAndroid Build Coastguard Worker (*in == '_') || (*in == '.') ||
8789*6777b538SAndroid Build Coastguard Worker (*in == '-'))
8790*6777b538SAndroid Build Coastguard Worker in++;
8791*6777b538SAndroid Build Coastguard Worker if ((*in == ' ') || (*in == '>') || (*in == '/') ||
8792*6777b538SAndroid Build Coastguard Worker (*in == '[') || (*in == ']') || (*in == ':') ||
8793*6777b538SAndroid Build Coastguard Worker (*in == '@') || (*in == '*')) {
8794*6777b538SAndroid Build Coastguard Worker count = in - ctxt->cur;
8795*6777b538SAndroid Build Coastguard Worker if (count == 0)
8796*6777b538SAndroid Build Coastguard Worker return(NULL);
8797*6777b538SAndroid Build Coastguard Worker ret = xmlStrndup(ctxt->cur, count);
8798*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
8799*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
8800*6777b538SAndroid Build Coastguard Worker ctxt->cur = in;
8801*6777b538SAndroid Build Coastguard Worker return(ret);
8802*6777b538SAndroid Build Coastguard Worker }
8803*6777b538SAndroid Build Coastguard Worker }
8804*6777b538SAndroid Build Coastguard Worker return(xmlXPathParseNameComplex(ctxt, 0));
8805*6777b538SAndroid Build Coastguard Worker }
8806*6777b538SAndroid Build Coastguard Worker
8807*6777b538SAndroid Build Coastguard Worker
8808*6777b538SAndroid Build Coastguard Worker /**
8809*6777b538SAndroid Build Coastguard Worker * xmlXPathParseQName:
8810*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8811*6777b538SAndroid Build Coastguard Worker * @prefix: a xmlChar **
8812*6777b538SAndroid Build Coastguard Worker *
8813*6777b538SAndroid Build Coastguard Worker * parse an XML qualified name
8814*6777b538SAndroid Build Coastguard Worker *
8815*6777b538SAndroid Build Coastguard Worker * [NS 5] QName ::= (Prefix ':')? LocalPart
8816*6777b538SAndroid Build Coastguard Worker *
8817*6777b538SAndroid Build Coastguard Worker * [NS 6] Prefix ::= NCName
8818*6777b538SAndroid Build Coastguard Worker *
8819*6777b538SAndroid Build Coastguard Worker * [NS 7] LocalPart ::= NCName
8820*6777b538SAndroid Build Coastguard Worker *
8821*6777b538SAndroid Build Coastguard Worker * Returns the function returns the local part, and prefix is updated
8822*6777b538SAndroid Build Coastguard Worker * to get the Prefix if any.
8823*6777b538SAndroid Build Coastguard Worker */
8824*6777b538SAndroid Build Coastguard Worker
8825*6777b538SAndroid Build Coastguard Worker static xmlChar *
xmlXPathParseQName(xmlXPathParserContextPtr ctxt,xmlChar ** prefix)8826*6777b538SAndroid Build Coastguard Worker xmlXPathParseQName(xmlXPathParserContextPtr ctxt, xmlChar **prefix) {
8827*6777b538SAndroid Build Coastguard Worker xmlChar *ret = NULL;
8828*6777b538SAndroid Build Coastguard Worker
8829*6777b538SAndroid Build Coastguard Worker *prefix = NULL;
8830*6777b538SAndroid Build Coastguard Worker ret = xmlXPathParseNCName(ctxt);
8831*6777b538SAndroid Build Coastguard Worker if (ret && CUR == ':') {
8832*6777b538SAndroid Build Coastguard Worker *prefix = ret;
8833*6777b538SAndroid Build Coastguard Worker NEXT;
8834*6777b538SAndroid Build Coastguard Worker ret = xmlXPathParseNCName(ctxt);
8835*6777b538SAndroid Build Coastguard Worker }
8836*6777b538SAndroid Build Coastguard Worker return(ret);
8837*6777b538SAndroid Build Coastguard Worker }
8838*6777b538SAndroid Build Coastguard Worker
8839*6777b538SAndroid Build Coastguard Worker /**
8840*6777b538SAndroid Build Coastguard Worker * xmlXPathParseName:
8841*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
8842*6777b538SAndroid Build Coastguard Worker *
8843*6777b538SAndroid Build Coastguard Worker * parse an XML name
8844*6777b538SAndroid Build Coastguard Worker *
8845*6777b538SAndroid Build Coastguard Worker * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
8846*6777b538SAndroid Build Coastguard Worker * CombiningChar | Extender
8847*6777b538SAndroid Build Coastguard Worker *
8848*6777b538SAndroid Build Coastguard Worker * [5] Name ::= (Letter | '_' | ':') (NameChar)*
8849*6777b538SAndroid Build Coastguard Worker *
8850*6777b538SAndroid Build Coastguard Worker * Returns the namespace name or NULL
8851*6777b538SAndroid Build Coastguard Worker */
8852*6777b538SAndroid Build Coastguard Worker
8853*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlXPathParseName(xmlXPathParserContextPtr ctxt)8854*6777b538SAndroid Build Coastguard Worker xmlXPathParseName(xmlXPathParserContextPtr ctxt) {
8855*6777b538SAndroid Build Coastguard Worker const xmlChar *in;
8856*6777b538SAndroid Build Coastguard Worker xmlChar *ret;
8857*6777b538SAndroid Build Coastguard Worker size_t count = 0;
8858*6777b538SAndroid Build Coastguard Worker
8859*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->cur == NULL)) return(NULL);
8860*6777b538SAndroid Build Coastguard Worker /*
8861*6777b538SAndroid Build Coastguard Worker * Accelerator for simple ASCII names
8862*6777b538SAndroid Build Coastguard Worker */
8863*6777b538SAndroid Build Coastguard Worker in = ctxt->cur;
8864*6777b538SAndroid Build Coastguard Worker if (((*in >= 0x61) && (*in <= 0x7A)) ||
8865*6777b538SAndroid Build Coastguard Worker ((*in >= 0x41) && (*in <= 0x5A)) ||
8866*6777b538SAndroid Build Coastguard Worker (*in == '_') || (*in == ':')) {
8867*6777b538SAndroid Build Coastguard Worker in++;
8868*6777b538SAndroid Build Coastguard Worker while (((*in >= 0x61) && (*in <= 0x7A)) ||
8869*6777b538SAndroid Build Coastguard Worker ((*in >= 0x41) && (*in <= 0x5A)) ||
8870*6777b538SAndroid Build Coastguard Worker ((*in >= 0x30) && (*in <= 0x39)) ||
8871*6777b538SAndroid Build Coastguard Worker (*in == '_') || (*in == '-') ||
8872*6777b538SAndroid Build Coastguard Worker (*in == ':') || (*in == '.'))
8873*6777b538SAndroid Build Coastguard Worker in++;
8874*6777b538SAndroid Build Coastguard Worker if ((*in > 0) && (*in < 0x80)) {
8875*6777b538SAndroid Build Coastguard Worker count = in - ctxt->cur;
8876*6777b538SAndroid Build Coastguard Worker if (count > XML_MAX_NAME_LENGTH) {
8877*6777b538SAndroid Build Coastguard Worker ctxt->cur = in;
8878*6777b538SAndroid Build Coastguard Worker XP_ERRORNULL(XPATH_EXPR_ERROR);
8879*6777b538SAndroid Build Coastguard Worker }
8880*6777b538SAndroid Build Coastguard Worker ret = xmlStrndup(ctxt->cur, count);
8881*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
8882*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
8883*6777b538SAndroid Build Coastguard Worker ctxt->cur = in;
8884*6777b538SAndroid Build Coastguard Worker return(ret);
8885*6777b538SAndroid Build Coastguard Worker }
8886*6777b538SAndroid Build Coastguard Worker }
8887*6777b538SAndroid Build Coastguard Worker return(xmlXPathParseNameComplex(ctxt, 1));
8888*6777b538SAndroid Build Coastguard Worker }
8889*6777b538SAndroid Build Coastguard Worker
8890*6777b538SAndroid Build Coastguard Worker static xmlChar *
xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt,int qualified)8891*6777b538SAndroid Build Coastguard Worker xmlXPathParseNameComplex(xmlXPathParserContextPtr ctxt, int qualified) {
8892*6777b538SAndroid Build Coastguard Worker xmlChar *ret;
8893*6777b538SAndroid Build Coastguard Worker xmlChar buf[XML_MAX_NAMELEN + 5];
8894*6777b538SAndroid Build Coastguard Worker int len = 0, l;
8895*6777b538SAndroid Build Coastguard Worker int c;
8896*6777b538SAndroid Build Coastguard Worker
8897*6777b538SAndroid Build Coastguard Worker /*
8898*6777b538SAndroid Build Coastguard Worker * Handler for more complex cases
8899*6777b538SAndroid Build Coastguard Worker */
8900*6777b538SAndroid Build Coastguard Worker c = CUR_CHAR(l);
8901*6777b538SAndroid Build Coastguard Worker if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
8902*6777b538SAndroid Build Coastguard Worker (c == '[') || (c == ']') || (c == '@') || /* accelerators */
8903*6777b538SAndroid Build Coastguard Worker (c == '*') || /* accelerators */
8904*6777b538SAndroid Build Coastguard Worker (!IS_LETTER(c) && (c != '_') &&
8905*6777b538SAndroid Build Coastguard Worker ((!qualified) || (c != ':')))) {
8906*6777b538SAndroid Build Coastguard Worker return(NULL);
8907*6777b538SAndroid Build Coastguard Worker }
8908*6777b538SAndroid Build Coastguard Worker
8909*6777b538SAndroid Build Coastguard Worker while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
8910*6777b538SAndroid Build Coastguard Worker ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
8911*6777b538SAndroid Build Coastguard Worker (c == '.') || (c == '-') ||
8912*6777b538SAndroid Build Coastguard Worker (c == '_') || ((qualified) && (c == ':')) ||
8913*6777b538SAndroid Build Coastguard Worker (IS_COMBINING(c)) ||
8914*6777b538SAndroid Build Coastguard Worker (IS_EXTENDER(c)))) {
8915*6777b538SAndroid Build Coastguard Worker COPY_BUF(l,buf,len,c);
8916*6777b538SAndroid Build Coastguard Worker NEXTL(l);
8917*6777b538SAndroid Build Coastguard Worker c = CUR_CHAR(l);
8918*6777b538SAndroid Build Coastguard Worker if (len >= XML_MAX_NAMELEN) {
8919*6777b538SAndroid Build Coastguard Worker /*
8920*6777b538SAndroid Build Coastguard Worker * Okay someone managed to make a huge name, so he's ready to pay
8921*6777b538SAndroid Build Coastguard Worker * for the processing speed.
8922*6777b538SAndroid Build Coastguard Worker */
8923*6777b538SAndroid Build Coastguard Worker xmlChar *buffer;
8924*6777b538SAndroid Build Coastguard Worker int max = len * 2;
8925*6777b538SAndroid Build Coastguard Worker
8926*6777b538SAndroid Build Coastguard Worker if (len > XML_MAX_NAME_LENGTH) {
8927*6777b538SAndroid Build Coastguard Worker XP_ERRORNULL(XPATH_EXPR_ERROR);
8928*6777b538SAndroid Build Coastguard Worker }
8929*6777b538SAndroid Build Coastguard Worker buffer = (xmlChar *) xmlMallocAtomic(max);
8930*6777b538SAndroid Build Coastguard Worker if (buffer == NULL) {
8931*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
8932*6777b538SAndroid Build Coastguard Worker return(NULL);
8933*6777b538SAndroid Build Coastguard Worker }
8934*6777b538SAndroid Build Coastguard Worker memcpy(buffer, buf, len);
8935*6777b538SAndroid Build Coastguard Worker while ((IS_LETTER(c)) || (IS_DIGIT(c)) || /* test bigname.xml */
8936*6777b538SAndroid Build Coastguard Worker (c == '.') || (c == '-') ||
8937*6777b538SAndroid Build Coastguard Worker (c == '_') || ((qualified) && (c == ':')) ||
8938*6777b538SAndroid Build Coastguard Worker (IS_COMBINING(c)) ||
8939*6777b538SAndroid Build Coastguard Worker (IS_EXTENDER(c))) {
8940*6777b538SAndroid Build Coastguard Worker if (len + 10 > max) {
8941*6777b538SAndroid Build Coastguard Worker xmlChar *tmp;
8942*6777b538SAndroid Build Coastguard Worker if (max > XML_MAX_NAME_LENGTH) {
8943*6777b538SAndroid Build Coastguard Worker xmlFree(buffer);
8944*6777b538SAndroid Build Coastguard Worker XP_ERRORNULL(XPATH_EXPR_ERROR);
8945*6777b538SAndroid Build Coastguard Worker }
8946*6777b538SAndroid Build Coastguard Worker max *= 2;
8947*6777b538SAndroid Build Coastguard Worker tmp = (xmlChar *) xmlRealloc(buffer, max);
8948*6777b538SAndroid Build Coastguard Worker if (tmp == NULL) {
8949*6777b538SAndroid Build Coastguard Worker xmlFree(buffer);
8950*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
8951*6777b538SAndroid Build Coastguard Worker return(NULL);
8952*6777b538SAndroid Build Coastguard Worker }
8953*6777b538SAndroid Build Coastguard Worker buffer = tmp;
8954*6777b538SAndroid Build Coastguard Worker }
8955*6777b538SAndroid Build Coastguard Worker COPY_BUF(l,buffer,len,c);
8956*6777b538SAndroid Build Coastguard Worker NEXTL(l);
8957*6777b538SAndroid Build Coastguard Worker c = CUR_CHAR(l);
8958*6777b538SAndroid Build Coastguard Worker }
8959*6777b538SAndroid Build Coastguard Worker buffer[len] = 0;
8960*6777b538SAndroid Build Coastguard Worker return(buffer);
8961*6777b538SAndroid Build Coastguard Worker }
8962*6777b538SAndroid Build Coastguard Worker }
8963*6777b538SAndroid Build Coastguard Worker if (len == 0)
8964*6777b538SAndroid Build Coastguard Worker return(NULL);
8965*6777b538SAndroid Build Coastguard Worker ret = xmlStrndup(buf, len);
8966*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
8967*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
8968*6777b538SAndroid Build Coastguard Worker return(ret);
8969*6777b538SAndroid Build Coastguard Worker }
8970*6777b538SAndroid Build Coastguard Worker
8971*6777b538SAndroid Build Coastguard Worker #define MAX_FRAC 20
8972*6777b538SAndroid Build Coastguard Worker
8973*6777b538SAndroid Build Coastguard Worker /**
8974*6777b538SAndroid Build Coastguard Worker * xmlXPathStringEvalNumber:
8975*6777b538SAndroid Build Coastguard Worker * @str: A string to scan
8976*6777b538SAndroid Build Coastguard Worker *
8977*6777b538SAndroid Build Coastguard Worker * [30a] Float ::= Number ('e' Digits?)?
8978*6777b538SAndroid Build Coastguard Worker *
8979*6777b538SAndroid Build Coastguard Worker * [30] Number ::= Digits ('.' Digits?)?
8980*6777b538SAndroid Build Coastguard Worker * | '.' Digits
8981*6777b538SAndroid Build Coastguard Worker * [31] Digits ::= [0-9]+
8982*6777b538SAndroid Build Coastguard Worker *
8983*6777b538SAndroid Build Coastguard Worker * Compile a Number in the string
8984*6777b538SAndroid Build Coastguard Worker * In complement of the Number expression, this function also handles
8985*6777b538SAndroid Build Coastguard Worker * negative values : '-' Number.
8986*6777b538SAndroid Build Coastguard Worker *
8987*6777b538SAndroid Build Coastguard Worker * Returns the double value.
8988*6777b538SAndroid Build Coastguard Worker */
8989*6777b538SAndroid Build Coastguard Worker double
xmlXPathStringEvalNumber(const xmlChar * str)8990*6777b538SAndroid Build Coastguard Worker xmlXPathStringEvalNumber(const xmlChar *str) {
8991*6777b538SAndroid Build Coastguard Worker const xmlChar *cur = str;
8992*6777b538SAndroid Build Coastguard Worker double ret;
8993*6777b538SAndroid Build Coastguard Worker int ok = 0;
8994*6777b538SAndroid Build Coastguard Worker int isneg = 0;
8995*6777b538SAndroid Build Coastguard Worker int exponent = 0;
8996*6777b538SAndroid Build Coastguard Worker int is_exponent_negative = 0;
8997*6777b538SAndroid Build Coastguard Worker #ifdef __GNUC__
8998*6777b538SAndroid Build Coastguard Worker unsigned long tmp = 0;
8999*6777b538SAndroid Build Coastguard Worker double temp;
9000*6777b538SAndroid Build Coastguard Worker #endif
9001*6777b538SAndroid Build Coastguard Worker if (cur == NULL) return(0);
9002*6777b538SAndroid Build Coastguard Worker while (IS_BLANK_CH(*cur)) cur++;
9003*6777b538SAndroid Build Coastguard Worker if (*cur == '-') {
9004*6777b538SAndroid Build Coastguard Worker isneg = 1;
9005*6777b538SAndroid Build Coastguard Worker cur++;
9006*6777b538SAndroid Build Coastguard Worker }
9007*6777b538SAndroid Build Coastguard Worker if ((*cur != '.') && ((*cur < '0') || (*cur > '9'))) {
9008*6777b538SAndroid Build Coastguard Worker return(xmlXPathNAN);
9009*6777b538SAndroid Build Coastguard Worker }
9010*6777b538SAndroid Build Coastguard Worker
9011*6777b538SAndroid Build Coastguard Worker #ifdef __GNUC__
9012*6777b538SAndroid Build Coastguard Worker /*
9013*6777b538SAndroid Build Coastguard Worker * tmp/temp is a workaround against a gcc compiler bug
9014*6777b538SAndroid Build Coastguard Worker * http://veillard.com/gcc.bug
9015*6777b538SAndroid Build Coastguard Worker */
9016*6777b538SAndroid Build Coastguard Worker ret = 0;
9017*6777b538SAndroid Build Coastguard Worker while ((*cur >= '0') && (*cur <= '9')) {
9018*6777b538SAndroid Build Coastguard Worker ret = ret * 10;
9019*6777b538SAndroid Build Coastguard Worker tmp = (*cur - '0');
9020*6777b538SAndroid Build Coastguard Worker ok = 1;
9021*6777b538SAndroid Build Coastguard Worker cur++;
9022*6777b538SAndroid Build Coastguard Worker temp = (double) tmp;
9023*6777b538SAndroid Build Coastguard Worker ret = ret + temp;
9024*6777b538SAndroid Build Coastguard Worker }
9025*6777b538SAndroid Build Coastguard Worker #else
9026*6777b538SAndroid Build Coastguard Worker ret = 0;
9027*6777b538SAndroid Build Coastguard Worker while ((*cur >= '0') && (*cur <= '9')) {
9028*6777b538SAndroid Build Coastguard Worker ret = ret * 10 + (*cur - '0');
9029*6777b538SAndroid Build Coastguard Worker ok = 1;
9030*6777b538SAndroid Build Coastguard Worker cur++;
9031*6777b538SAndroid Build Coastguard Worker }
9032*6777b538SAndroid Build Coastguard Worker #endif
9033*6777b538SAndroid Build Coastguard Worker
9034*6777b538SAndroid Build Coastguard Worker if (*cur == '.') {
9035*6777b538SAndroid Build Coastguard Worker int v, frac = 0, max;
9036*6777b538SAndroid Build Coastguard Worker double fraction = 0;
9037*6777b538SAndroid Build Coastguard Worker
9038*6777b538SAndroid Build Coastguard Worker cur++;
9039*6777b538SAndroid Build Coastguard Worker if (((*cur < '0') || (*cur > '9')) && (!ok)) {
9040*6777b538SAndroid Build Coastguard Worker return(xmlXPathNAN);
9041*6777b538SAndroid Build Coastguard Worker }
9042*6777b538SAndroid Build Coastguard Worker while (*cur == '0') {
9043*6777b538SAndroid Build Coastguard Worker frac = frac + 1;
9044*6777b538SAndroid Build Coastguard Worker cur++;
9045*6777b538SAndroid Build Coastguard Worker }
9046*6777b538SAndroid Build Coastguard Worker max = frac + MAX_FRAC;
9047*6777b538SAndroid Build Coastguard Worker while (((*cur >= '0') && (*cur <= '9')) && (frac < max)) {
9048*6777b538SAndroid Build Coastguard Worker v = (*cur - '0');
9049*6777b538SAndroid Build Coastguard Worker fraction = fraction * 10 + v;
9050*6777b538SAndroid Build Coastguard Worker frac = frac + 1;
9051*6777b538SAndroid Build Coastguard Worker cur++;
9052*6777b538SAndroid Build Coastguard Worker }
9053*6777b538SAndroid Build Coastguard Worker fraction /= pow(10.0, frac);
9054*6777b538SAndroid Build Coastguard Worker ret = ret + fraction;
9055*6777b538SAndroid Build Coastguard Worker while ((*cur >= '0') && (*cur <= '9'))
9056*6777b538SAndroid Build Coastguard Worker cur++;
9057*6777b538SAndroid Build Coastguard Worker }
9058*6777b538SAndroid Build Coastguard Worker if ((*cur == 'e') || (*cur == 'E')) {
9059*6777b538SAndroid Build Coastguard Worker cur++;
9060*6777b538SAndroid Build Coastguard Worker if (*cur == '-') {
9061*6777b538SAndroid Build Coastguard Worker is_exponent_negative = 1;
9062*6777b538SAndroid Build Coastguard Worker cur++;
9063*6777b538SAndroid Build Coastguard Worker } else if (*cur == '+') {
9064*6777b538SAndroid Build Coastguard Worker cur++;
9065*6777b538SAndroid Build Coastguard Worker }
9066*6777b538SAndroid Build Coastguard Worker while ((*cur >= '0') && (*cur <= '9')) {
9067*6777b538SAndroid Build Coastguard Worker if (exponent < 1000000)
9068*6777b538SAndroid Build Coastguard Worker exponent = exponent * 10 + (*cur - '0');
9069*6777b538SAndroid Build Coastguard Worker cur++;
9070*6777b538SAndroid Build Coastguard Worker }
9071*6777b538SAndroid Build Coastguard Worker }
9072*6777b538SAndroid Build Coastguard Worker while (IS_BLANK_CH(*cur)) cur++;
9073*6777b538SAndroid Build Coastguard Worker if (*cur != 0) return(xmlXPathNAN);
9074*6777b538SAndroid Build Coastguard Worker if (isneg) ret = -ret;
9075*6777b538SAndroid Build Coastguard Worker if (is_exponent_negative) exponent = -exponent;
9076*6777b538SAndroid Build Coastguard Worker ret *= pow(10.0, (double)exponent);
9077*6777b538SAndroid Build Coastguard Worker return(ret);
9078*6777b538SAndroid Build Coastguard Worker }
9079*6777b538SAndroid Build Coastguard Worker
9080*6777b538SAndroid Build Coastguard Worker /**
9081*6777b538SAndroid Build Coastguard Worker * xmlXPathCompNumber:
9082*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9083*6777b538SAndroid Build Coastguard Worker *
9084*6777b538SAndroid Build Coastguard Worker * [30] Number ::= Digits ('.' Digits?)?
9085*6777b538SAndroid Build Coastguard Worker * | '.' Digits
9086*6777b538SAndroid Build Coastguard Worker * [31] Digits ::= [0-9]+
9087*6777b538SAndroid Build Coastguard Worker *
9088*6777b538SAndroid Build Coastguard Worker * Compile a Number, then push it on the stack
9089*6777b538SAndroid Build Coastguard Worker *
9090*6777b538SAndroid Build Coastguard Worker */
9091*6777b538SAndroid Build Coastguard Worker static void
xmlXPathCompNumber(xmlXPathParserContextPtr ctxt)9092*6777b538SAndroid Build Coastguard Worker xmlXPathCompNumber(xmlXPathParserContextPtr ctxt)
9093*6777b538SAndroid Build Coastguard Worker {
9094*6777b538SAndroid Build Coastguard Worker double ret = 0.0;
9095*6777b538SAndroid Build Coastguard Worker int ok = 0;
9096*6777b538SAndroid Build Coastguard Worker int exponent = 0;
9097*6777b538SAndroid Build Coastguard Worker int is_exponent_negative = 0;
9098*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr num;
9099*6777b538SAndroid Build Coastguard Worker #ifdef __GNUC__
9100*6777b538SAndroid Build Coastguard Worker unsigned long tmp = 0;
9101*6777b538SAndroid Build Coastguard Worker double temp;
9102*6777b538SAndroid Build Coastguard Worker #endif
9103*6777b538SAndroid Build Coastguard Worker
9104*6777b538SAndroid Build Coastguard Worker CHECK_ERROR;
9105*6777b538SAndroid Build Coastguard Worker if ((CUR != '.') && ((CUR < '0') || (CUR > '9'))) {
9106*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_NUMBER_ERROR);
9107*6777b538SAndroid Build Coastguard Worker }
9108*6777b538SAndroid Build Coastguard Worker #ifdef __GNUC__
9109*6777b538SAndroid Build Coastguard Worker /*
9110*6777b538SAndroid Build Coastguard Worker * tmp/temp is a workaround against a gcc compiler bug
9111*6777b538SAndroid Build Coastguard Worker * http://veillard.com/gcc.bug
9112*6777b538SAndroid Build Coastguard Worker */
9113*6777b538SAndroid Build Coastguard Worker ret = 0;
9114*6777b538SAndroid Build Coastguard Worker while ((CUR >= '0') && (CUR <= '9')) {
9115*6777b538SAndroid Build Coastguard Worker ret = ret * 10;
9116*6777b538SAndroid Build Coastguard Worker tmp = (CUR - '0');
9117*6777b538SAndroid Build Coastguard Worker ok = 1;
9118*6777b538SAndroid Build Coastguard Worker NEXT;
9119*6777b538SAndroid Build Coastguard Worker temp = (double) tmp;
9120*6777b538SAndroid Build Coastguard Worker ret = ret + temp;
9121*6777b538SAndroid Build Coastguard Worker }
9122*6777b538SAndroid Build Coastguard Worker #else
9123*6777b538SAndroid Build Coastguard Worker ret = 0;
9124*6777b538SAndroid Build Coastguard Worker while ((CUR >= '0') && (CUR <= '9')) {
9125*6777b538SAndroid Build Coastguard Worker ret = ret * 10 + (CUR - '0');
9126*6777b538SAndroid Build Coastguard Worker ok = 1;
9127*6777b538SAndroid Build Coastguard Worker NEXT;
9128*6777b538SAndroid Build Coastguard Worker }
9129*6777b538SAndroid Build Coastguard Worker #endif
9130*6777b538SAndroid Build Coastguard Worker if (CUR == '.') {
9131*6777b538SAndroid Build Coastguard Worker int v, frac = 0, max;
9132*6777b538SAndroid Build Coastguard Worker double fraction = 0;
9133*6777b538SAndroid Build Coastguard Worker
9134*6777b538SAndroid Build Coastguard Worker NEXT;
9135*6777b538SAndroid Build Coastguard Worker if (((CUR < '0') || (CUR > '9')) && (!ok)) {
9136*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_NUMBER_ERROR);
9137*6777b538SAndroid Build Coastguard Worker }
9138*6777b538SAndroid Build Coastguard Worker while (CUR == '0') {
9139*6777b538SAndroid Build Coastguard Worker frac = frac + 1;
9140*6777b538SAndroid Build Coastguard Worker NEXT;
9141*6777b538SAndroid Build Coastguard Worker }
9142*6777b538SAndroid Build Coastguard Worker max = frac + MAX_FRAC;
9143*6777b538SAndroid Build Coastguard Worker while ((CUR >= '0') && (CUR <= '9') && (frac < max)) {
9144*6777b538SAndroid Build Coastguard Worker v = (CUR - '0');
9145*6777b538SAndroid Build Coastguard Worker fraction = fraction * 10 + v;
9146*6777b538SAndroid Build Coastguard Worker frac = frac + 1;
9147*6777b538SAndroid Build Coastguard Worker NEXT;
9148*6777b538SAndroid Build Coastguard Worker }
9149*6777b538SAndroid Build Coastguard Worker fraction /= pow(10.0, frac);
9150*6777b538SAndroid Build Coastguard Worker ret = ret + fraction;
9151*6777b538SAndroid Build Coastguard Worker while ((CUR >= '0') && (CUR <= '9'))
9152*6777b538SAndroid Build Coastguard Worker NEXT;
9153*6777b538SAndroid Build Coastguard Worker }
9154*6777b538SAndroid Build Coastguard Worker if ((CUR == 'e') || (CUR == 'E')) {
9155*6777b538SAndroid Build Coastguard Worker NEXT;
9156*6777b538SAndroid Build Coastguard Worker if (CUR == '-') {
9157*6777b538SAndroid Build Coastguard Worker is_exponent_negative = 1;
9158*6777b538SAndroid Build Coastguard Worker NEXT;
9159*6777b538SAndroid Build Coastguard Worker } else if (CUR == '+') {
9160*6777b538SAndroid Build Coastguard Worker NEXT;
9161*6777b538SAndroid Build Coastguard Worker }
9162*6777b538SAndroid Build Coastguard Worker while ((CUR >= '0') && (CUR <= '9')) {
9163*6777b538SAndroid Build Coastguard Worker if (exponent < 1000000)
9164*6777b538SAndroid Build Coastguard Worker exponent = exponent * 10 + (CUR - '0');
9165*6777b538SAndroid Build Coastguard Worker NEXT;
9166*6777b538SAndroid Build Coastguard Worker }
9167*6777b538SAndroid Build Coastguard Worker if (is_exponent_negative)
9168*6777b538SAndroid Build Coastguard Worker exponent = -exponent;
9169*6777b538SAndroid Build Coastguard Worker ret *= pow(10.0, (double) exponent);
9170*6777b538SAndroid Build Coastguard Worker }
9171*6777b538SAndroid Build Coastguard Worker num = xmlXPathCacheNewFloat(ctxt, ret);
9172*6777b538SAndroid Build Coastguard Worker if (num == NULL) {
9173*6777b538SAndroid Build Coastguard Worker ctxt->error = XPATH_MEMORY_ERROR;
9174*6777b538SAndroid Build Coastguard Worker } else if (PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_NUMBER, 0, 0, num,
9175*6777b538SAndroid Build Coastguard Worker NULL) == -1) {
9176*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, num);
9177*6777b538SAndroid Build Coastguard Worker }
9178*6777b538SAndroid Build Coastguard Worker }
9179*6777b538SAndroid Build Coastguard Worker
9180*6777b538SAndroid Build Coastguard Worker /**
9181*6777b538SAndroid Build Coastguard Worker * xmlXPathParseLiteral:
9182*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9183*6777b538SAndroid Build Coastguard Worker *
9184*6777b538SAndroid Build Coastguard Worker * Parse a Literal
9185*6777b538SAndroid Build Coastguard Worker *
9186*6777b538SAndroid Build Coastguard Worker * [29] Literal ::= '"' [^"]* '"'
9187*6777b538SAndroid Build Coastguard Worker * | "'" [^']* "'"
9188*6777b538SAndroid Build Coastguard Worker *
9189*6777b538SAndroid Build Coastguard Worker * Returns the value found or NULL in case of error
9190*6777b538SAndroid Build Coastguard Worker */
9191*6777b538SAndroid Build Coastguard Worker static xmlChar *
xmlXPathParseLiteral(xmlXPathParserContextPtr ctxt)9192*6777b538SAndroid Build Coastguard Worker xmlXPathParseLiteral(xmlXPathParserContextPtr ctxt) {
9193*6777b538SAndroid Build Coastguard Worker const xmlChar *q;
9194*6777b538SAndroid Build Coastguard Worker xmlChar *ret = NULL;
9195*6777b538SAndroid Build Coastguard Worker int quote;
9196*6777b538SAndroid Build Coastguard Worker
9197*6777b538SAndroid Build Coastguard Worker if (CUR == '"') {
9198*6777b538SAndroid Build Coastguard Worker quote = '"';
9199*6777b538SAndroid Build Coastguard Worker } else if (CUR == '\'') {
9200*6777b538SAndroid Build Coastguard Worker quote = '\'';
9201*6777b538SAndroid Build Coastguard Worker } else {
9202*6777b538SAndroid Build Coastguard Worker XP_ERRORNULL(XPATH_START_LITERAL_ERROR);
9203*6777b538SAndroid Build Coastguard Worker }
9204*6777b538SAndroid Build Coastguard Worker
9205*6777b538SAndroid Build Coastguard Worker NEXT;
9206*6777b538SAndroid Build Coastguard Worker q = CUR_PTR;
9207*6777b538SAndroid Build Coastguard Worker while (CUR != quote) {
9208*6777b538SAndroid Build Coastguard Worker int ch;
9209*6777b538SAndroid Build Coastguard Worker int len = 4;
9210*6777b538SAndroid Build Coastguard Worker
9211*6777b538SAndroid Build Coastguard Worker if (CUR == 0)
9212*6777b538SAndroid Build Coastguard Worker XP_ERRORNULL(XPATH_UNFINISHED_LITERAL_ERROR);
9213*6777b538SAndroid Build Coastguard Worker ch = xmlGetUTF8Char(CUR_PTR, &len);
9214*6777b538SAndroid Build Coastguard Worker if ((ch < 0) || (IS_CHAR(ch) == 0))
9215*6777b538SAndroid Build Coastguard Worker XP_ERRORNULL(XPATH_INVALID_CHAR_ERROR);
9216*6777b538SAndroid Build Coastguard Worker CUR_PTR += len;
9217*6777b538SAndroid Build Coastguard Worker }
9218*6777b538SAndroid Build Coastguard Worker ret = xmlStrndup(q, CUR_PTR - q);
9219*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
9220*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
9221*6777b538SAndroid Build Coastguard Worker NEXT;
9222*6777b538SAndroid Build Coastguard Worker return(ret);
9223*6777b538SAndroid Build Coastguard Worker }
9224*6777b538SAndroid Build Coastguard Worker
9225*6777b538SAndroid Build Coastguard Worker /**
9226*6777b538SAndroid Build Coastguard Worker * xmlXPathCompLiteral:
9227*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9228*6777b538SAndroid Build Coastguard Worker *
9229*6777b538SAndroid Build Coastguard Worker * Parse a Literal and push it on the stack.
9230*6777b538SAndroid Build Coastguard Worker *
9231*6777b538SAndroid Build Coastguard Worker * [29] Literal ::= '"' [^"]* '"'
9232*6777b538SAndroid Build Coastguard Worker * | "'" [^']* "'"
9233*6777b538SAndroid Build Coastguard Worker *
9234*6777b538SAndroid Build Coastguard Worker * TODO: xmlXPathCompLiteral memory allocation could be improved.
9235*6777b538SAndroid Build Coastguard Worker */
9236*6777b538SAndroid Build Coastguard Worker static void
xmlXPathCompLiteral(xmlXPathParserContextPtr ctxt)9237*6777b538SAndroid Build Coastguard Worker xmlXPathCompLiteral(xmlXPathParserContextPtr ctxt) {
9238*6777b538SAndroid Build Coastguard Worker xmlChar *ret = NULL;
9239*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr lit;
9240*6777b538SAndroid Build Coastguard Worker
9241*6777b538SAndroid Build Coastguard Worker ret = xmlXPathParseLiteral(ctxt);
9242*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
9243*6777b538SAndroid Build Coastguard Worker return;
9244*6777b538SAndroid Build Coastguard Worker lit = xmlXPathCacheNewString(ctxt, ret);
9245*6777b538SAndroid Build Coastguard Worker if (lit == NULL) {
9246*6777b538SAndroid Build Coastguard Worker ctxt->error = XPATH_MEMORY_ERROR;
9247*6777b538SAndroid Build Coastguard Worker } else if (PUSH_LONG_EXPR(XPATH_OP_VALUE, XPATH_STRING, 0, 0, lit,
9248*6777b538SAndroid Build Coastguard Worker NULL) == -1) {
9249*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, lit);
9250*6777b538SAndroid Build Coastguard Worker }
9251*6777b538SAndroid Build Coastguard Worker xmlFree(ret);
9252*6777b538SAndroid Build Coastguard Worker }
9253*6777b538SAndroid Build Coastguard Worker
9254*6777b538SAndroid Build Coastguard Worker /**
9255*6777b538SAndroid Build Coastguard Worker * xmlXPathCompVariableReference:
9256*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9257*6777b538SAndroid Build Coastguard Worker *
9258*6777b538SAndroid Build Coastguard Worker * Parse a VariableReference, evaluate it and push it on the stack.
9259*6777b538SAndroid Build Coastguard Worker *
9260*6777b538SAndroid Build Coastguard Worker * The variable bindings consist of a mapping from variable names
9261*6777b538SAndroid Build Coastguard Worker * to variable values. The value of a variable is an object, which can be
9262*6777b538SAndroid Build Coastguard Worker * of any of the types that are possible for the value of an expression,
9263*6777b538SAndroid Build Coastguard Worker * and may also be of additional types not specified here.
9264*6777b538SAndroid Build Coastguard Worker *
9265*6777b538SAndroid Build Coastguard Worker * Early evaluation is possible since:
9266*6777b538SAndroid Build Coastguard Worker * The variable bindings [...] used to evaluate a subexpression are
9267*6777b538SAndroid Build Coastguard Worker * always the same as those used to evaluate the containing expression.
9268*6777b538SAndroid Build Coastguard Worker *
9269*6777b538SAndroid Build Coastguard Worker * [36] VariableReference ::= '$' QName
9270*6777b538SAndroid Build Coastguard Worker */
9271*6777b538SAndroid Build Coastguard Worker static void
xmlXPathCompVariableReference(xmlXPathParserContextPtr ctxt)9272*6777b538SAndroid Build Coastguard Worker xmlXPathCompVariableReference(xmlXPathParserContextPtr ctxt) {
9273*6777b538SAndroid Build Coastguard Worker xmlChar *name;
9274*6777b538SAndroid Build Coastguard Worker xmlChar *prefix;
9275*6777b538SAndroid Build Coastguard Worker
9276*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9277*6777b538SAndroid Build Coastguard Worker if (CUR != '$') {
9278*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_VARIABLE_REF_ERROR);
9279*6777b538SAndroid Build Coastguard Worker }
9280*6777b538SAndroid Build Coastguard Worker NEXT;
9281*6777b538SAndroid Build Coastguard Worker name = xmlXPathParseQName(ctxt, &prefix);
9282*6777b538SAndroid Build Coastguard Worker if (name == NULL) {
9283*6777b538SAndroid Build Coastguard Worker xmlFree(prefix);
9284*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_VARIABLE_REF_ERROR);
9285*6777b538SAndroid Build Coastguard Worker }
9286*6777b538SAndroid Build Coastguard Worker ctxt->comp->last = -1;
9287*6777b538SAndroid Build Coastguard Worker if (PUSH_LONG_EXPR(XPATH_OP_VARIABLE, 0, 0, 0, name, prefix) == -1) {
9288*6777b538SAndroid Build Coastguard Worker xmlFree(prefix);
9289*6777b538SAndroid Build Coastguard Worker xmlFree(name);
9290*6777b538SAndroid Build Coastguard Worker }
9291*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9292*6777b538SAndroid Build Coastguard Worker if ((ctxt->context != NULL) && (ctxt->context->flags & XML_XPATH_NOVAR)) {
9293*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_FORBID_VARIABLE_ERROR);
9294*6777b538SAndroid Build Coastguard Worker }
9295*6777b538SAndroid Build Coastguard Worker }
9296*6777b538SAndroid Build Coastguard Worker
9297*6777b538SAndroid Build Coastguard Worker /**
9298*6777b538SAndroid Build Coastguard Worker * xmlXPathIsNodeType:
9299*6777b538SAndroid Build Coastguard Worker * @name: a name string
9300*6777b538SAndroid Build Coastguard Worker *
9301*6777b538SAndroid Build Coastguard Worker * Is the name given a NodeType one.
9302*6777b538SAndroid Build Coastguard Worker *
9303*6777b538SAndroid Build Coastguard Worker * [38] NodeType ::= 'comment'
9304*6777b538SAndroid Build Coastguard Worker * | 'text'
9305*6777b538SAndroid Build Coastguard Worker * | 'processing-instruction'
9306*6777b538SAndroid Build Coastguard Worker * | 'node'
9307*6777b538SAndroid Build Coastguard Worker *
9308*6777b538SAndroid Build Coastguard Worker * Returns 1 if true 0 otherwise
9309*6777b538SAndroid Build Coastguard Worker */
9310*6777b538SAndroid Build Coastguard Worker int
xmlXPathIsNodeType(const xmlChar * name)9311*6777b538SAndroid Build Coastguard Worker xmlXPathIsNodeType(const xmlChar *name) {
9312*6777b538SAndroid Build Coastguard Worker if (name == NULL)
9313*6777b538SAndroid Build Coastguard Worker return(0);
9314*6777b538SAndroid Build Coastguard Worker
9315*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "node"))
9316*6777b538SAndroid Build Coastguard Worker return(1);
9317*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "text"))
9318*6777b538SAndroid Build Coastguard Worker return(1);
9319*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "comment"))
9320*6777b538SAndroid Build Coastguard Worker return(1);
9321*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "processing-instruction"))
9322*6777b538SAndroid Build Coastguard Worker return(1);
9323*6777b538SAndroid Build Coastguard Worker return(0);
9324*6777b538SAndroid Build Coastguard Worker }
9325*6777b538SAndroid Build Coastguard Worker
9326*6777b538SAndroid Build Coastguard Worker /**
9327*6777b538SAndroid Build Coastguard Worker * xmlXPathCompFunctionCall:
9328*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9329*6777b538SAndroid Build Coastguard Worker *
9330*6777b538SAndroid Build Coastguard Worker * [16] FunctionCall ::= FunctionName '(' ( Argument ( ',' Argument)*)? ')'
9331*6777b538SAndroid Build Coastguard Worker * [17] Argument ::= Expr
9332*6777b538SAndroid Build Coastguard Worker *
9333*6777b538SAndroid Build Coastguard Worker * Compile a function call, the evaluation of all arguments are
9334*6777b538SAndroid Build Coastguard Worker * pushed on the stack
9335*6777b538SAndroid Build Coastguard Worker */
9336*6777b538SAndroid Build Coastguard Worker static void
xmlXPathCompFunctionCall(xmlXPathParserContextPtr ctxt)9337*6777b538SAndroid Build Coastguard Worker xmlXPathCompFunctionCall(xmlXPathParserContextPtr ctxt) {
9338*6777b538SAndroid Build Coastguard Worker xmlChar *name;
9339*6777b538SAndroid Build Coastguard Worker xmlChar *prefix;
9340*6777b538SAndroid Build Coastguard Worker int nbargs = 0;
9341*6777b538SAndroid Build Coastguard Worker int sort = 1;
9342*6777b538SAndroid Build Coastguard Worker
9343*6777b538SAndroid Build Coastguard Worker name = xmlXPathParseQName(ctxt, &prefix);
9344*6777b538SAndroid Build Coastguard Worker if (name == NULL) {
9345*6777b538SAndroid Build Coastguard Worker xmlFree(prefix);
9346*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_EXPR_ERROR);
9347*6777b538SAndroid Build Coastguard Worker }
9348*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9349*6777b538SAndroid Build Coastguard Worker
9350*6777b538SAndroid Build Coastguard Worker if (CUR != '(') {
9351*6777b538SAndroid Build Coastguard Worker xmlFree(name);
9352*6777b538SAndroid Build Coastguard Worker xmlFree(prefix);
9353*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_EXPR_ERROR);
9354*6777b538SAndroid Build Coastguard Worker }
9355*6777b538SAndroid Build Coastguard Worker NEXT;
9356*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9357*6777b538SAndroid Build Coastguard Worker
9358*6777b538SAndroid Build Coastguard Worker /*
9359*6777b538SAndroid Build Coastguard Worker * Optimization for count(): we don't need the node-set to be sorted.
9360*6777b538SAndroid Build Coastguard Worker */
9361*6777b538SAndroid Build Coastguard Worker if ((prefix == NULL) && (name[0] == 'c') &&
9362*6777b538SAndroid Build Coastguard Worker xmlStrEqual(name, BAD_CAST "count"))
9363*6777b538SAndroid Build Coastguard Worker {
9364*6777b538SAndroid Build Coastguard Worker sort = 0;
9365*6777b538SAndroid Build Coastguard Worker }
9366*6777b538SAndroid Build Coastguard Worker ctxt->comp->last = -1;
9367*6777b538SAndroid Build Coastguard Worker if (CUR != ')') {
9368*6777b538SAndroid Build Coastguard Worker while (CUR != 0) {
9369*6777b538SAndroid Build Coastguard Worker int op1 = ctxt->comp->last;
9370*6777b538SAndroid Build Coastguard Worker ctxt->comp->last = -1;
9371*6777b538SAndroid Build Coastguard Worker xmlXPathCompileExpr(ctxt, sort);
9372*6777b538SAndroid Build Coastguard Worker if (ctxt->error != XPATH_EXPRESSION_OK) {
9373*6777b538SAndroid Build Coastguard Worker xmlFree(name);
9374*6777b538SAndroid Build Coastguard Worker xmlFree(prefix);
9375*6777b538SAndroid Build Coastguard Worker return;
9376*6777b538SAndroid Build Coastguard Worker }
9377*6777b538SAndroid Build Coastguard Worker PUSH_BINARY_EXPR(XPATH_OP_ARG, op1, ctxt->comp->last, 0, 0);
9378*6777b538SAndroid Build Coastguard Worker nbargs++;
9379*6777b538SAndroid Build Coastguard Worker if (CUR == ')') break;
9380*6777b538SAndroid Build Coastguard Worker if (CUR != ',') {
9381*6777b538SAndroid Build Coastguard Worker xmlFree(name);
9382*6777b538SAndroid Build Coastguard Worker xmlFree(prefix);
9383*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_EXPR_ERROR);
9384*6777b538SAndroid Build Coastguard Worker }
9385*6777b538SAndroid Build Coastguard Worker NEXT;
9386*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9387*6777b538SAndroid Build Coastguard Worker }
9388*6777b538SAndroid Build Coastguard Worker }
9389*6777b538SAndroid Build Coastguard Worker if (PUSH_LONG_EXPR(XPATH_OP_FUNCTION, nbargs, 0, 0, name, prefix) == -1) {
9390*6777b538SAndroid Build Coastguard Worker xmlFree(prefix);
9391*6777b538SAndroid Build Coastguard Worker xmlFree(name);
9392*6777b538SAndroid Build Coastguard Worker }
9393*6777b538SAndroid Build Coastguard Worker NEXT;
9394*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9395*6777b538SAndroid Build Coastguard Worker }
9396*6777b538SAndroid Build Coastguard Worker
9397*6777b538SAndroid Build Coastguard Worker /**
9398*6777b538SAndroid Build Coastguard Worker * xmlXPathCompPrimaryExpr:
9399*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9400*6777b538SAndroid Build Coastguard Worker *
9401*6777b538SAndroid Build Coastguard Worker * [15] PrimaryExpr ::= VariableReference
9402*6777b538SAndroid Build Coastguard Worker * | '(' Expr ')'
9403*6777b538SAndroid Build Coastguard Worker * | Literal
9404*6777b538SAndroid Build Coastguard Worker * | Number
9405*6777b538SAndroid Build Coastguard Worker * | FunctionCall
9406*6777b538SAndroid Build Coastguard Worker *
9407*6777b538SAndroid Build Coastguard Worker * Compile a primary expression.
9408*6777b538SAndroid Build Coastguard Worker */
9409*6777b538SAndroid Build Coastguard Worker static void
xmlXPathCompPrimaryExpr(xmlXPathParserContextPtr ctxt)9410*6777b538SAndroid Build Coastguard Worker xmlXPathCompPrimaryExpr(xmlXPathParserContextPtr ctxt) {
9411*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9412*6777b538SAndroid Build Coastguard Worker if (CUR == '$') xmlXPathCompVariableReference(ctxt);
9413*6777b538SAndroid Build Coastguard Worker else if (CUR == '(') {
9414*6777b538SAndroid Build Coastguard Worker NEXT;
9415*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9416*6777b538SAndroid Build Coastguard Worker xmlXPathCompileExpr(ctxt, 1);
9417*6777b538SAndroid Build Coastguard Worker CHECK_ERROR;
9418*6777b538SAndroid Build Coastguard Worker if (CUR != ')') {
9419*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_EXPR_ERROR);
9420*6777b538SAndroid Build Coastguard Worker }
9421*6777b538SAndroid Build Coastguard Worker NEXT;
9422*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9423*6777b538SAndroid Build Coastguard Worker } else if (IS_ASCII_DIGIT(CUR) || (CUR == '.' && IS_ASCII_DIGIT(NXT(1)))) {
9424*6777b538SAndroid Build Coastguard Worker xmlXPathCompNumber(ctxt);
9425*6777b538SAndroid Build Coastguard Worker } else if ((CUR == '\'') || (CUR == '"')) {
9426*6777b538SAndroid Build Coastguard Worker xmlXPathCompLiteral(ctxt);
9427*6777b538SAndroid Build Coastguard Worker } else {
9428*6777b538SAndroid Build Coastguard Worker xmlXPathCompFunctionCall(ctxt);
9429*6777b538SAndroid Build Coastguard Worker }
9430*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9431*6777b538SAndroid Build Coastguard Worker }
9432*6777b538SAndroid Build Coastguard Worker
9433*6777b538SAndroid Build Coastguard Worker /**
9434*6777b538SAndroid Build Coastguard Worker * xmlXPathCompFilterExpr:
9435*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9436*6777b538SAndroid Build Coastguard Worker *
9437*6777b538SAndroid Build Coastguard Worker * [20] FilterExpr ::= PrimaryExpr
9438*6777b538SAndroid Build Coastguard Worker * | FilterExpr Predicate
9439*6777b538SAndroid Build Coastguard Worker *
9440*6777b538SAndroid Build Coastguard Worker * Compile a filter expression.
9441*6777b538SAndroid Build Coastguard Worker * Square brackets are used to filter expressions in the same way that
9442*6777b538SAndroid Build Coastguard Worker * they are used in location paths. It is an error if the expression to
9443*6777b538SAndroid Build Coastguard Worker * be filtered does not evaluate to a node-set. The context node list
9444*6777b538SAndroid Build Coastguard Worker * used for evaluating the expression in square brackets is the node-set
9445*6777b538SAndroid Build Coastguard Worker * to be filtered listed in document order.
9446*6777b538SAndroid Build Coastguard Worker */
9447*6777b538SAndroid Build Coastguard Worker
9448*6777b538SAndroid Build Coastguard Worker static void
xmlXPathCompFilterExpr(xmlXPathParserContextPtr ctxt)9449*6777b538SAndroid Build Coastguard Worker xmlXPathCompFilterExpr(xmlXPathParserContextPtr ctxt) {
9450*6777b538SAndroid Build Coastguard Worker xmlXPathCompPrimaryExpr(ctxt);
9451*6777b538SAndroid Build Coastguard Worker CHECK_ERROR;
9452*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9453*6777b538SAndroid Build Coastguard Worker
9454*6777b538SAndroid Build Coastguard Worker while (CUR == '[') {
9455*6777b538SAndroid Build Coastguard Worker xmlXPathCompPredicate(ctxt, 1);
9456*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9457*6777b538SAndroid Build Coastguard Worker }
9458*6777b538SAndroid Build Coastguard Worker
9459*6777b538SAndroid Build Coastguard Worker
9460*6777b538SAndroid Build Coastguard Worker }
9461*6777b538SAndroid Build Coastguard Worker
9462*6777b538SAndroid Build Coastguard Worker /**
9463*6777b538SAndroid Build Coastguard Worker * xmlXPathScanName:
9464*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9465*6777b538SAndroid Build Coastguard Worker *
9466*6777b538SAndroid Build Coastguard Worker * Trickery: parse an XML name but without consuming the input flow
9467*6777b538SAndroid Build Coastguard Worker * Needed to avoid insanity in the parser state.
9468*6777b538SAndroid Build Coastguard Worker *
9469*6777b538SAndroid Build Coastguard Worker * [4] NameChar ::= Letter | Digit | '.' | '-' | '_' | ':' |
9470*6777b538SAndroid Build Coastguard Worker * CombiningChar | Extender
9471*6777b538SAndroid Build Coastguard Worker *
9472*6777b538SAndroid Build Coastguard Worker * [5] Name ::= (Letter | '_' | ':') (NameChar)*
9473*6777b538SAndroid Build Coastguard Worker *
9474*6777b538SAndroid Build Coastguard Worker * [6] Names ::= Name (S Name)*
9475*6777b538SAndroid Build Coastguard Worker *
9476*6777b538SAndroid Build Coastguard Worker * Returns the Name parsed or NULL
9477*6777b538SAndroid Build Coastguard Worker */
9478*6777b538SAndroid Build Coastguard Worker
9479*6777b538SAndroid Build Coastguard Worker static xmlChar *
xmlXPathScanName(xmlXPathParserContextPtr ctxt)9480*6777b538SAndroid Build Coastguard Worker xmlXPathScanName(xmlXPathParserContextPtr ctxt) {
9481*6777b538SAndroid Build Coastguard Worker int l;
9482*6777b538SAndroid Build Coastguard Worker int c;
9483*6777b538SAndroid Build Coastguard Worker const xmlChar *cur;
9484*6777b538SAndroid Build Coastguard Worker xmlChar *ret;
9485*6777b538SAndroid Build Coastguard Worker
9486*6777b538SAndroid Build Coastguard Worker cur = ctxt->cur;
9487*6777b538SAndroid Build Coastguard Worker
9488*6777b538SAndroid Build Coastguard Worker c = CUR_CHAR(l);
9489*6777b538SAndroid Build Coastguard Worker if ((c == ' ') || (c == '>') || (c == '/') || /* accelerators */
9490*6777b538SAndroid Build Coastguard Worker (!IS_LETTER(c) && (c != '_') &&
9491*6777b538SAndroid Build Coastguard Worker (c != ':'))) {
9492*6777b538SAndroid Build Coastguard Worker return(NULL);
9493*6777b538SAndroid Build Coastguard Worker }
9494*6777b538SAndroid Build Coastguard Worker
9495*6777b538SAndroid Build Coastguard Worker while ((c != ' ') && (c != '>') && (c != '/') && /* test bigname.xml */
9496*6777b538SAndroid Build Coastguard Worker ((IS_LETTER(c)) || (IS_DIGIT(c)) ||
9497*6777b538SAndroid Build Coastguard Worker (c == '.') || (c == '-') ||
9498*6777b538SAndroid Build Coastguard Worker (c == '_') || (c == ':') ||
9499*6777b538SAndroid Build Coastguard Worker (IS_COMBINING(c)) ||
9500*6777b538SAndroid Build Coastguard Worker (IS_EXTENDER(c)))) {
9501*6777b538SAndroid Build Coastguard Worker NEXTL(l);
9502*6777b538SAndroid Build Coastguard Worker c = CUR_CHAR(l);
9503*6777b538SAndroid Build Coastguard Worker }
9504*6777b538SAndroid Build Coastguard Worker ret = xmlStrndup(cur, ctxt->cur - cur);
9505*6777b538SAndroid Build Coastguard Worker if (ret == NULL)
9506*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
9507*6777b538SAndroid Build Coastguard Worker ctxt->cur = cur;
9508*6777b538SAndroid Build Coastguard Worker return(ret);
9509*6777b538SAndroid Build Coastguard Worker }
9510*6777b538SAndroid Build Coastguard Worker
9511*6777b538SAndroid Build Coastguard Worker /**
9512*6777b538SAndroid Build Coastguard Worker * xmlXPathCompPathExpr:
9513*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9514*6777b538SAndroid Build Coastguard Worker *
9515*6777b538SAndroid Build Coastguard Worker * [19] PathExpr ::= LocationPath
9516*6777b538SAndroid Build Coastguard Worker * | FilterExpr
9517*6777b538SAndroid Build Coastguard Worker * | FilterExpr '/' RelativeLocationPath
9518*6777b538SAndroid Build Coastguard Worker * | FilterExpr '//' RelativeLocationPath
9519*6777b538SAndroid Build Coastguard Worker *
9520*6777b538SAndroid Build Coastguard Worker * Compile a path expression.
9521*6777b538SAndroid Build Coastguard Worker * The / operator and // operators combine an arbitrary expression
9522*6777b538SAndroid Build Coastguard Worker * and a relative location path. It is an error if the expression
9523*6777b538SAndroid Build Coastguard Worker * does not evaluate to a node-set.
9524*6777b538SAndroid Build Coastguard Worker * The / operator does composition in the same way as when / is
9525*6777b538SAndroid Build Coastguard Worker * used in a location path. As in location paths, // is short for
9526*6777b538SAndroid Build Coastguard Worker * /descendant-or-self::node()/.
9527*6777b538SAndroid Build Coastguard Worker */
9528*6777b538SAndroid Build Coastguard Worker
9529*6777b538SAndroid Build Coastguard Worker static void
xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt)9530*6777b538SAndroid Build Coastguard Worker xmlXPathCompPathExpr(xmlXPathParserContextPtr ctxt) {
9531*6777b538SAndroid Build Coastguard Worker int lc = 1; /* Should we branch to LocationPath ? */
9532*6777b538SAndroid Build Coastguard Worker xmlChar *name = NULL; /* we may have to preparse a name to find out */
9533*6777b538SAndroid Build Coastguard Worker
9534*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9535*6777b538SAndroid Build Coastguard Worker if ((CUR == '$') || (CUR == '(') ||
9536*6777b538SAndroid Build Coastguard Worker (IS_ASCII_DIGIT(CUR)) ||
9537*6777b538SAndroid Build Coastguard Worker (CUR == '\'') || (CUR == '"') ||
9538*6777b538SAndroid Build Coastguard Worker (CUR == '.' && IS_ASCII_DIGIT(NXT(1)))) {
9539*6777b538SAndroid Build Coastguard Worker lc = 0;
9540*6777b538SAndroid Build Coastguard Worker } else if (CUR == '*') {
9541*6777b538SAndroid Build Coastguard Worker /* relative or absolute location path */
9542*6777b538SAndroid Build Coastguard Worker lc = 1;
9543*6777b538SAndroid Build Coastguard Worker } else if (CUR == '/') {
9544*6777b538SAndroid Build Coastguard Worker /* relative or absolute location path */
9545*6777b538SAndroid Build Coastguard Worker lc = 1;
9546*6777b538SAndroid Build Coastguard Worker } else if (CUR == '@') {
9547*6777b538SAndroid Build Coastguard Worker /* relative abbreviated attribute location path */
9548*6777b538SAndroid Build Coastguard Worker lc = 1;
9549*6777b538SAndroid Build Coastguard Worker } else if (CUR == '.') {
9550*6777b538SAndroid Build Coastguard Worker /* relative abbreviated attribute location path */
9551*6777b538SAndroid Build Coastguard Worker lc = 1;
9552*6777b538SAndroid Build Coastguard Worker } else {
9553*6777b538SAndroid Build Coastguard Worker /*
9554*6777b538SAndroid Build Coastguard Worker * Problem is finding if we have a name here whether it's:
9555*6777b538SAndroid Build Coastguard Worker * - a nodetype
9556*6777b538SAndroid Build Coastguard Worker * - a function call in which case it's followed by '('
9557*6777b538SAndroid Build Coastguard Worker * - an axis in which case it's followed by ':'
9558*6777b538SAndroid Build Coastguard Worker * - a element name
9559*6777b538SAndroid Build Coastguard Worker * We do an a priori analysis here rather than having to
9560*6777b538SAndroid Build Coastguard Worker * maintain parsed token content through the recursive function
9561*6777b538SAndroid Build Coastguard Worker * calls. This looks uglier but makes the code easier to
9562*6777b538SAndroid Build Coastguard Worker * read/write/debug.
9563*6777b538SAndroid Build Coastguard Worker */
9564*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9565*6777b538SAndroid Build Coastguard Worker name = xmlXPathScanName(ctxt);
9566*6777b538SAndroid Build Coastguard Worker if ((name != NULL) && (xmlStrstr(name, (xmlChar *) "::") != NULL)) {
9567*6777b538SAndroid Build Coastguard Worker lc = 1;
9568*6777b538SAndroid Build Coastguard Worker xmlFree(name);
9569*6777b538SAndroid Build Coastguard Worker } else if (name != NULL) {
9570*6777b538SAndroid Build Coastguard Worker int len =xmlStrlen(name);
9571*6777b538SAndroid Build Coastguard Worker
9572*6777b538SAndroid Build Coastguard Worker
9573*6777b538SAndroid Build Coastguard Worker while (NXT(len) != 0) {
9574*6777b538SAndroid Build Coastguard Worker if (NXT(len) == '/') {
9575*6777b538SAndroid Build Coastguard Worker /* element name */
9576*6777b538SAndroid Build Coastguard Worker lc = 1;
9577*6777b538SAndroid Build Coastguard Worker break;
9578*6777b538SAndroid Build Coastguard Worker } else if (IS_BLANK_CH(NXT(len))) {
9579*6777b538SAndroid Build Coastguard Worker /* ignore blanks */
9580*6777b538SAndroid Build Coastguard Worker ;
9581*6777b538SAndroid Build Coastguard Worker } else if (NXT(len) == ':') {
9582*6777b538SAndroid Build Coastguard Worker lc = 1;
9583*6777b538SAndroid Build Coastguard Worker break;
9584*6777b538SAndroid Build Coastguard Worker } else if ((NXT(len) == '(')) {
9585*6777b538SAndroid Build Coastguard Worker /* Node Type or Function */
9586*6777b538SAndroid Build Coastguard Worker if (xmlXPathIsNodeType(name)) {
9587*6777b538SAndroid Build Coastguard Worker lc = 1;
9588*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
9589*6777b538SAndroid Build Coastguard Worker } else if (ctxt->xptr &&
9590*6777b538SAndroid Build Coastguard Worker xmlStrEqual(name, BAD_CAST "range-to")) {
9591*6777b538SAndroid Build Coastguard Worker lc = 1;
9592*6777b538SAndroid Build Coastguard Worker #endif
9593*6777b538SAndroid Build Coastguard Worker } else {
9594*6777b538SAndroid Build Coastguard Worker lc = 0;
9595*6777b538SAndroid Build Coastguard Worker }
9596*6777b538SAndroid Build Coastguard Worker break;
9597*6777b538SAndroid Build Coastguard Worker } else if ((NXT(len) == '[')) {
9598*6777b538SAndroid Build Coastguard Worker /* element name */
9599*6777b538SAndroid Build Coastguard Worker lc = 1;
9600*6777b538SAndroid Build Coastguard Worker break;
9601*6777b538SAndroid Build Coastguard Worker } else if ((NXT(len) == '<') || (NXT(len) == '>') ||
9602*6777b538SAndroid Build Coastguard Worker (NXT(len) == '=')) {
9603*6777b538SAndroid Build Coastguard Worker lc = 1;
9604*6777b538SAndroid Build Coastguard Worker break;
9605*6777b538SAndroid Build Coastguard Worker } else {
9606*6777b538SAndroid Build Coastguard Worker lc = 1;
9607*6777b538SAndroid Build Coastguard Worker break;
9608*6777b538SAndroid Build Coastguard Worker }
9609*6777b538SAndroid Build Coastguard Worker len++;
9610*6777b538SAndroid Build Coastguard Worker }
9611*6777b538SAndroid Build Coastguard Worker if (NXT(len) == 0) {
9612*6777b538SAndroid Build Coastguard Worker /* element name */
9613*6777b538SAndroid Build Coastguard Worker lc = 1;
9614*6777b538SAndroid Build Coastguard Worker }
9615*6777b538SAndroid Build Coastguard Worker xmlFree(name);
9616*6777b538SAndroid Build Coastguard Worker } else {
9617*6777b538SAndroid Build Coastguard Worker /* make sure all cases are covered explicitly */
9618*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_EXPR_ERROR);
9619*6777b538SAndroid Build Coastguard Worker }
9620*6777b538SAndroid Build Coastguard Worker }
9621*6777b538SAndroid Build Coastguard Worker
9622*6777b538SAndroid Build Coastguard Worker if (lc) {
9623*6777b538SAndroid Build Coastguard Worker if (CUR == '/') {
9624*6777b538SAndroid Build Coastguard Worker PUSH_LEAVE_EXPR(XPATH_OP_ROOT, 0, 0);
9625*6777b538SAndroid Build Coastguard Worker } else {
9626*6777b538SAndroid Build Coastguard Worker PUSH_LEAVE_EXPR(XPATH_OP_NODE, 0, 0);
9627*6777b538SAndroid Build Coastguard Worker }
9628*6777b538SAndroid Build Coastguard Worker xmlXPathCompLocationPath(ctxt);
9629*6777b538SAndroid Build Coastguard Worker } else {
9630*6777b538SAndroid Build Coastguard Worker xmlXPathCompFilterExpr(ctxt);
9631*6777b538SAndroid Build Coastguard Worker CHECK_ERROR;
9632*6777b538SAndroid Build Coastguard Worker if ((CUR == '/') && (NXT(1) == '/')) {
9633*6777b538SAndroid Build Coastguard Worker SKIP(2);
9634*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9635*6777b538SAndroid Build Coastguard Worker
9636*6777b538SAndroid Build Coastguard Worker PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
9637*6777b538SAndroid Build Coastguard Worker NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
9638*6777b538SAndroid Build Coastguard Worker
9639*6777b538SAndroid Build Coastguard Worker xmlXPathCompRelativeLocationPath(ctxt);
9640*6777b538SAndroid Build Coastguard Worker } else if (CUR == '/') {
9641*6777b538SAndroid Build Coastguard Worker xmlXPathCompRelativeLocationPath(ctxt);
9642*6777b538SAndroid Build Coastguard Worker }
9643*6777b538SAndroid Build Coastguard Worker }
9644*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9645*6777b538SAndroid Build Coastguard Worker }
9646*6777b538SAndroid Build Coastguard Worker
9647*6777b538SAndroid Build Coastguard Worker /**
9648*6777b538SAndroid Build Coastguard Worker * xmlXPathCompUnionExpr:
9649*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9650*6777b538SAndroid Build Coastguard Worker *
9651*6777b538SAndroid Build Coastguard Worker * [18] UnionExpr ::= PathExpr
9652*6777b538SAndroid Build Coastguard Worker * | UnionExpr '|' PathExpr
9653*6777b538SAndroid Build Coastguard Worker *
9654*6777b538SAndroid Build Coastguard Worker * Compile an union expression.
9655*6777b538SAndroid Build Coastguard Worker */
9656*6777b538SAndroid Build Coastguard Worker
9657*6777b538SAndroid Build Coastguard Worker static void
xmlXPathCompUnionExpr(xmlXPathParserContextPtr ctxt)9658*6777b538SAndroid Build Coastguard Worker xmlXPathCompUnionExpr(xmlXPathParserContextPtr ctxt) {
9659*6777b538SAndroid Build Coastguard Worker xmlXPathCompPathExpr(ctxt);
9660*6777b538SAndroid Build Coastguard Worker CHECK_ERROR;
9661*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9662*6777b538SAndroid Build Coastguard Worker while (CUR == '|') {
9663*6777b538SAndroid Build Coastguard Worker int op1 = ctxt->comp->last;
9664*6777b538SAndroid Build Coastguard Worker PUSH_LEAVE_EXPR(XPATH_OP_NODE, 0, 0);
9665*6777b538SAndroid Build Coastguard Worker
9666*6777b538SAndroid Build Coastguard Worker NEXT;
9667*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9668*6777b538SAndroid Build Coastguard Worker xmlXPathCompPathExpr(ctxt);
9669*6777b538SAndroid Build Coastguard Worker
9670*6777b538SAndroid Build Coastguard Worker PUSH_BINARY_EXPR(XPATH_OP_UNION, op1, ctxt->comp->last, 0, 0);
9671*6777b538SAndroid Build Coastguard Worker
9672*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9673*6777b538SAndroid Build Coastguard Worker }
9674*6777b538SAndroid Build Coastguard Worker }
9675*6777b538SAndroid Build Coastguard Worker
9676*6777b538SAndroid Build Coastguard Worker /**
9677*6777b538SAndroid Build Coastguard Worker * xmlXPathCompUnaryExpr:
9678*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9679*6777b538SAndroid Build Coastguard Worker *
9680*6777b538SAndroid Build Coastguard Worker * [27] UnaryExpr ::= UnionExpr
9681*6777b538SAndroid Build Coastguard Worker * | '-' UnaryExpr
9682*6777b538SAndroid Build Coastguard Worker *
9683*6777b538SAndroid Build Coastguard Worker * Compile an unary expression.
9684*6777b538SAndroid Build Coastguard Worker */
9685*6777b538SAndroid Build Coastguard Worker
9686*6777b538SAndroid Build Coastguard Worker static void
xmlXPathCompUnaryExpr(xmlXPathParserContextPtr ctxt)9687*6777b538SAndroid Build Coastguard Worker xmlXPathCompUnaryExpr(xmlXPathParserContextPtr ctxt) {
9688*6777b538SAndroid Build Coastguard Worker int minus = 0;
9689*6777b538SAndroid Build Coastguard Worker int found = 0;
9690*6777b538SAndroid Build Coastguard Worker
9691*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9692*6777b538SAndroid Build Coastguard Worker while (CUR == '-') {
9693*6777b538SAndroid Build Coastguard Worker minus = 1 - minus;
9694*6777b538SAndroid Build Coastguard Worker found = 1;
9695*6777b538SAndroid Build Coastguard Worker NEXT;
9696*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9697*6777b538SAndroid Build Coastguard Worker }
9698*6777b538SAndroid Build Coastguard Worker
9699*6777b538SAndroid Build Coastguard Worker xmlXPathCompUnionExpr(ctxt);
9700*6777b538SAndroid Build Coastguard Worker CHECK_ERROR;
9701*6777b538SAndroid Build Coastguard Worker if (found) {
9702*6777b538SAndroid Build Coastguard Worker if (minus)
9703*6777b538SAndroid Build Coastguard Worker PUSH_UNARY_EXPR(XPATH_OP_PLUS, ctxt->comp->last, 2, 0);
9704*6777b538SAndroid Build Coastguard Worker else
9705*6777b538SAndroid Build Coastguard Worker PUSH_UNARY_EXPR(XPATH_OP_PLUS, ctxt->comp->last, 3, 0);
9706*6777b538SAndroid Build Coastguard Worker }
9707*6777b538SAndroid Build Coastguard Worker }
9708*6777b538SAndroid Build Coastguard Worker
9709*6777b538SAndroid Build Coastguard Worker /**
9710*6777b538SAndroid Build Coastguard Worker * xmlXPathCompMultiplicativeExpr:
9711*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9712*6777b538SAndroid Build Coastguard Worker *
9713*6777b538SAndroid Build Coastguard Worker * [26] MultiplicativeExpr ::= UnaryExpr
9714*6777b538SAndroid Build Coastguard Worker * | MultiplicativeExpr MultiplyOperator UnaryExpr
9715*6777b538SAndroid Build Coastguard Worker * | MultiplicativeExpr 'div' UnaryExpr
9716*6777b538SAndroid Build Coastguard Worker * | MultiplicativeExpr 'mod' UnaryExpr
9717*6777b538SAndroid Build Coastguard Worker * [34] MultiplyOperator ::= '*'
9718*6777b538SAndroid Build Coastguard Worker *
9719*6777b538SAndroid Build Coastguard Worker * Compile an Additive expression.
9720*6777b538SAndroid Build Coastguard Worker */
9721*6777b538SAndroid Build Coastguard Worker
9722*6777b538SAndroid Build Coastguard Worker static void
xmlXPathCompMultiplicativeExpr(xmlXPathParserContextPtr ctxt)9723*6777b538SAndroid Build Coastguard Worker xmlXPathCompMultiplicativeExpr(xmlXPathParserContextPtr ctxt) {
9724*6777b538SAndroid Build Coastguard Worker xmlXPathCompUnaryExpr(ctxt);
9725*6777b538SAndroid Build Coastguard Worker CHECK_ERROR;
9726*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9727*6777b538SAndroid Build Coastguard Worker while ((CUR == '*') ||
9728*6777b538SAndroid Build Coastguard Worker ((CUR == 'd') && (NXT(1) == 'i') && (NXT(2) == 'v')) ||
9729*6777b538SAndroid Build Coastguard Worker ((CUR == 'm') && (NXT(1) == 'o') && (NXT(2) == 'd'))) {
9730*6777b538SAndroid Build Coastguard Worker int op = -1;
9731*6777b538SAndroid Build Coastguard Worker int op1 = ctxt->comp->last;
9732*6777b538SAndroid Build Coastguard Worker
9733*6777b538SAndroid Build Coastguard Worker if (CUR == '*') {
9734*6777b538SAndroid Build Coastguard Worker op = 0;
9735*6777b538SAndroid Build Coastguard Worker NEXT;
9736*6777b538SAndroid Build Coastguard Worker } else if (CUR == 'd') {
9737*6777b538SAndroid Build Coastguard Worker op = 1;
9738*6777b538SAndroid Build Coastguard Worker SKIP(3);
9739*6777b538SAndroid Build Coastguard Worker } else if (CUR == 'm') {
9740*6777b538SAndroid Build Coastguard Worker op = 2;
9741*6777b538SAndroid Build Coastguard Worker SKIP(3);
9742*6777b538SAndroid Build Coastguard Worker }
9743*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9744*6777b538SAndroid Build Coastguard Worker xmlXPathCompUnaryExpr(ctxt);
9745*6777b538SAndroid Build Coastguard Worker CHECK_ERROR;
9746*6777b538SAndroid Build Coastguard Worker PUSH_BINARY_EXPR(XPATH_OP_MULT, op1, ctxt->comp->last, op, 0);
9747*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9748*6777b538SAndroid Build Coastguard Worker }
9749*6777b538SAndroid Build Coastguard Worker }
9750*6777b538SAndroid Build Coastguard Worker
9751*6777b538SAndroid Build Coastguard Worker /**
9752*6777b538SAndroid Build Coastguard Worker * xmlXPathCompAdditiveExpr:
9753*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9754*6777b538SAndroid Build Coastguard Worker *
9755*6777b538SAndroid Build Coastguard Worker * [25] AdditiveExpr ::= MultiplicativeExpr
9756*6777b538SAndroid Build Coastguard Worker * | AdditiveExpr '+' MultiplicativeExpr
9757*6777b538SAndroid Build Coastguard Worker * | AdditiveExpr '-' MultiplicativeExpr
9758*6777b538SAndroid Build Coastguard Worker *
9759*6777b538SAndroid Build Coastguard Worker * Compile an Additive expression.
9760*6777b538SAndroid Build Coastguard Worker */
9761*6777b538SAndroid Build Coastguard Worker
9762*6777b538SAndroid Build Coastguard Worker static void
xmlXPathCompAdditiveExpr(xmlXPathParserContextPtr ctxt)9763*6777b538SAndroid Build Coastguard Worker xmlXPathCompAdditiveExpr(xmlXPathParserContextPtr ctxt) {
9764*6777b538SAndroid Build Coastguard Worker
9765*6777b538SAndroid Build Coastguard Worker xmlXPathCompMultiplicativeExpr(ctxt);
9766*6777b538SAndroid Build Coastguard Worker CHECK_ERROR;
9767*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9768*6777b538SAndroid Build Coastguard Worker while ((CUR == '+') || (CUR == '-')) {
9769*6777b538SAndroid Build Coastguard Worker int plus;
9770*6777b538SAndroid Build Coastguard Worker int op1 = ctxt->comp->last;
9771*6777b538SAndroid Build Coastguard Worker
9772*6777b538SAndroid Build Coastguard Worker if (CUR == '+') plus = 1;
9773*6777b538SAndroid Build Coastguard Worker else plus = 0;
9774*6777b538SAndroid Build Coastguard Worker NEXT;
9775*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9776*6777b538SAndroid Build Coastguard Worker xmlXPathCompMultiplicativeExpr(ctxt);
9777*6777b538SAndroid Build Coastguard Worker CHECK_ERROR;
9778*6777b538SAndroid Build Coastguard Worker PUSH_BINARY_EXPR(XPATH_OP_PLUS, op1, ctxt->comp->last, plus, 0);
9779*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9780*6777b538SAndroid Build Coastguard Worker }
9781*6777b538SAndroid Build Coastguard Worker }
9782*6777b538SAndroid Build Coastguard Worker
9783*6777b538SAndroid Build Coastguard Worker /**
9784*6777b538SAndroid Build Coastguard Worker * xmlXPathCompRelationalExpr:
9785*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9786*6777b538SAndroid Build Coastguard Worker *
9787*6777b538SAndroid Build Coastguard Worker * [24] RelationalExpr ::= AdditiveExpr
9788*6777b538SAndroid Build Coastguard Worker * | RelationalExpr '<' AdditiveExpr
9789*6777b538SAndroid Build Coastguard Worker * | RelationalExpr '>' AdditiveExpr
9790*6777b538SAndroid Build Coastguard Worker * | RelationalExpr '<=' AdditiveExpr
9791*6777b538SAndroid Build Coastguard Worker * | RelationalExpr '>=' AdditiveExpr
9792*6777b538SAndroid Build Coastguard Worker *
9793*6777b538SAndroid Build Coastguard Worker * A <= B > C is allowed ? Answer from James, yes with
9794*6777b538SAndroid Build Coastguard Worker * (AdditiveExpr <= AdditiveExpr) > AdditiveExpr
9795*6777b538SAndroid Build Coastguard Worker * which is basically what got implemented.
9796*6777b538SAndroid Build Coastguard Worker *
9797*6777b538SAndroid Build Coastguard Worker * Compile a Relational expression, then push the result
9798*6777b538SAndroid Build Coastguard Worker * on the stack
9799*6777b538SAndroid Build Coastguard Worker */
9800*6777b538SAndroid Build Coastguard Worker
9801*6777b538SAndroid Build Coastguard Worker static void
xmlXPathCompRelationalExpr(xmlXPathParserContextPtr ctxt)9802*6777b538SAndroid Build Coastguard Worker xmlXPathCompRelationalExpr(xmlXPathParserContextPtr ctxt) {
9803*6777b538SAndroid Build Coastguard Worker xmlXPathCompAdditiveExpr(ctxt);
9804*6777b538SAndroid Build Coastguard Worker CHECK_ERROR;
9805*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9806*6777b538SAndroid Build Coastguard Worker while ((CUR == '<') || (CUR == '>')) {
9807*6777b538SAndroid Build Coastguard Worker int inf, strict;
9808*6777b538SAndroid Build Coastguard Worker int op1 = ctxt->comp->last;
9809*6777b538SAndroid Build Coastguard Worker
9810*6777b538SAndroid Build Coastguard Worker if (CUR == '<') inf = 1;
9811*6777b538SAndroid Build Coastguard Worker else inf = 0;
9812*6777b538SAndroid Build Coastguard Worker if (NXT(1) == '=') strict = 0;
9813*6777b538SAndroid Build Coastguard Worker else strict = 1;
9814*6777b538SAndroid Build Coastguard Worker NEXT;
9815*6777b538SAndroid Build Coastguard Worker if (!strict) NEXT;
9816*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9817*6777b538SAndroid Build Coastguard Worker xmlXPathCompAdditiveExpr(ctxt);
9818*6777b538SAndroid Build Coastguard Worker CHECK_ERROR;
9819*6777b538SAndroid Build Coastguard Worker PUSH_BINARY_EXPR(XPATH_OP_CMP, op1, ctxt->comp->last, inf, strict);
9820*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9821*6777b538SAndroid Build Coastguard Worker }
9822*6777b538SAndroid Build Coastguard Worker }
9823*6777b538SAndroid Build Coastguard Worker
9824*6777b538SAndroid Build Coastguard Worker /**
9825*6777b538SAndroid Build Coastguard Worker * xmlXPathCompEqualityExpr:
9826*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9827*6777b538SAndroid Build Coastguard Worker *
9828*6777b538SAndroid Build Coastguard Worker * [23] EqualityExpr ::= RelationalExpr
9829*6777b538SAndroid Build Coastguard Worker * | EqualityExpr '=' RelationalExpr
9830*6777b538SAndroid Build Coastguard Worker * | EqualityExpr '!=' RelationalExpr
9831*6777b538SAndroid Build Coastguard Worker *
9832*6777b538SAndroid Build Coastguard Worker * A != B != C is allowed ? Answer from James, yes with
9833*6777b538SAndroid Build Coastguard Worker * (RelationalExpr = RelationalExpr) = RelationalExpr
9834*6777b538SAndroid Build Coastguard Worker * (RelationalExpr != RelationalExpr) != RelationalExpr
9835*6777b538SAndroid Build Coastguard Worker * which is basically what got implemented.
9836*6777b538SAndroid Build Coastguard Worker *
9837*6777b538SAndroid Build Coastguard Worker * Compile an Equality expression.
9838*6777b538SAndroid Build Coastguard Worker *
9839*6777b538SAndroid Build Coastguard Worker */
9840*6777b538SAndroid Build Coastguard Worker static void
xmlXPathCompEqualityExpr(xmlXPathParserContextPtr ctxt)9841*6777b538SAndroid Build Coastguard Worker xmlXPathCompEqualityExpr(xmlXPathParserContextPtr ctxt) {
9842*6777b538SAndroid Build Coastguard Worker xmlXPathCompRelationalExpr(ctxt);
9843*6777b538SAndroid Build Coastguard Worker CHECK_ERROR;
9844*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9845*6777b538SAndroid Build Coastguard Worker while ((CUR == '=') || ((CUR == '!') && (NXT(1) == '='))) {
9846*6777b538SAndroid Build Coastguard Worker int eq;
9847*6777b538SAndroid Build Coastguard Worker int op1 = ctxt->comp->last;
9848*6777b538SAndroid Build Coastguard Worker
9849*6777b538SAndroid Build Coastguard Worker if (CUR == '=') eq = 1;
9850*6777b538SAndroid Build Coastguard Worker else eq = 0;
9851*6777b538SAndroid Build Coastguard Worker NEXT;
9852*6777b538SAndroid Build Coastguard Worker if (!eq) NEXT;
9853*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9854*6777b538SAndroid Build Coastguard Worker xmlXPathCompRelationalExpr(ctxt);
9855*6777b538SAndroid Build Coastguard Worker CHECK_ERROR;
9856*6777b538SAndroid Build Coastguard Worker PUSH_BINARY_EXPR(XPATH_OP_EQUAL, op1, ctxt->comp->last, eq, 0);
9857*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9858*6777b538SAndroid Build Coastguard Worker }
9859*6777b538SAndroid Build Coastguard Worker }
9860*6777b538SAndroid Build Coastguard Worker
9861*6777b538SAndroid Build Coastguard Worker /**
9862*6777b538SAndroid Build Coastguard Worker * xmlXPathCompAndExpr:
9863*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9864*6777b538SAndroid Build Coastguard Worker *
9865*6777b538SAndroid Build Coastguard Worker * [22] AndExpr ::= EqualityExpr
9866*6777b538SAndroid Build Coastguard Worker * | AndExpr 'and' EqualityExpr
9867*6777b538SAndroid Build Coastguard Worker *
9868*6777b538SAndroid Build Coastguard Worker * Compile an AND expression.
9869*6777b538SAndroid Build Coastguard Worker *
9870*6777b538SAndroid Build Coastguard Worker */
9871*6777b538SAndroid Build Coastguard Worker static void
xmlXPathCompAndExpr(xmlXPathParserContextPtr ctxt)9872*6777b538SAndroid Build Coastguard Worker xmlXPathCompAndExpr(xmlXPathParserContextPtr ctxt) {
9873*6777b538SAndroid Build Coastguard Worker xmlXPathCompEqualityExpr(ctxt);
9874*6777b538SAndroid Build Coastguard Worker CHECK_ERROR;
9875*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9876*6777b538SAndroid Build Coastguard Worker while ((CUR == 'a') && (NXT(1) == 'n') && (NXT(2) == 'd')) {
9877*6777b538SAndroid Build Coastguard Worker int op1 = ctxt->comp->last;
9878*6777b538SAndroid Build Coastguard Worker SKIP(3);
9879*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9880*6777b538SAndroid Build Coastguard Worker xmlXPathCompEqualityExpr(ctxt);
9881*6777b538SAndroid Build Coastguard Worker CHECK_ERROR;
9882*6777b538SAndroid Build Coastguard Worker PUSH_BINARY_EXPR(XPATH_OP_AND, op1, ctxt->comp->last, 0, 0);
9883*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9884*6777b538SAndroid Build Coastguard Worker }
9885*6777b538SAndroid Build Coastguard Worker }
9886*6777b538SAndroid Build Coastguard Worker
9887*6777b538SAndroid Build Coastguard Worker /**
9888*6777b538SAndroid Build Coastguard Worker * xmlXPathCompileExpr:
9889*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9890*6777b538SAndroid Build Coastguard Worker *
9891*6777b538SAndroid Build Coastguard Worker * [14] Expr ::= OrExpr
9892*6777b538SAndroid Build Coastguard Worker * [21] OrExpr ::= AndExpr
9893*6777b538SAndroid Build Coastguard Worker * | OrExpr 'or' AndExpr
9894*6777b538SAndroid Build Coastguard Worker *
9895*6777b538SAndroid Build Coastguard Worker * Parse and compile an expression
9896*6777b538SAndroid Build Coastguard Worker */
9897*6777b538SAndroid Build Coastguard Worker static void
xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt,int sort)9898*6777b538SAndroid Build Coastguard Worker xmlXPathCompileExpr(xmlXPathParserContextPtr ctxt, int sort) {
9899*6777b538SAndroid Build Coastguard Worker xmlXPathContextPtr xpctxt = ctxt->context;
9900*6777b538SAndroid Build Coastguard Worker
9901*6777b538SAndroid Build Coastguard Worker if (xpctxt != NULL) {
9902*6777b538SAndroid Build Coastguard Worker if (xpctxt->depth >= XPATH_MAX_RECURSION_DEPTH)
9903*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_RECURSION_LIMIT_EXCEEDED);
9904*6777b538SAndroid Build Coastguard Worker /*
9905*6777b538SAndroid Build Coastguard Worker * Parsing a single '(' pushes about 10 functions on the call stack
9906*6777b538SAndroid Build Coastguard Worker * before recursing!
9907*6777b538SAndroid Build Coastguard Worker */
9908*6777b538SAndroid Build Coastguard Worker xpctxt->depth += 10;
9909*6777b538SAndroid Build Coastguard Worker }
9910*6777b538SAndroid Build Coastguard Worker
9911*6777b538SAndroid Build Coastguard Worker xmlXPathCompAndExpr(ctxt);
9912*6777b538SAndroid Build Coastguard Worker CHECK_ERROR;
9913*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9914*6777b538SAndroid Build Coastguard Worker while ((CUR == 'o') && (NXT(1) == 'r')) {
9915*6777b538SAndroid Build Coastguard Worker int op1 = ctxt->comp->last;
9916*6777b538SAndroid Build Coastguard Worker SKIP(2);
9917*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9918*6777b538SAndroid Build Coastguard Worker xmlXPathCompAndExpr(ctxt);
9919*6777b538SAndroid Build Coastguard Worker CHECK_ERROR;
9920*6777b538SAndroid Build Coastguard Worker PUSH_BINARY_EXPR(XPATH_OP_OR, op1, ctxt->comp->last, 0, 0);
9921*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9922*6777b538SAndroid Build Coastguard Worker }
9923*6777b538SAndroid Build Coastguard Worker if ((sort) && (ctxt->comp->steps[ctxt->comp->last].op != XPATH_OP_VALUE)) {
9924*6777b538SAndroid Build Coastguard Worker /* more ops could be optimized too */
9925*6777b538SAndroid Build Coastguard Worker /*
9926*6777b538SAndroid Build Coastguard Worker * This is the main place to eliminate sorting for
9927*6777b538SAndroid Build Coastguard Worker * operations which don't require a sorted node-set.
9928*6777b538SAndroid Build Coastguard Worker * E.g. count().
9929*6777b538SAndroid Build Coastguard Worker */
9930*6777b538SAndroid Build Coastguard Worker PUSH_UNARY_EXPR(XPATH_OP_SORT, ctxt->comp->last , 0, 0);
9931*6777b538SAndroid Build Coastguard Worker }
9932*6777b538SAndroid Build Coastguard Worker
9933*6777b538SAndroid Build Coastguard Worker if (xpctxt != NULL)
9934*6777b538SAndroid Build Coastguard Worker xpctxt->depth -= 10;
9935*6777b538SAndroid Build Coastguard Worker }
9936*6777b538SAndroid Build Coastguard Worker
9937*6777b538SAndroid Build Coastguard Worker /**
9938*6777b538SAndroid Build Coastguard Worker * xmlXPathCompPredicate:
9939*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9940*6777b538SAndroid Build Coastguard Worker * @filter: act as a filter
9941*6777b538SAndroid Build Coastguard Worker *
9942*6777b538SAndroid Build Coastguard Worker * [8] Predicate ::= '[' PredicateExpr ']'
9943*6777b538SAndroid Build Coastguard Worker * [9] PredicateExpr ::= Expr
9944*6777b538SAndroid Build Coastguard Worker *
9945*6777b538SAndroid Build Coastguard Worker * Compile a predicate expression
9946*6777b538SAndroid Build Coastguard Worker */
9947*6777b538SAndroid Build Coastguard Worker static void
xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt,int filter)9948*6777b538SAndroid Build Coastguard Worker xmlXPathCompPredicate(xmlXPathParserContextPtr ctxt, int filter) {
9949*6777b538SAndroid Build Coastguard Worker int op1 = ctxt->comp->last;
9950*6777b538SAndroid Build Coastguard Worker
9951*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9952*6777b538SAndroid Build Coastguard Worker if (CUR != '[') {
9953*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
9954*6777b538SAndroid Build Coastguard Worker }
9955*6777b538SAndroid Build Coastguard Worker NEXT;
9956*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9957*6777b538SAndroid Build Coastguard Worker
9958*6777b538SAndroid Build Coastguard Worker ctxt->comp->last = -1;
9959*6777b538SAndroid Build Coastguard Worker /*
9960*6777b538SAndroid Build Coastguard Worker * This call to xmlXPathCompileExpr() will deactivate sorting
9961*6777b538SAndroid Build Coastguard Worker * of the predicate result.
9962*6777b538SAndroid Build Coastguard Worker * TODO: Sorting is still activated for filters, since I'm not
9963*6777b538SAndroid Build Coastguard Worker * sure if needed. Normally sorting should not be needed, since
9964*6777b538SAndroid Build Coastguard Worker * a filter can only diminish the number of items in a sequence,
9965*6777b538SAndroid Build Coastguard Worker * but won't change its order; so if the initial sequence is sorted,
9966*6777b538SAndroid Build Coastguard Worker * subsequent sorting is not needed.
9967*6777b538SAndroid Build Coastguard Worker */
9968*6777b538SAndroid Build Coastguard Worker if (! filter)
9969*6777b538SAndroid Build Coastguard Worker xmlXPathCompileExpr(ctxt, 0);
9970*6777b538SAndroid Build Coastguard Worker else
9971*6777b538SAndroid Build Coastguard Worker xmlXPathCompileExpr(ctxt, 1);
9972*6777b538SAndroid Build Coastguard Worker CHECK_ERROR;
9973*6777b538SAndroid Build Coastguard Worker
9974*6777b538SAndroid Build Coastguard Worker if (CUR != ']') {
9975*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_PREDICATE_ERROR);
9976*6777b538SAndroid Build Coastguard Worker }
9977*6777b538SAndroid Build Coastguard Worker
9978*6777b538SAndroid Build Coastguard Worker if (filter)
9979*6777b538SAndroid Build Coastguard Worker PUSH_BINARY_EXPR(XPATH_OP_FILTER, op1, ctxt->comp->last, 0, 0);
9980*6777b538SAndroid Build Coastguard Worker else
9981*6777b538SAndroid Build Coastguard Worker PUSH_BINARY_EXPR(XPATH_OP_PREDICATE, op1, ctxt->comp->last, 0, 0);
9982*6777b538SAndroid Build Coastguard Worker
9983*6777b538SAndroid Build Coastguard Worker NEXT;
9984*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
9985*6777b538SAndroid Build Coastguard Worker }
9986*6777b538SAndroid Build Coastguard Worker
9987*6777b538SAndroid Build Coastguard Worker /**
9988*6777b538SAndroid Build Coastguard Worker * xmlXPathCompNodeTest:
9989*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
9990*6777b538SAndroid Build Coastguard Worker * @test: pointer to a xmlXPathTestVal
9991*6777b538SAndroid Build Coastguard Worker * @type: pointer to a xmlXPathTypeVal
9992*6777b538SAndroid Build Coastguard Worker * @prefix: placeholder for a possible name prefix
9993*6777b538SAndroid Build Coastguard Worker *
9994*6777b538SAndroid Build Coastguard Worker * [7] NodeTest ::= NameTest
9995*6777b538SAndroid Build Coastguard Worker * | NodeType '(' ')'
9996*6777b538SAndroid Build Coastguard Worker * | 'processing-instruction' '(' Literal ')'
9997*6777b538SAndroid Build Coastguard Worker *
9998*6777b538SAndroid Build Coastguard Worker * [37] NameTest ::= '*'
9999*6777b538SAndroid Build Coastguard Worker * | NCName ':' '*'
10000*6777b538SAndroid Build Coastguard Worker * | QName
10001*6777b538SAndroid Build Coastguard Worker * [38] NodeType ::= 'comment'
10002*6777b538SAndroid Build Coastguard Worker * | 'text'
10003*6777b538SAndroid Build Coastguard Worker * | 'processing-instruction'
10004*6777b538SAndroid Build Coastguard Worker * | 'node'
10005*6777b538SAndroid Build Coastguard Worker *
10006*6777b538SAndroid Build Coastguard Worker * Returns the name found and updates @test, @type and @prefix appropriately
10007*6777b538SAndroid Build Coastguard Worker */
10008*6777b538SAndroid Build Coastguard Worker static xmlChar *
xmlXPathCompNodeTest(xmlXPathParserContextPtr ctxt,xmlXPathTestVal * test,xmlXPathTypeVal * type,xmlChar ** prefix,xmlChar * name)10009*6777b538SAndroid Build Coastguard Worker xmlXPathCompNodeTest(xmlXPathParserContextPtr ctxt, xmlXPathTestVal *test,
10010*6777b538SAndroid Build Coastguard Worker xmlXPathTypeVal *type, xmlChar **prefix,
10011*6777b538SAndroid Build Coastguard Worker xmlChar *name) {
10012*6777b538SAndroid Build Coastguard Worker int blanks;
10013*6777b538SAndroid Build Coastguard Worker
10014*6777b538SAndroid Build Coastguard Worker if ((test == NULL) || (type == NULL) || (prefix == NULL)) {
10015*6777b538SAndroid Build Coastguard Worker return(NULL);
10016*6777b538SAndroid Build Coastguard Worker }
10017*6777b538SAndroid Build Coastguard Worker *type = (xmlXPathTypeVal) 0;
10018*6777b538SAndroid Build Coastguard Worker *test = (xmlXPathTestVal) 0;
10019*6777b538SAndroid Build Coastguard Worker *prefix = NULL;
10020*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
10021*6777b538SAndroid Build Coastguard Worker
10022*6777b538SAndroid Build Coastguard Worker if ((name == NULL) && (CUR == '*')) {
10023*6777b538SAndroid Build Coastguard Worker /*
10024*6777b538SAndroid Build Coastguard Worker * All elements
10025*6777b538SAndroid Build Coastguard Worker */
10026*6777b538SAndroid Build Coastguard Worker NEXT;
10027*6777b538SAndroid Build Coastguard Worker *test = NODE_TEST_ALL;
10028*6777b538SAndroid Build Coastguard Worker return(NULL);
10029*6777b538SAndroid Build Coastguard Worker }
10030*6777b538SAndroid Build Coastguard Worker
10031*6777b538SAndroid Build Coastguard Worker if (name == NULL)
10032*6777b538SAndroid Build Coastguard Worker name = xmlXPathParseNCName(ctxt);
10033*6777b538SAndroid Build Coastguard Worker if (name == NULL) {
10034*6777b538SAndroid Build Coastguard Worker XP_ERRORNULL(XPATH_EXPR_ERROR);
10035*6777b538SAndroid Build Coastguard Worker }
10036*6777b538SAndroid Build Coastguard Worker
10037*6777b538SAndroid Build Coastguard Worker blanks = IS_BLANK_CH(CUR);
10038*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
10039*6777b538SAndroid Build Coastguard Worker if (CUR == '(') {
10040*6777b538SAndroid Build Coastguard Worker NEXT;
10041*6777b538SAndroid Build Coastguard Worker /*
10042*6777b538SAndroid Build Coastguard Worker * NodeType or PI search
10043*6777b538SAndroid Build Coastguard Worker */
10044*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "comment"))
10045*6777b538SAndroid Build Coastguard Worker *type = NODE_TYPE_COMMENT;
10046*6777b538SAndroid Build Coastguard Worker else if (xmlStrEqual(name, BAD_CAST "node"))
10047*6777b538SAndroid Build Coastguard Worker *type = NODE_TYPE_NODE;
10048*6777b538SAndroid Build Coastguard Worker else if (xmlStrEqual(name, BAD_CAST "processing-instruction"))
10049*6777b538SAndroid Build Coastguard Worker *type = NODE_TYPE_PI;
10050*6777b538SAndroid Build Coastguard Worker else if (xmlStrEqual(name, BAD_CAST "text"))
10051*6777b538SAndroid Build Coastguard Worker *type = NODE_TYPE_TEXT;
10052*6777b538SAndroid Build Coastguard Worker else {
10053*6777b538SAndroid Build Coastguard Worker if (name != NULL)
10054*6777b538SAndroid Build Coastguard Worker xmlFree(name);
10055*6777b538SAndroid Build Coastguard Worker XP_ERRORNULL(XPATH_EXPR_ERROR);
10056*6777b538SAndroid Build Coastguard Worker }
10057*6777b538SAndroid Build Coastguard Worker
10058*6777b538SAndroid Build Coastguard Worker *test = NODE_TEST_TYPE;
10059*6777b538SAndroid Build Coastguard Worker
10060*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
10061*6777b538SAndroid Build Coastguard Worker if (*type == NODE_TYPE_PI) {
10062*6777b538SAndroid Build Coastguard Worker /*
10063*6777b538SAndroid Build Coastguard Worker * Specific case: search a PI by name.
10064*6777b538SAndroid Build Coastguard Worker */
10065*6777b538SAndroid Build Coastguard Worker if (name != NULL)
10066*6777b538SAndroid Build Coastguard Worker xmlFree(name);
10067*6777b538SAndroid Build Coastguard Worker name = NULL;
10068*6777b538SAndroid Build Coastguard Worker if (CUR != ')') {
10069*6777b538SAndroid Build Coastguard Worker name = xmlXPathParseLiteral(ctxt);
10070*6777b538SAndroid Build Coastguard Worker *test = NODE_TEST_PI;
10071*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
10072*6777b538SAndroid Build Coastguard Worker }
10073*6777b538SAndroid Build Coastguard Worker }
10074*6777b538SAndroid Build Coastguard Worker if (CUR != ')') {
10075*6777b538SAndroid Build Coastguard Worker if (name != NULL)
10076*6777b538SAndroid Build Coastguard Worker xmlFree(name);
10077*6777b538SAndroid Build Coastguard Worker XP_ERRORNULL(XPATH_UNCLOSED_ERROR);
10078*6777b538SAndroid Build Coastguard Worker }
10079*6777b538SAndroid Build Coastguard Worker NEXT;
10080*6777b538SAndroid Build Coastguard Worker return(name);
10081*6777b538SAndroid Build Coastguard Worker }
10082*6777b538SAndroid Build Coastguard Worker *test = NODE_TEST_NAME;
10083*6777b538SAndroid Build Coastguard Worker if ((!blanks) && (CUR == ':')) {
10084*6777b538SAndroid Build Coastguard Worker NEXT;
10085*6777b538SAndroid Build Coastguard Worker
10086*6777b538SAndroid Build Coastguard Worker /*
10087*6777b538SAndroid Build Coastguard Worker * Since currently the parser context don't have a
10088*6777b538SAndroid Build Coastguard Worker * namespace list associated:
10089*6777b538SAndroid Build Coastguard Worker * The namespace name for this prefix can be computed
10090*6777b538SAndroid Build Coastguard Worker * only at evaluation time. The compilation is done
10091*6777b538SAndroid Build Coastguard Worker * outside of any context.
10092*6777b538SAndroid Build Coastguard Worker */
10093*6777b538SAndroid Build Coastguard Worker #if 0
10094*6777b538SAndroid Build Coastguard Worker *prefix = xmlXPathNsLookup(ctxt->context, name);
10095*6777b538SAndroid Build Coastguard Worker if (name != NULL)
10096*6777b538SAndroid Build Coastguard Worker xmlFree(name);
10097*6777b538SAndroid Build Coastguard Worker if (*prefix == NULL) {
10098*6777b538SAndroid Build Coastguard Worker XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
10099*6777b538SAndroid Build Coastguard Worker }
10100*6777b538SAndroid Build Coastguard Worker #else
10101*6777b538SAndroid Build Coastguard Worker *prefix = name;
10102*6777b538SAndroid Build Coastguard Worker #endif
10103*6777b538SAndroid Build Coastguard Worker
10104*6777b538SAndroid Build Coastguard Worker if (CUR == '*') {
10105*6777b538SAndroid Build Coastguard Worker /*
10106*6777b538SAndroid Build Coastguard Worker * All elements
10107*6777b538SAndroid Build Coastguard Worker */
10108*6777b538SAndroid Build Coastguard Worker NEXT;
10109*6777b538SAndroid Build Coastguard Worker *test = NODE_TEST_ALL;
10110*6777b538SAndroid Build Coastguard Worker return(NULL);
10111*6777b538SAndroid Build Coastguard Worker }
10112*6777b538SAndroid Build Coastguard Worker
10113*6777b538SAndroid Build Coastguard Worker name = xmlXPathParseNCName(ctxt);
10114*6777b538SAndroid Build Coastguard Worker if (name == NULL) {
10115*6777b538SAndroid Build Coastguard Worker XP_ERRORNULL(XPATH_EXPR_ERROR);
10116*6777b538SAndroid Build Coastguard Worker }
10117*6777b538SAndroid Build Coastguard Worker }
10118*6777b538SAndroid Build Coastguard Worker return(name);
10119*6777b538SAndroid Build Coastguard Worker }
10120*6777b538SAndroid Build Coastguard Worker
10121*6777b538SAndroid Build Coastguard Worker /**
10122*6777b538SAndroid Build Coastguard Worker * xmlXPathIsAxisName:
10123*6777b538SAndroid Build Coastguard Worker * @name: a preparsed name token
10124*6777b538SAndroid Build Coastguard Worker *
10125*6777b538SAndroid Build Coastguard Worker * [6] AxisName ::= 'ancestor'
10126*6777b538SAndroid Build Coastguard Worker * | 'ancestor-or-self'
10127*6777b538SAndroid Build Coastguard Worker * | 'attribute'
10128*6777b538SAndroid Build Coastguard Worker * | 'child'
10129*6777b538SAndroid Build Coastguard Worker * | 'descendant'
10130*6777b538SAndroid Build Coastguard Worker * | 'descendant-or-self'
10131*6777b538SAndroid Build Coastguard Worker * | 'following'
10132*6777b538SAndroid Build Coastguard Worker * | 'following-sibling'
10133*6777b538SAndroid Build Coastguard Worker * | 'namespace'
10134*6777b538SAndroid Build Coastguard Worker * | 'parent'
10135*6777b538SAndroid Build Coastguard Worker * | 'preceding'
10136*6777b538SAndroid Build Coastguard Worker * | 'preceding-sibling'
10137*6777b538SAndroid Build Coastguard Worker * | 'self'
10138*6777b538SAndroid Build Coastguard Worker *
10139*6777b538SAndroid Build Coastguard Worker * Returns the axis or 0
10140*6777b538SAndroid Build Coastguard Worker */
10141*6777b538SAndroid Build Coastguard Worker static xmlXPathAxisVal
xmlXPathIsAxisName(const xmlChar * name)10142*6777b538SAndroid Build Coastguard Worker xmlXPathIsAxisName(const xmlChar *name) {
10143*6777b538SAndroid Build Coastguard Worker xmlXPathAxisVal ret = (xmlXPathAxisVal) 0;
10144*6777b538SAndroid Build Coastguard Worker switch (name[0]) {
10145*6777b538SAndroid Build Coastguard Worker case 'a':
10146*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "ancestor"))
10147*6777b538SAndroid Build Coastguard Worker ret = AXIS_ANCESTOR;
10148*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "ancestor-or-self"))
10149*6777b538SAndroid Build Coastguard Worker ret = AXIS_ANCESTOR_OR_SELF;
10150*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "attribute"))
10151*6777b538SAndroid Build Coastguard Worker ret = AXIS_ATTRIBUTE;
10152*6777b538SAndroid Build Coastguard Worker break;
10153*6777b538SAndroid Build Coastguard Worker case 'c':
10154*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "child"))
10155*6777b538SAndroid Build Coastguard Worker ret = AXIS_CHILD;
10156*6777b538SAndroid Build Coastguard Worker break;
10157*6777b538SAndroid Build Coastguard Worker case 'd':
10158*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "descendant"))
10159*6777b538SAndroid Build Coastguard Worker ret = AXIS_DESCENDANT;
10160*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "descendant-or-self"))
10161*6777b538SAndroid Build Coastguard Worker ret = AXIS_DESCENDANT_OR_SELF;
10162*6777b538SAndroid Build Coastguard Worker break;
10163*6777b538SAndroid Build Coastguard Worker case 'f':
10164*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "following"))
10165*6777b538SAndroid Build Coastguard Worker ret = AXIS_FOLLOWING;
10166*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "following-sibling"))
10167*6777b538SAndroid Build Coastguard Worker ret = AXIS_FOLLOWING_SIBLING;
10168*6777b538SAndroid Build Coastguard Worker break;
10169*6777b538SAndroid Build Coastguard Worker case 'n':
10170*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "namespace"))
10171*6777b538SAndroid Build Coastguard Worker ret = AXIS_NAMESPACE;
10172*6777b538SAndroid Build Coastguard Worker break;
10173*6777b538SAndroid Build Coastguard Worker case 'p':
10174*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "parent"))
10175*6777b538SAndroid Build Coastguard Worker ret = AXIS_PARENT;
10176*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "preceding"))
10177*6777b538SAndroid Build Coastguard Worker ret = AXIS_PRECEDING;
10178*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "preceding-sibling"))
10179*6777b538SAndroid Build Coastguard Worker ret = AXIS_PRECEDING_SIBLING;
10180*6777b538SAndroid Build Coastguard Worker break;
10181*6777b538SAndroid Build Coastguard Worker case 's':
10182*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(name, BAD_CAST "self"))
10183*6777b538SAndroid Build Coastguard Worker ret = AXIS_SELF;
10184*6777b538SAndroid Build Coastguard Worker break;
10185*6777b538SAndroid Build Coastguard Worker }
10186*6777b538SAndroid Build Coastguard Worker return(ret);
10187*6777b538SAndroid Build Coastguard Worker }
10188*6777b538SAndroid Build Coastguard Worker
10189*6777b538SAndroid Build Coastguard Worker /**
10190*6777b538SAndroid Build Coastguard Worker * xmlXPathCompStep:
10191*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
10192*6777b538SAndroid Build Coastguard Worker *
10193*6777b538SAndroid Build Coastguard Worker * [4] Step ::= AxisSpecifier NodeTest Predicate*
10194*6777b538SAndroid Build Coastguard Worker * | AbbreviatedStep
10195*6777b538SAndroid Build Coastguard Worker *
10196*6777b538SAndroid Build Coastguard Worker * [12] AbbreviatedStep ::= '.' | '..'
10197*6777b538SAndroid Build Coastguard Worker *
10198*6777b538SAndroid Build Coastguard Worker * [5] AxisSpecifier ::= AxisName '::'
10199*6777b538SAndroid Build Coastguard Worker * | AbbreviatedAxisSpecifier
10200*6777b538SAndroid Build Coastguard Worker *
10201*6777b538SAndroid Build Coastguard Worker * [13] AbbreviatedAxisSpecifier ::= '@'?
10202*6777b538SAndroid Build Coastguard Worker *
10203*6777b538SAndroid Build Coastguard Worker * Modified for XPtr range support as:
10204*6777b538SAndroid Build Coastguard Worker *
10205*6777b538SAndroid Build Coastguard Worker * [4xptr] Step ::= AxisSpecifier NodeTest Predicate*
10206*6777b538SAndroid Build Coastguard Worker * | AbbreviatedStep
10207*6777b538SAndroid Build Coastguard Worker * | 'range-to' '(' Expr ')' Predicate*
10208*6777b538SAndroid Build Coastguard Worker *
10209*6777b538SAndroid Build Coastguard Worker * Compile one step in a Location Path
10210*6777b538SAndroid Build Coastguard Worker * A location step of . is short for self::node(). This is
10211*6777b538SAndroid Build Coastguard Worker * particularly useful in conjunction with //. For example, the
10212*6777b538SAndroid Build Coastguard Worker * location path .//para is short for
10213*6777b538SAndroid Build Coastguard Worker * self::node()/descendant-or-self::node()/child::para
10214*6777b538SAndroid Build Coastguard Worker * and so will select all para descendant elements of the context
10215*6777b538SAndroid Build Coastguard Worker * node.
10216*6777b538SAndroid Build Coastguard Worker * Similarly, a location step of .. is short for parent::node().
10217*6777b538SAndroid Build Coastguard Worker * For example, ../title is short for parent::node()/child::title
10218*6777b538SAndroid Build Coastguard Worker * and so will select the title children of the parent of the context
10219*6777b538SAndroid Build Coastguard Worker * node.
10220*6777b538SAndroid Build Coastguard Worker */
10221*6777b538SAndroid Build Coastguard Worker static void
xmlXPathCompStep(xmlXPathParserContextPtr ctxt)10222*6777b538SAndroid Build Coastguard Worker xmlXPathCompStep(xmlXPathParserContextPtr ctxt) {
10223*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
10224*6777b538SAndroid Build Coastguard Worker int rangeto = 0;
10225*6777b538SAndroid Build Coastguard Worker int op2 = -1;
10226*6777b538SAndroid Build Coastguard Worker #endif
10227*6777b538SAndroid Build Coastguard Worker
10228*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
10229*6777b538SAndroid Build Coastguard Worker if ((CUR == '.') && (NXT(1) == '.')) {
10230*6777b538SAndroid Build Coastguard Worker SKIP(2);
10231*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
10232*6777b538SAndroid Build Coastguard Worker PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_PARENT,
10233*6777b538SAndroid Build Coastguard Worker NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
10234*6777b538SAndroid Build Coastguard Worker } else if (CUR == '.') {
10235*6777b538SAndroid Build Coastguard Worker NEXT;
10236*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
10237*6777b538SAndroid Build Coastguard Worker } else {
10238*6777b538SAndroid Build Coastguard Worker xmlChar *name = NULL;
10239*6777b538SAndroid Build Coastguard Worker xmlChar *prefix = NULL;
10240*6777b538SAndroid Build Coastguard Worker xmlXPathTestVal test = (xmlXPathTestVal) 0;
10241*6777b538SAndroid Build Coastguard Worker xmlXPathAxisVal axis = (xmlXPathAxisVal) 0;
10242*6777b538SAndroid Build Coastguard Worker xmlXPathTypeVal type = (xmlXPathTypeVal) 0;
10243*6777b538SAndroid Build Coastguard Worker int op1;
10244*6777b538SAndroid Build Coastguard Worker
10245*6777b538SAndroid Build Coastguard Worker /*
10246*6777b538SAndroid Build Coastguard Worker * The modification needed for XPointer change to the production
10247*6777b538SAndroid Build Coastguard Worker */
10248*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
10249*6777b538SAndroid Build Coastguard Worker if (ctxt->xptr) {
10250*6777b538SAndroid Build Coastguard Worker name = xmlXPathParseNCName(ctxt);
10251*6777b538SAndroid Build Coastguard Worker if ((name != NULL) && (xmlStrEqual(name, BAD_CAST "range-to"))) {
10252*6777b538SAndroid Build Coastguard Worker op2 = ctxt->comp->last;
10253*6777b538SAndroid Build Coastguard Worker xmlFree(name);
10254*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
10255*6777b538SAndroid Build Coastguard Worker if (CUR != '(') {
10256*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_EXPR_ERROR);
10257*6777b538SAndroid Build Coastguard Worker }
10258*6777b538SAndroid Build Coastguard Worker NEXT;
10259*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
10260*6777b538SAndroid Build Coastguard Worker
10261*6777b538SAndroid Build Coastguard Worker xmlXPathCompileExpr(ctxt, 1);
10262*6777b538SAndroid Build Coastguard Worker /* PUSH_BINARY_EXPR(XPATH_OP_RANGETO, op2, ctxt->comp->last, 0, 0); */
10263*6777b538SAndroid Build Coastguard Worker CHECK_ERROR;
10264*6777b538SAndroid Build Coastguard Worker
10265*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
10266*6777b538SAndroid Build Coastguard Worker if (CUR != ')') {
10267*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_EXPR_ERROR);
10268*6777b538SAndroid Build Coastguard Worker }
10269*6777b538SAndroid Build Coastguard Worker NEXT;
10270*6777b538SAndroid Build Coastguard Worker rangeto = 1;
10271*6777b538SAndroid Build Coastguard Worker goto eval_predicates;
10272*6777b538SAndroid Build Coastguard Worker }
10273*6777b538SAndroid Build Coastguard Worker }
10274*6777b538SAndroid Build Coastguard Worker #endif
10275*6777b538SAndroid Build Coastguard Worker if (CUR == '*') {
10276*6777b538SAndroid Build Coastguard Worker axis = AXIS_CHILD;
10277*6777b538SAndroid Build Coastguard Worker } else {
10278*6777b538SAndroid Build Coastguard Worker if (name == NULL)
10279*6777b538SAndroid Build Coastguard Worker name = xmlXPathParseNCName(ctxt);
10280*6777b538SAndroid Build Coastguard Worker if (name != NULL) {
10281*6777b538SAndroid Build Coastguard Worker axis = xmlXPathIsAxisName(name);
10282*6777b538SAndroid Build Coastguard Worker if (axis != 0) {
10283*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
10284*6777b538SAndroid Build Coastguard Worker if ((CUR == ':') && (NXT(1) == ':')) {
10285*6777b538SAndroid Build Coastguard Worker SKIP(2);
10286*6777b538SAndroid Build Coastguard Worker xmlFree(name);
10287*6777b538SAndroid Build Coastguard Worker name = NULL;
10288*6777b538SAndroid Build Coastguard Worker } else {
10289*6777b538SAndroid Build Coastguard Worker /* an element name can conflict with an axis one :-\ */
10290*6777b538SAndroid Build Coastguard Worker axis = AXIS_CHILD;
10291*6777b538SAndroid Build Coastguard Worker }
10292*6777b538SAndroid Build Coastguard Worker } else {
10293*6777b538SAndroid Build Coastguard Worker axis = AXIS_CHILD;
10294*6777b538SAndroid Build Coastguard Worker }
10295*6777b538SAndroid Build Coastguard Worker } else if (CUR == '@') {
10296*6777b538SAndroid Build Coastguard Worker NEXT;
10297*6777b538SAndroid Build Coastguard Worker axis = AXIS_ATTRIBUTE;
10298*6777b538SAndroid Build Coastguard Worker } else {
10299*6777b538SAndroid Build Coastguard Worker axis = AXIS_CHILD;
10300*6777b538SAndroid Build Coastguard Worker }
10301*6777b538SAndroid Build Coastguard Worker }
10302*6777b538SAndroid Build Coastguard Worker
10303*6777b538SAndroid Build Coastguard Worker if (ctxt->error != XPATH_EXPRESSION_OK) {
10304*6777b538SAndroid Build Coastguard Worker xmlFree(name);
10305*6777b538SAndroid Build Coastguard Worker return;
10306*6777b538SAndroid Build Coastguard Worker }
10307*6777b538SAndroid Build Coastguard Worker
10308*6777b538SAndroid Build Coastguard Worker name = xmlXPathCompNodeTest(ctxt, &test, &type, &prefix, name);
10309*6777b538SAndroid Build Coastguard Worker if (test == 0)
10310*6777b538SAndroid Build Coastguard Worker return;
10311*6777b538SAndroid Build Coastguard Worker
10312*6777b538SAndroid Build Coastguard Worker if ((prefix != NULL) && (ctxt->context != NULL) &&
10313*6777b538SAndroid Build Coastguard Worker (ctxt->context->flags & XML_XPATH_CHECKNS)) {
10314*6777b538SAndroid Build Coastguard Worker if (xmlXPathNsLookup(ctxt->context, prefix) == NULL) {
10315*6777b538SAndroid Build Coastguard Worker xmlXPathErr(ctxt, XPATH_UNDEF_PREFIX_ERROR);
10316*6777b538SAndroid Build Coastguard Worker }
10317*6777b538SAndroid Build Coastguard Worker }
10318*6777b538SAndroid Build Coastguard Worker
10319*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
10320*6777b538SAndroid Build Coastguard Worker eval_predicates:
10321*6777b538SAndroid Build Coastguard Worker #endif
10322*6777b538SAndroid Build Coastguard Worker op1 = ctxt->comp->last;
10323*6777b538SAndroid Build Coastguard Worker ctxt->comp->last = -1;
10324*6777b538SAndroid Build Coastguard Worker
10325*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
10326*6777b538SAndroid Build Coastguard Worker while (CUR == '[') {
10327*6777b538SAndroid Build Coastguard Worker xmlXPathCompPredicate(ctxt, 0);
10328*6777b538SAndroid Build Coastguard Worker }
10329*6777b538SAndroid Build Coastguard Worker
10330*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
10331*6777b538SAndroid Build Coastguard Worker if (rangeto) {
10332*6777b538SAndroid Build Coastguard Worker PUSH_BINARY_EXPR(XPATH_OP_RANGETO, op2, op1, 0, 0);
10333*6777b538SAndroid Build Coastguard Worker } else
10334*6777b538SAndroid Build Coastguard Worker #endif
10335*6777b538SAndroid Build Coastguard Worker if (PUSH_FULL_EXPR(XPATH_OP_COLLECT, op1, ctxt->comp->last, axis,
10336*6777b538SAndroid Build Coastguard Worker test, type, (void *)prefix, (void *)name) == -1) {
10337*6777b538SAndroid Build Coastguard Worker xmlFree(prefix);
10338*6777b538SAndroid Build Coastguard Worker xmlFree(name);
10339*6777b538SAndroid Build Coastguard Worker }
10340*6777b538SAndroid Build Coastguard Worker }
10341*6777b538SAndroid Build Coastguard Worker }
10342*6777b538SAndroid Build Coastguard Worker
10343*6777b538SAndroid Build Coastguard Worker /**
10344*6777b538SAndroid Build Coastguard Worker * xmlXPathCompRelativeLocationPath:
10345*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
10346*6777b538SAndroid Build Coastguard Worker *
10347*6777b538SAndroid Build Coastguard Worker * [3] RelativeLocationPath ::= Step
10348*6777b538SAndroid Build Coastguard Worker * | RelativeLocationPath '/' Step
10349*6777b538SAndroid Build Coastguard Worker * | AbbreviatedRelativeLocationPath
10350*6777b538SAndroid Build Coastguard Worker * [11] AbbreviatedRelativeLocationPath ::= RelativeLocationPath '//' Step
10351*6777b538SAndroid Build Coastguard Worker *
10352*6777b538SAndroid Build Coastguard Worker * Compile a relative location path.
10353*6777b538SAndroid Build Coastguard Worker */
10354*6777b538SAndroid Build Coastguard Worker static void
xmlXPathCompRelativeLocationPath(xmlXPathParserContextPtr ctxt)10355*6777b538SAndroid Build Coastguard Worker xmlXPathCompRelativeLocationPath
10356*6777b538SAndroid Build Coastguard Worker (xmlXPathParserContextPtr ctxt) {
10357*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
10358*6777b538SAndroid Build Coastguard Worker if ((CUR == '/') && (NXT(1) == '/')) {
10359*6777b538SAndroid Build Coastguard Worker SKIP(2);
10360*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
10361*6777b538SAndroid Build Coastguard Worker PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
10362*6777b538SAndroid Build Coastguard Worker NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
10363*6777b538SAndroid Build Coastguard Worker } else if (CUR == '/') {
10364*6777b538SAndroid Build Coastguard Worker NEXT;
10365*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
10366*6777b538SAndroid Build Coastguard Worker }
10367*6777b538SAndroid Build Coastguard Worker xmlXPathCompStep(ctxt);
10368*6777b538SAndroid Build Coastguard Worker CHECK_ERROR;
10369*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
10370*6777b538SAndroid Build Coastguard Worker while (CUR == '/') {
10371*6777b538SAndroid Build Coastguard Worker if ((CUR == '/') && (NXT(1) == '/')) {
10372*6777b538SAndroid Build Coastguard Worker SKIP(2);
10373*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
10374*6777b538SAndroid Build Coastguard Worker PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
10375*6777b538SAndroid Build Coastguard Worker NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
10376*6777b538SAndroid Build Coastguard Worker xmlXPathCompStep(ctxt);
10377*6777b538SAndroid Build Coastguard Worker } else if (CUR == '/') {
10378*6777b538SAndroid Build Coastguard Worker NEXT;
10379*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
10380*6777b538SAndroid Build Coastguard Worker xmlXPathCompStep(ctxt);
10381*6777b538SAndroid Build Coastguard Worker }
10382*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
10383*6777b538SAndroid Build Coastguard Worker }
10384*6777b538SAndroid Build Coastguard Worker }
10385*6777b538SAndroid Build Coastguard Worker
10386*6777b538SAndroid Build Coastguard Worker /**
10387*6777b538SAndroid Build Coastguard Worker * xmlXPathCompLocationPath:
10388*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
10389*6777b538SAndroid Build Coastguard Worker *
10390*6777b538SAndroid Build Coastguard Worker * [1] LocationPath ::= RelativeLocationPath
10391*6777b538SAndroid Build Coastguard Worker * | AbsoluteLocationPath
10392*6777b538SAndroid Build Coastguard Worker * [2] AbsoluteLocationPath ::= '/' RelativeLocationPath?
10393*6777b538SAndroid Build Coastguard Worker * | AbbreviatedAbsoluteLocationPath
10394*6777b538SAndroid Build Coastguard Worker * [10] AbbreviatedAbsoluteLocationPath ::=
10395*6777b538SAndroid Build Coastguard Worker * '//' RelativeLocationPath
10396*6777b538SAndroid Build Coastguard Worker *
10397*6777b538SAndroid Build Coastguard Worker * Compile a location path
10398*6777b538SAndroid Build Coastguard Worker *
10399*6777b538SAndroid Build Coastguard Worker * // is short for /descendant-or-self::node()/. For example,
10400*6777b538SAndroid Build Coastguard Worker * //para is short for /descendant-or-self::node()/child::para and
10401*6777b538SAndroid Build Coastguard Worker * so will select any para element in the document (even a para element
10402*6777b538SAndroid Build Coastguard Worker * that is a document element will be selected by //para since the
10403*6777b538SAndroid Build Coastguard Worker * document element node is a child of the root node); div//para is
10404*6777b538SAndroid Build Coastguard Worker * short for div/descendant-or-self::node()/child::para and so will
10405*6777b538SAndroid Build Coastguard Worker * select all para descendants of div children.
10406*6777b538SAndroid Build Coastguard Worker */
10407*6777b538SAndroid Build Coastguard Worker static void
xmlXPathCompLocationPath(xmlXPathParserContextPtr ctxt)10408*6777b538SAndroid Build Coastguard Worker xmlXPathCompLocationPath(xmlXPathParserContextPtr ctxt) {
10409*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
10410*6777b538SAndroid Build Coastguard Worker if (CUR != '/') {
10411*6777b538SAndroid Build Coastguard Worker xmlXPathCompRelativeLocationPath(ctxt);
10412*6777b538SAndroid Build Coastguard Worker } else {
10413*6777b538SAndroid Build Coastguard Worker while (CUR == '/') {
10414*6777b538SAndroid Build Coastguard Worker if ((CUR == '/') && (NXT(1) == '/')) {
10415*6777b538SAndroid Build Coastguard Worker SKIP(2);
10416*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
10417*6777b538SAndroid Build Coastguard Worker PUSH_LONG_EXPR(XPATH_OP_COLLECT, AXIS_DESCENDANT_OR_SELF,
10418*6777b538SAndroid Build Coastguard Worker NODE_TEST_TYPE, NODE_TYPE_NODE, NULL, NULL);
10419*6777b538SAndroid Build Coastguard Worker xmlXPathCompRelativeLocationPath(ctxt);
10420*6777b538SAndroid Build Coastguard Worker } else if (CUR == '/') {
10421*6777b538SAndroid Build Coastguard Worker NEXT;
10422*6777b538SAndroid Build Coastguard Worker SKIP_BLANKS;
10423*6777b538SAndroid Build Coastguard Worker if ((CUR != 0 ) &&
10424*6777b538SAndroid Build Coastguard Worker ((IS_ASCII_LETTER(CUR)) || (CUR == '_') || (CUR == '.') ||
10425*6777b538SAndroid Build Coastguard Worker (CUR == '@') || (CUR == '*')))
10426*6777b538SAndroid Build Coastguard Worker xmlXPathCompRelativeLocationPath(ctxt);
10427*6777b538SAndroid Build Coastguard Worker }
10428*6777b538SAndroid Build Coastguard Worker CHECK_ERROR;
10429*6777b538SAndroid Build Coastguard Worker }
10430*6777b538SAndroid Build Coastguard Worker }
10431*6777b538SAndroid Build Coastguard Worker }
10432*6777b538SAndroid Build Coastguard Worker
10433*6777b538SAndroid Build Coastguard Worker /************************************************************************
10434*6777b538SAndroid Build Coastguard Worker * *
10435*6777b538SAndroid Build Coastguard Worker * XPath precompiled expression evaluation *
10436*6777b538SAndroid Build Coastguard Worker * *
10437*6777b538SAndroid Build Coastguard Worker ************************************************************************/
10438*6777b538SAndroid Build Coastguard Worker
10439*6777b538SAndroid Build Coastguard Worker static int
10440*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op);
10441*6777b538SAndroid Build Coastguard Worker
10442*6777b538SAndroid Build Coastguard Worker /**
10443*6777b538SAndroid Build Coastguard Worker * xmlXPathNodeSetFilter:
10444*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
10445*6777b538SAndroid Build Coastguard Worker * @set: the node set to filter
10446*6777b538SAndroid Build Coastguard Worker * @filterOpIndex: the index of the predicate/filter op
10447*6777b538SAndroid Build Coastguard Worker * @minPos: minimum position in the filtered set (1-based)
10448*6777b538SAndroid Build Coastguard Worker * @maxPos: maximum position in the filtered set (1-based)
10449*6777b538SAndroid Build Coastguard Worker * @hasNsNodes: true if the node set may contain namespace nodes
10450*6777b538SAndroid Build Coastguard Worker *
10451*6777b538SAndroid Build Coastguard Worker * Filter a node set, keeping only nodes for which the predicate expression
10452*6777b538SAndroid Build Coastguard Worker * matches. Afterwards, keep only nodes between minPos and maxPos in the
10453*6777b538SAndroid Build Coastguard Worker * filtered result.
10454*6777b538SAndroid Build Coastguard Worker */
10455*6777b538SAndroid Build Coastguard Worker static void
xmlXPathNodeSetFilter(xmlXPathParserContextPtr ctxt,xmlNodeSetPtr set,int filterOpIndex,int minPos,int maxPos,int hasNsNodes)10456*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetFilter(xmlXPathParserContextPtr ctxt,
10457*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr set,
10458*6777b538SAndroid Build Coastguard Worker int filterOpIndex,
10459*6777b538SAndroid Build Coastguard Worker int minPos, int maxPos,
10460*6777b538SAndroid Build Coastguard Worker int hasNsNodes)
10461*6777b538SAndroid Build Coastguard Worker {
10462*6777b538SAndroid Build Coastguard Worker xmlXPathContextPtr xpctxt;
10463*6777b538SAndroid Build Coastguard Worker xmlNodePtr oldnode;
10464*6777b538SAndroid Build Coastguard Worker xmlDocPtr olddoc;
10465*6777b538SAndroid Build Coastguard Worker xmlXPathStepOpPtr filterOp;
10466*6777b538SAndroid Build Coastguard Worker int oldcs, oldpp;
10467*6777b538SAndroid Build Coastguard Worker int i, j, pos;
10468*6777b538SAndroid Build Coastguard Worker
10469*6777b538SAndroid Build Coastguard Worker if ((set == NULL) || (set->nodeNr == 0))
10470*6777b538SAndroid Build Coastguard Worker return;
10471*6777b538SAndroid Build Coastguard Worker
10472*6777b538SAndroid Build Coastguard Worker /*
10473*6777b538SAndroid Build Coastguard Worker * Check if the node set contains a sufficient number of nodes for
10474*6777b538SAndroid Build Coastguard Worker * the requested range.
10475*6777b538SAndroid Build Coastguard Worker */
10476*6777b538SAndroid Build Coastguard Worker if (set->nodeNr < minPos) {
10477*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetClear(set, hasNsNodes);
10478*6777b538SAndroid Build Coastguard Worker return;
10479*6777b538SAndroid Build Coastguard Worker }
10480*6777b538SAndroid Build Coastguard Worker
10481*6777b538SAndroid Build Coastguard Worker xpctxt = ctxt->context;
10482*6777b538SAndroid Build Coastguard Worker oldnode = xpctxt->node;
10483*6777b538SAndroid Build Coastguard Worker olddoc = xpctxt->doc;
10484*6777b538SAndroid Build Coastguard Worker oldcs = xpctxt->contextSize;
10485*6777b538SAndroid Build Coastguard Worker oldpp = xpctxt->proximityPosition;
10486*6777b538SAndroid Build Coastguard Worker filterOp = &ctxt->comp->steps[filterOpIndex];
10487*6777b538SAndroid Build Coastguard Worker
10488*6777b538SAndroid Build Coastguard Worker xpctxt->contextSize = set->nodeNr;
10489*6777b538SAndroid Build Coastguard Worker
10490*6777b538SAndroid Build Coastguard Worker for (i = 0, j = 0, pos = 1; i < set->nodeNr; i++) {
10491*6777b538SAndroid Build Coastguard Worker xmlNodePtr node = set->nodeTab[i];
10492*6777b538SAndroid Build Coastguard Worker int res;
10493*6777b538SAndroid Build Coastguard Worker
10494*6777b538SAndroid Build Coastguard Worker xpctxt->node = node;
10495*6777b538SAndroid Build Coastguard Worker xpctxt->proximityPosition = i + 1;
10496*6777b538SAndroid Build Coastguard Worker
10497*6777b538SAndroid Build Coastguard Worker /*
10498*6777b538SAndroid Build Coastguard Worker * Also set the xpath document in case things like
10499*6777b538SAndroid Build Coastguard Worker * key() are evaluated in the predicate.
10500*6777b538SAndroid Build Coastguard Worker *
10501*6777b538SAndroid Build Coastguard Worker * TODO: Get real doc for namespace nodes.
10502*6777b538SAndroid Build Coastguard Worker */
10503*6777b538SAndroid Build Coastguard Worker if ((node->type != XML_NAMESPACE_DECL) &&
10504*6777b538SAndroid Build Coastguard Worker (node->doc != NULL))
10505*6777b538SAndroid Build Coastguard Worker xpctxt->doc = node->doc;
10506*6777b538SAndroid Build Coastguard Worker
10507*6777b538SAndroid Build Coastguard Worker res = xmlXPathCompOpEvalToBoolean(ctxt, filterOp, 1);
10508*6777b538SAndroid Build Coastguard Worker
10509*6777b538SAndroid Build Coastguard Worker if (ctxt->error != XPATH_EXPRESSION_OK)
10510*6777b538SAndroid Build Coastguard Worker break;
10511*6777b538SAndroid Build Coastguard Worker if (res < 0) {
10512*6777b538SAndroid Build Coastguard Worker /* Shouldn't happen */
10513*6777b538SAndroid Build Coastguard Worker xmlXPathErr(ctxt, XPATH_EXPR_ERROR);
10514*6777b538SAndroid Build Coastguard Worker break;
10515*6777b538SAndroid Build Coastguard Worker }
10516*6777b538SAndroid Build Coastguard Worker
10517*6777b538SAndroid Build Coastguard Worker if ((res != 0) && ((pos >= minPos) && (pos <= maxPos))) {
10518*6777b538SAndroid Build Coastguard Worker if (i != j) {
10519*6777b538SAndroid Build Coastguard Worker set->nodeTab[j] = node;
10520*6777b538SAndroid Build Coastguard Worker set->nodeTab[i] = NULL;
10521*6777b538SAndroid Build Coastguard Worker }
10522*6777b538SAndroid Build Coastguard Worker
10523*6777b538SAndroid Build Coastguard Worker j += 1;
10524*6777b538SAndroid Build Coastguard Worker } else {
10525*6777b538SAndroid Build Coastguard Worker /* Remove the entry from the initial node set. */
10526*6777b538SAndroid Build Coastguard Worker set->nodeTab[i] = NULL;
10527*6777b538SAndroid Build Coastguard Worker if (node->type == XML_NAMESPACE_DECL)
10528*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetFreeNs((xmlNsPtr) node);
10529*6777b538SAndroid Build Coastguard Worker }
10530*6777b538SAndroid Build Coastguard Worker
10531*6777b538SAndroid Build Coastguard Worker if (res != 0) {
10532*6777b538SAndroid Build Coastguard Worker if (pos == maxPos) {
10533*6777b538SAndroid Build Coastguard Worker i += 1;
10534*6777b538SAndroid Build Coastguard Worker break;
10535*6777b538SAndroid Build Coastguard Worker }
10536*6777b538SAndroid Build Coastguard Worker
10537*6777b538SAndroid Build Coastguard Worker pos += 1;
10538*6777b538SAndroid Build Coastguard Worker }
10539*6777b538SAndroid Build Coastguard Worker }
10540*6777b538SAndroid Build Coastguard Worker
10541*6777b538SAndroid Build Coastguard Worker /* Free remaining nodes. */
10542*6777b538SAndroid Build Coastguard Worker if (hasNsNodes) {
10543*6777b538SAndroid Build Coastguard Worker for (; i < set->nodeNr; i++) {
10544*6777b538SAndroid Build Coastguard Worker xmlNodePtr node = set->nodeTab[i];
10545*6777b538SAndroid Build Coastguard Worker if ((node != NULL) && (node->type == XML_NAMESPACE_DECL))
10546*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetFreeNs((xmlNsPtr) node);
10547*6777b538SAndroid Build Coastguard Worker }
10548*6777b538SAndroid Build Coastguard Worker }
10549*6777b538SAndroid Build Coastguard Worker
10550*6777b538SAndroid Build Coastguard Worker set->nodeNr = j;
10551*6777b538SAndroid Build Coastguard Worker
10552*6777b538SAndroid Build Coastguard Worker /* If too many elements were removed, shrink table to preserve memory. */
10553*6777b538SAndroid Build Coastguard Worker if ((set->nodeMax > XML_NODESET_DEFAULT) &&
10554*6777b538SAndroid Build Coastguard Worker (set->nodeNr < set->nodeMax / 2)) {
10555*6777b538SAndroid Build Coastguard Worker xmlNodePtr *tmp;
10556*6777b538SAndroid Build Coastguard Worker int nodeMax = set->nodeNr;
10557*6777b538SAndroid Build Coastguard Worker
10558*6777b538SAndroid Build Coastguard Worker if (nodeMax < XML_NODESET_DEFAULT)
10559*6777b538SAndroid Build Coastguard Worker nodeMax = XML_NODESET_DEFAULT;
10560*6777b538SAndroid Build Coastguard Worker tmp = (xmlNodePtr *) xmlRealloc(set->nodeTab,
10561*6777b538SAndroid Build Coastguard Worker nodeMax * sizeof(xmlNodePtr));
10562*6777b538SAndroid Build Coastguard Worker if (tmp == NULL) {
10563*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
10564*6777b538SAndroid Build Coastguard Worker } else {
10565*6777b538SAndroid Build Coastguard Worker set->nodeTab = tmp;
10566*6777b538SAndroid Build Coastguard Worker set->nodeMax = nodeMax;
10567*6777b538SAndroid Build Coastguard Worker }
10568*6777b538SAndroid Build Coastguard Worker }
10569*6777b538SAndroid Build Coastguard Worker
10570*6777b538SAndroid Build Coastguard Worker xpctxt->node = oldnode;
10571*6777b538SAndroid Build Coastguard Worker xpctxt->doc = olddoc;
10572*6777b538SAndroid Build Coastguard Worker xpctxt->contextSize = oldcs;
10573*6777b538SAndroid Build Coastguard Worker xpctxt->proximityPosition = oldpp;
10574*6777b538SAndroid Build Coastguard Worker }
10575*6777b538SAndroid Build Coastguard Worker
10576*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
10577*6777b538SAndroid Build Coastguard Worker /**
10578*6777b538SAndroid Build Coastguard Worker * xmlXPathLocationSetFilter:
10579*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
10580*6777b538SAndroid Build Coastguard Worker * @locset: the location set to filter
10581*6777b538SAndroid Build Coastguard Worker * @filterOpIndex: the index of the predicate/filter op
10582*6777b538SAndroid Build Coastguard Worker * @minPos: minimum position in the filtered set (1-based)
10583*6777b538SAndroid Build Coastguard Worker * @maxPos: maximum position in the filtered set (1-based)
10584*6777b538SAndroid Build Coastguard Worker *
10585*6777b538SAndroid Build Coastguard Worker * Filter a location set, keeping only nodes for which the predicate
10586*6777b538SAndroid Build Coastguard Worker * expression matches. Afterwards, keep only nodes between minPos and maxPos
10587*6777b538SAndroid Build Coastguard Worker * in the filtered result.
10588*6777b538SAndroid Build Coastguard Worker */
10589*6777b538SAndroid Build Coastguard Worker static void
xmlXPathLocationSetFilter(xmlXPathParserContextPtr ctxt,xmlLocationSetPtr locset,int filterOpIndex,int minPos,int maxPos)10590*6777b538SAndroid Build Coastguard Worker xmlXPathLocationSetFilter(xmlXPathParserContextPtr ctxt,
10591*6777b538SAndroid Build Coastguard Worker xmlLocationSetPtr locset,
10592*6777b538SAndroid Build Coastguard Worker int filterOpIndex,
10593*6777b538SAndroid Build Coastguard Worker int minPos, int maxPos)
10594*6777b538SAndroid Build Coastguard Worker {
10595*6777b538SAndroid Build Coastguard Worker xmlXPathContextPtr xpctxt;
10596*6777b538SAndroid Build Coastguard Worker xmlNodePtr oldnode;
10597*6777b538SAndroid Build Coastguard Worker xmlDocPtr olddoc;
10598*6777b538SAndroid Build Coastguard Worker xmlXPathStepOpPtr filterOp;
10599*6777b538SAndroid Build Coastguard Worker int oldcs, oldpp;
10600*6777b538SAndroid Build Coastguard Worker int i, j, pos;
10601*6777b538SAndroid Build Coastguard Worker
10602*6777b538SAndroid Build Coastguard Worker if ((locset == NULL) || (locset->locNr == 0) || (filterOpIndex == -1))
10603*6777b538SAndroid Build Coastguard Worker return;
10604*6777b538SAndroid Build Coastguard Worker
10605*6777b538SAndroid Build Coastguard Worker xpctxt = ctxt->context;
10606*6777b538SAndroid Build Coastguard Worker oldnode = xpctxt->node;
10607*6777b538SAndroid Build Coastguard Worker olddoc = xpctxt->doc;
10608*6777b538SAndroid Build Coastguard Worker oldcs = xpctxt->contextSize;
10609*6777b538SAndroid Build Coastguard Worker oldpp = xpctxt->proximityPosition;
10610*6777b538SAndroid Build Coastguard Worker filterOp = &ctxt->comp->steps[filterOpIndex];
10611*6777b538SAndroid Build Coastguard Worker
10612*6777b538SAndroid Build Coastguard Worker xpctxt->contextSize = locset->locNr;
10613*6777b538SAndroid Build Coastguard Worker
10614*6777b538SAndroid Build Coastguard Worker for (i = 0, j = 0, pos = 1; i < locset->locNr; i++) {
10615*6777b538SAndroid Build Coastguard Worker xmlNodePtr contextNode = locset->locTab[i]->user;
10616*6777b538SAndroid Build Coastguard Worker int res;
10617*6777b538SAndroid Build Coastguard Worker
10618*6777b538SAndroid Build Coastguard Worker xpctxt->node = contextNode;
10619*6777b538SAndroid Build Coastguard Worker xpctxt->proximityPosition = i + 1;
10620*6777b538SAndroid Build Coastguard Worker
10621*6777b538SAndroid Build Coastguard Worker /*
10622*6777b538SAndroid Build Coastguard Worker * Also set the xpath document in case things like
10623*6777b538SAndroid Build Coastguard Worker * key() are evaluated in the predicate.
10624*6777b538SAndroid Build Coastguard Worker *
10625*6777b538SAndroid Build Coastguard Worker * TODO: Get real doc for namespace nodes.
10626*6777b538SAndroid Build Coastguard Worker */
10627*6777b538SAndroid Build Coastguard Worker if ((contextNode->type != XML_NAMESPACE_DECL) &&
10628*6777b538SAndroid Build Coastguard Worker (contextNode->doc != NULL))
10629*6777b538SAndroid Build Coastguard Worker xpctxt->doc = contextNode->doc;
10630*6777b538SAndroid Build Coastguard Worker
10631*6777b538SAndroid Build Coastguard Worker res = xmlXPathCompOpEvalToBoolean(ctxt, filterOp, 1);
10632*6777b538SAndroid Build Coastguard Worker
10633*6777b538SAndroid Build Coastguard Worker if (ctxt->error != XPATH_EXPRESSION_OK)
10634*6777b538SAndroid Build Coastguard Worker break;
10635*6777b538SAndroid Build Coastguard Worker if (res < 0) {
10636*6777b538SAndroid Build Coastguard Worker /* Shouldn't happen */
10637*6777b538SAndroid Build Coastguard Worker xmlXPathErr(ctxt, XPATH_EXPR_ERROR);
10638*6777b538SAndroid Build Coastguard Worker break;
10639*6777b538SAndroid Build Coastguard Worker }
10640*6777b538SAndroid Build Coastguard Worker
10641*6777b538SAndroid Build Coastguard Worker if ((res != 0) && ((pos >= minPos) && (pos <= maxPos))) {
10642*6777b538SAndroid Build Coastguard Worker if (i != j) {
10643*6777b538SAndroid Build Coastguard Worker locset->locTab[j] = locset->locTab[i];
10644*6777b538SAndroid Build Coastguard Worker locset->locTab[i] = NULL;
10645*6777b538SAndroid Build Coastguard Worker }
10646*6777b538SAndroid Build Coastguard Worker
10647*6777b538SAndroid Build Coastguard Worker j += 1;
10648*6777b538SAndroid Build Coastguard Worker } else {
10649*6777b538SAndroid Build Coastguard Worker /* Remove the entry from the initial location set. */
10650*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject(locset->locTab[i]);
10651*6777b538SAndroid Build Coastguard Worker locset->locTab[i] = NULL;
10652*6777b538SAndroid Build Coastguard Worker }
10653*6777b538SAndroid Build Coastguard Worker
10654*6777b538SAndroid Build Coastguard Worker if (res != 0) {
10655*6777b538SAndroid Build Coastguard Worker if (pos == maxPos) {
10656*6777b538SAndroid Build Coastguard Worker i += 1;
10657*6777b538SAndroid Build Coastguard Worker break;
10658*6777b538SAndroid Build Coastguard Worker }
10659*6777b538SAndroid Build Coastguard Worker
10660*6777b538SAndroid Build Coastguard Worker pos += 1;
10661*6777b538SAndroid Build Coastguard Worker }
10662*6777b538SAndroid Build Coastguard Worker }
10663*6777b538SAndroid Build Coastguard Worker
10664*6777b538SAndroid Build Coastguard Worker /* Free remaining nodes. */
10665*6777b538SAndroid Build Coastguard Worker for (; i < locset->locNr; i++)
10666*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject(locset->locTab[i]);
10667*6777b538SAndroid Build Coastguard Worker
10668*6777b538SAndroid Build Coastguard Worker locset->locNr = j;
10669*6777b538SAndroid Build Coastguard Worker
10670*6777b538SAndroid Build Coastguard Worker /* If too many elements were removed, shrink table to preserve memory. */
10671*6777b538SAndroid Build Coastguard Worker if ((locset->locMax > XML_NODESET_DEFAULT) &&
10672*6777b538SAndroid Build Coastguard Worker (locset->locNr < locset->locMax / 2)) {
10673*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr *tmp;
10674*6777b538SAndroid Build Coastguard Worker int locMax = locset->locNr;
10675*6777b538SAndroid Build Coastguard Worker
10676*6777b538SAndroid Build Coastguard Worker if (locMax < XML_NODESET_DEFAULT)
10677*6777b538SAndroid Build Coastguard Worker locMax = XML_NODESET_DEFAULT;
10678*6777b538SAndroid Build Coastguard Worker tmp = (xmlXPathObjectPtr *) xmlRealloc(locset->locTab,
10679*6777b538SAndroid Build Coastguard Worker locMax * sizeof(xmlXPathObjectPtr));
10680*6777b538SAndroid Build Coastguard Worker if (tmp == NULL) {
10681*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
10682*6777b538SAndroid Build Coastguard Worker } else {
10683*6777b538SAndroid Build Coastguard Worker locset->locTab = tmp;
10684*6777b538SAndroid Build Coastguard Worker locset->locMax = locMax;
10685*6777b538SAndroid Build Coastguard Worker }
10686*6777b538SAndroid Build Coastguard Worker }
10687*6777b538SAndroid Build Coastguard Worker
10688*6777b538SAndroid Build Coastguard Worker xpctxt->node = oldnode;
10689*6777b538SAndroid Build Coastguard Worker xpctxt->doc = olddoc;
10690*6777b538SAndroid Build Coastguard Worker xpctxt->contextSize = oldcs;
10691*6777b538SAndroid Build Coastguard Worker xpctxt->proximityPosition = oldpp;
10692*6777b538SAndroid Build Coastguard Worker }
10693*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_XPTR_LOCS_ENABLED */
10694*6777b538SAndroid Build Coastguard Worker
10695*6777b538SAndroid Build Coastguard Worker /**
10696*6777b538SAndroid Build Coastguard Worker * xmlXPathCompOpEvalPredicate:
10697*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
10698*6777b538SAndroid Build Coastguard Worker * @op: the predicate op
10699*6777b538SAndroid Build Coastguard Worker * @set: the node set to filter
10700*6777b538SAndroid Build Coastguard Worker * @minPos: minimum position in the filtered set (1-based)
10701*6777b538SAndroid Build Coastguard Worker * @maxPos: maximum position in the filtered set (1-based)
10702*6777b538SAndroid Build Coastguard Worker * @hasNsNodes: true if the node set may contain namespace nodes
10703*6777b538SAndroid Build Coastguard Worker *
10704*6777b538SAndroid Build Coastguard Worker * Filter a node set, keeping only nodes for which the sequence of predicate
10705*6777b538SAndroid Build Coastguard Worker * expressions matches. Afterwards, keep only nodes between minPos and maxPos
10706*6777b538SAndroid Build Coastguard Worker * in the filtered result.
10707*6777b538SAndroid Build Coastguard Worker */
10708*6777b538SAndroid Build Coastguard Worker static void
xmlXPathCompOpEvalPredicate(xmlXPathParserContextPtr ctxt,xmlXPathStepOpPtr op,xmlNodeSetPtr set,int minPos,int maxPos,int hasNsNodes)10709*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEvalPredicate(xmlXPathParserContextPtr ctxt,
10710*6777b538SAndroid Build Coastguard Worker xmlXPathStepOpPtr op,
10711*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr set,
10712*6777b538SAndroid Build Coastguard Worker int minPos, int maxPos,
10713*6777b538SAndroid Build Coastguard Worker int hasNsNodes)
10714*6777b538SAndroid Build Coastguard Worker {
10715*6777b538SAndroid Build Coastguard Worker if (op->ch1 != -1) {
10716*6777b538SAndroid Build Coastguard Worker xmlXPathCompExprPtr comp = ctxt->comp;
10717*6777b538SAndroid Build Coastguard Worker /*
10718*6777b538SAndroid Build Coastguard Worker * Process inner predicates first.
10719*6777b538SAndroid Build Coastguard Worker */
10720*6777b538SAndroid Build Coastguard Worker if (comp->steps[op->ch1].op != XPATH_OP_PREDICATE) {
10721*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_INVALID_OPERAND);
10722*6777b538SAndroid Build Coastguard Worker }
10723*6777b538SAndroid Build Coastguard Worker if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH)
10724*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_RECURSION_LIMIT_EXCEEDED);
10725*6777b538SAndroid Build Coastguard Worker ctxt->context->depth += 1;
10726*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEvalPredicate(ctxt, &comp->steps[op->ch1], set,
10727*6777b538SAndroid Build Coastguard Worker 1, set->nodeNr, hasNsNodes);
10728*6777b538SAndroid Build Coastguard Worker ctxt->context->depth -= 1;
10729*6777b538SAndroid Build Coastguard Worker CHECK_ERROR;
10730*6777b538SAndroid Build Coastguard Worker }
10731*6777b538SAndroid Build Coastguard Worker
10732*6777b538SAndroid Build Coastguard Worker if (op->ch2 != -1)
10733*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetFilter(ctxt, set, op->ch2, minPos, maxPos, hasNsNodes);
10734*6777b538SAndroid Build Coastguard Worker }
10735*6777b538SAndroid Build Coastguard Worker
10736*6777b538SAndroid Build Coastguard Worker static int
xmlXPathIsPositionalPredicate(xmlXPathParserContextPtr ctxt,xmlXPathStepOpPtr op,int * maxPos)10737*6777b538SAndroid Build Coastguard Worker xmlXPathIsPositionalPredicate(xmlXPathParserContextPtr ctxt,
10738*6777b538SAndroid Build Coastguard Worker xmlXPathStepOpPtr op,
10739*6777b538SAndroid Build Coastguard Worker int *maxPos)
10740*6777b538SAndroid Build Coastguard Worker {
10741*6777b538SAndroid Build Coastguard Worker
10742*6777b538SAndroid Build Coastguard Worker xmlXPathStepOpPtr exprOp;
10743*6777b538SAndroid Build Coastguard Worker
10744*6777b538SAndroid Build Coastguard Worker /*
10745*6777b538SAndroid Build Coastguard Worker * BIG NOTE: This is not intended for XPATH_OP_FILTER yet!
10746*6777b538SAndroid Build Coastguard Worker */
10747*6777b538SAndroid Build Coastguard Worker
10748*6777b538SAndroid Build Coastguard Worker /*
10749*6777b538SAndroid Build Coastguard Worker * If not -1, then ch1 will point to:
10750*6777b538SAndroid Build Coastguard Worker * 1) For predicates (XPATH_OP_PREDICATE):
10751*6777b538SAndroid Build Coastguard Worker * - an inner predicate operator
10752*6777b538SAndroid Build Coastguard Worker * 2) For filters (XPATH_OP_FILTER):
10753*6777b538SAndroid Build Coastguard Worker * - an inner filter operator OR
10754*6777b538SAndroid Build Coastguard Worker * - an expression selecting the node set.
10755*6777b538SAndroid Build Coastguard Worker * E.g. "key('a', 'b')" or "(//foo | //bar)".
10756*6777b538SAndroid Build Coastguard Worker */
10757*6777b538SAndroid Build Coastguard Worker if ((op->op != XPATH_OP_PREDICATE) && (op->op != XPATH_OP_FILTER))
10758*6777b538SAndroid Build Coastguard Worker return(0);
10759*6777b538SAndroid Build Coastguard Worker
10760*6777b538SAndroid Build Coastguard Worker if (op->ch2 != -1) {
10761*6777b538SAndroid Build Coastguard Worker exprOp = &ctxt->comp->steps[op->ch2];
10762*6777b538SAndroid Build Coastguard Worker } else
10763*6777b538SAndroid Build Coastguard Worker return(0);
10764*6777b538SAndroid Build Coastguard Worker
10765*6777b538SAndroid Build Coastguard Worker if ((exprOp != NULL) &&
10766*6777b538SAndroid Build Coastguard Worker (exprOp->op == XPATH_OP_VALUE) &&
10767*6777b538SAndroid Build Coastguard Worker (exprOp->value4 != NULL) &&
10768*6777b538SAndroid Build Coastguard Worker (((xmlXPathObjectPtr) exprOp->value4)->type == XPATH_NUMBER))
10769*6777b538SAndroid Build Coastguard Worker {
10770*6777b538SAndroid Build Coastguard Worker double floatval = ((xmlXPathObjectPtr) exprOp->value4)->floatval;
10771*6777b538SAndroid Build Coastguard Worker
10772*6777b538SAndroid Build Coastguard Worker /*
10773*6777b538SAndroid Build Coastguard Worker * We have a "[n]" predicate here.
10774*6777b538SAndroid Build Coastguard Worker * TODO: Unfortunately this simplistic test here is not
10775*6777b538SAndroid Build Coastguard Worker * able to detect a position() predicate in compound
10776*6777b538SAndroid Build Coastguard Worker * expressions like "[@attr = 'a" and position() = 1],
10777*6777b538SAndroid Build Coastguard Worker * and even not the usage of position() in
10778*6777b538SAndroid Build Coastguard Worker * "[position() = 1]"; thus - obviously - a position-range,
10779*6777b538SAndroid Build Coastguard Worker * like it "[position() < 5]", is also not detected.
10780*6777b538SAndroid Build Coastguard Worker * Maybe we could rewrite the AST to ease the optimization.
10781*6777b538SAndroid Build Coastguard Worker */
10782*6777b538SAndroid Build Coastguard Worker
10783*6777b538SAndroid Build Coastguard Worker if ((floatval > INT_MIN) && (floatval < INT_MAX)) {
10784*6777b538SAndroid Build Coastguard Worker *maxPos = (int) floatval;
10785*6777b538SAndroid Build Coastguard Worker if (floatval == (double) *maxPos)
10786*6777b538SAndroid Build Coastguard Worker return(1);
10787*6777b538SAndroid Build Coastguard Worker }
10788*6777b538SAndroid Build Coastguard Worker }
10789*6777b538SAndroid Build Coastguard Worker return(0);
10790*6777b538SAndroid Build Coastguard Worker }
10791*6777b538SAndroid Build Coastguard Worker
10792*6777b538SAndroid Build Coastguard Worker static int
xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,xmlXPathStepOpPtr op,xmlNodePtr * first,xmlNodePtr * last,int toBool)10793*6777b538SAndroid Build Coastguard Worker xmlXPathNodeCollectAndTest(xmlXPathParserContextPtr ctxt,
10794*6777b538SAndroid Build Coastguard Worker xmlXPathStepOpPtr op,
10795*6777b538SAndroid Build Coastguard Worker xmlNodePtr * first, xmlNodePtr * last,
10796*6777b538SAndroid Build Coastguard Worker int toBool)
10797*6777b538SAndroid Build Coastguard Worker {
10798*6777b538SAndroid Build Coastguard Worker
10799*6777b538SAndroid Build Coastguard Worker #define XP_TEST_HIT \
10800*6777b538SAndroid Build Coastguard Worker if (hasAxisRange != 0) { \
10801*6777b538SAndroid Build Coastguard Worker if (++pos == maxPos) { \
10802*6777b538SAndroid Build Coastguard Worker if (addNode(seq, cur) < 0) \
10803*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt); \
10804*6777b538SAndroid Build Coastguard Worker goto axis_range_end; } \
10805*6777b538SAndroid Build Coastguard Worker } else { \
10806*6777b538SAndroid Build Coastguard Worker if (addNode(seq, cur) < 0) \
10807*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt); \
10808*6777b538SAndroid Build Coastguard Worker if (breakOnFirstHit) goto first_hit; }
10809*6777b538SAndroid Build Coastguard Worker
10810*6777b538SAndroid Build Coastguard Worker #define XP_TEST_HIT_NS \
10811*6777b538SAndroid Build Coastguard Worker if (hasAxisRange != 0) { \
10812*6777b538SAndroid Build Coastguard Worker if (++pos == maxPos) { \
10813*6777b538SAndroid Build Coastguard Worker hasNsNodes = 1; \
10814*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur) < 0) \
10815*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt); \
10816*6777b538SAndroid Build Coastguard Worker goto axis_range_end; } \
10817*6777b538SAndroid Build Coastguard Worker } else { \
10818*6777b538SAndroid Build Coastguard Worker hasNsNodes = 1; \
10819*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetAddNs(seq, xpctxt->node, (xmlNsPtr) cur) < 0) \
10820*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt); \
10821*6777b538SAndroid Build Coastguard Worker if (breakOnFirstHit) goto first_hit; }
10822*6777b538SAndroid Build Coastguard Worker
10823*6777b538SAndroid Build Coastguard Worker xmlXPathAxisVal axis = (xmlXPathAxisVal) op->value;
10824*6777b538SAndroid Build Coastguard Worker xmlXPathTestVal test = (xmlXPathTestVal) op->value2;
10825*6777b538SAndroid Build Coastguard Worker xmlXPathTypeVal type = (xmlXPathTypeVal) op->value3;
10826*6777b538SAndroid Build Coastguard Worker const xmlChar *prefix = op->value4;
10827*6777b538SAndroid Build Coastguard Worker const xmlChar *name = op->value5;
10828*6777b538SAndroid Build Coastguard Worker const xmlChar *URI = NULL;
10829*6777b538SAndroid Build Coastguard Worker
10830*6777b538SAndroid Build Coastguard Worker int total = 0, hasNsNodes = 0;
10831*6777b538SAndroid Build Coastguard Worker /* The popped object holding the context nodes */
10832*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr obj;
10833*6777b538SAndroid Build Coastguard Worker /* The set of context nodes for the node tests */
10834*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr contextSeq;
10835*6777b538SAndroid Build Coastguard Worker int contextIdx;
10836*6777b538SAndroid Build Coastguard Worker xmlNodePtr contextNode;
10837*6777b538SAndroid Build Coastguard Worker /* The final resulting node set wrt to all context nodes */
10838*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr outSeq;
10839*6777b538SAndroid Build Coastguard Worker /*
10840*6777b538SAndroid Build Coastguard Worker * The temporary resulting node set wrt 1 context node.
10841*6777b538SAndroid Build Coastguard Worker * Used to feed predicate evaluation.
10842*6777b538SAndroid Build Coastguard Worker */
10843*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr seq;
10844*6777b538SAndroid Build Coastguard Worker xmlNodePtr cur;
10845*6777b538SAndroid Build Coastguard Worker /* First predicate operator */
10846*6777b538SAndroid Build Coastguard Worker xmlXPathStepOpPtr predOp;
10847*6777b538SAndroid Build Coastguard Worker int maxPos; /* The requested position() (when a "[n]" predicate) */
10848*6777b538SAndroid Build Coastguard Worker int hasPredicateRange, hasAxisRange, pos;
10849*6777b538SAndroid Build Coastguard Worker int breakOnFirstHit;
10850*6777b538SAndroid Build Coastguard Worker
10851*6777b538SAndroid Build Coastguard Worker xmlXPathTraversalFunction next = NULL;
10852*6777b538SAndroid Build Coastguard Worker int (*addNode) (xmlNodeSetPtr, xmlNodePtr);
10853*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetMergeFunction mergeAndClear;
10854*6777b538SAndroid Build Coastguard Worker xmlNodePtr oldContextNode;
10855*6777b538SAndroid Build Coastguard Worker xmlXPathContextPtr xpctxt = ctxt->context;
10856*6777b538SAndroid Build Coastguard Worker
10857*6777b538SAndroid Build Coastguard Worker
10858*6777b538SAndroid Build Coastguard Worker CHECK_TYPE0(XPATH_NODESET);
10859*6777b538SAndroid Build Coastguard Worker obj = valuePop(ctxt);
10860*6777b538SAndroid Build Coastguard Worker /*
10861*6777b538SAndroid Build Coastguard Worker * Setup namespaces.
10862*6777b538SAndroid Build Coastguard Worker */
10863*6777b538SAndroid Build Coastguard Worker if (prefix != NULL) {
10864*6777b538SAndroid Build Coastguard Worker URI = xmlXPathNsLookup(xpctxt, prefix);
10865*6777b538SAndroid Build Coastguard Worker if (URI == NULL) {
10866*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(xpctxt, obj);
10867*6777b538SAndroid Build Coastguard Worker XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
10868*6777b538SAndroid Build Coastguard Worker }
10869*6777b538SAndroid Build Coastguard Worker }
10870*6777b538SAndroid Build Coastguard Worker /*
10871*6777b538SAndroid Build Coastguard Worker * Setup axis.
10872*6777b538SAndroid Build Coastguard Worker *
10873*6777b538SAndroid Build Coastguard Worker * MAYBE FUTURE TODO: merging optimizations:
10874*6777b538SAndroid Build Coastguard Worker * - If the nodes to be traversed wrt to the initial nodes and
10875*6777b538SAndroid Build Coastguard Worker * the current axis cannot overlap, then we could avoid searching
10876*6777b538SAndroid Build Coastguard Worker * for duplicates during the merge.
10877*6777b538SAndroid Build Coastguard Worker * But the question is how/when to evaluate if they cannot overlap.
10878*6777b538SAndroid Build Coastguard Worker * Example: if we know that for two initial nodes, the one is
10879*6777b538SAndroid Build Coastguard Worker * not in the ancestor-or-self axis of the other, then we could safely
10880*6777b538SAndroid Build Coastguard Worker * avoid a duplicate-aware merge, if the axis to be traversed is e.g.
10881*6777b538SAndroid Build Coastguard Worker * the descendant-or-self axis.
10882*6777b538SAndroid Build Coastguard Worker */
10883*6777b538SAndroid Build Coastguard Worker mergeAndClear = xmlXPathNodeSetMergeAndClear;
10884*6777b538SAndroid Build Coastguard Worker switch (axis) {
10885*6777b538SAndroid Build Coastguard Worker case AXIS_ANCESTOR:
10886*6777b538SAndroid Build Coastguard Worker first = NULL;
10887*6777b538SAndroid Build Coastguard Worker next = xmlXPathNextAncestor;
10888*6777b538SAndroid Build Coastguard Worker break;
10889*6777b538SAndroid Build Coastguard Worker case AXIS_ANCESTOR_OR_SELF:
10890*6777b538SAndroid Build Coastguard Worker first = NULL;
10891*6777b538SAndroid Build Coastguard Worker next = xmlXPathNextAncestorOrSelf;
10892*6777b538SAndroid Build Coastguard Worker break;
10893*6777b538SAndroid Build Coastguard Worker case AXIS_ATTRIBUTE:
10894*6777b538SAndroid Build Coastguard Worker first = NULL;
10895*6777b538SAndroid Build Coastguard Worker last = NULL;
10896*6777b538SAndroid Build Coastguard Worker next = xmlXPathNextAttribute;
10897*6777b538SAndroid Build Coastguard Worker mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls;
10898*6777b538SAndroid Build Coastguard Worker break;
10899*6777b538SAndroid Build Coastguard Worker case AXIS_CHILD:
10900*6777b538SAndroid Build Coastguard Worker last = NULL;
10901*6777b538SAndroid Build Coastguard Worker if (((test == NODE_TEST_NAME) || (test == NODE_TEST_ALL)) &&
10902*6777b538SAndroid Build Coastguard Worker (type == NODE_TYPE_NODE))
10903*6777b538SAndroid Build Coastguard Worker {
10904*6777b538SAndroid Build Coastguard Worker /*
10905*6777b538SAndroid Build Coastguard Worker * Optimization if an element node type is 'element'.
10906*6777b538SAndroid Build Coastguard Worker */
10907*6777b538SAndroid Build Coastguard Worker next = xmlXPathNextChildElement;
10908*6777b538SAndroid Build Coastguard Worker } else
10909*6777b538SAndroid Build Coastguard Worker next = xmlXPathNextChild;
10910*6777b538SAndroid Build Coastguard Worker mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls;
10911*6777b538SAndroid Build Coastguard Worker break;
10912*6777b538SAndroid Build Coastguard Worker case AXIS_DESCENDANT:
10913*6777b538SAndroid Build Coastguard Worker last = NULL;
10914*6777b538SAndroid Build Coastguard Worker next = xmlXPathNextDescendant;
10915*6777b538SAndroid Build Coastguard Worker break;
10916*6777b538SAndroid Build Coastguard Worker case AXIS_DESCENDANT_OR_SELF:
10917*6777b538SAndroid Build Coastguard Worker last = NULL;
10918*6777b538SAndroid Build Coastguard Worker next = xmlXPathNextDescendantOrSelf;
10919*6777b538SAndroid Build Coastguard Worker break;
10920*6777b538SAndroid Build Coastguard Worker case AXIS_FOLLOWING:
10921*6777b538SAndroid Build Coastguard Worker last = NULL;
10922*6777b538SAndroid Build Coastguard Worker next = xmlXPathNextFollowing;
10923*6777b538SAndroid Build Coastguard Worker break;
10924*6777b538SAndroid Build Coastguard Worker case AXIS_FOLLOWING_SIBLING:
10925*6777b538SAndroid Build Coastguard Worker last = NULL;
10926*6777b538SAndroid Build Coastguard Worker next = xmlXPathNextFollowingSibling;
10927*6777b538SAndroid Build Coastguard Worker break;
10928*6777b538SAndroid Build Coastguard Worker case AXIS_NAMESPACE:
10929*6777b538SAndroid Build Coastguard Worker first = NULL;
10930*6777b538SAndroid Build Coastguard Worker last = NULL;
10931*6777b538SAndroid Build Coastguard Worker next = (xmlXPathTraversalFunction) xmlXPathNextNamespace;
10932*6777b538SAndroid Build Coastguard Worker mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls;
10933*6777b538SAndroid Build Coastguard Worker break;
10934*6777b538SAndroid Build Coastguard Worker case AXIS_PARENT:
10935*6777b538SAndroid Build Coastguard Worker first = NULL;
10936*6777b538SAndroid Build Coastguard Worker next = xmlXPathNextParent;
10937*6777b538SAndroid Build Coastguard Worker break;
10938*6777b538SAndroid Build Coastguard Worker case AXIS_PRECEDING:
10939*6777b538SAndroid Build Coastguard Worker first = NULL;
10940*6777b538SAndroid Build Coastguard Worker next = xmlXPathNextPrecedingInternal;
10941*6777b538SAndroid Build Coastguard Worker break;
10942*6777b538SAndroid Build Coastguard Worker case AXIS_PRECEDING_SIBLING:
10943*6777b538SAndroid Build Coastguard Worker first = NULL;
10944*6777b538SAndroid Build Coastguard Worker next = xmlXPathNextPrecedingSibling;
10945*6777b538SAndroid Build Coastguard Worker break;
10946*6777b538SAndroid Build Coastguard Worker case AXIS_SELF:
10947*6777b538SAndroid Build Coastguard Worker first = NULL;
10948*6777b538SAndroid Build Coastguard Worker last = NULL;
10949*6777b538SAndroid Build Coastguard Worker next = xmlXPathNextSelf;
10950*6777b538SAndroid Build Coastguard Worker mergeAndClear = xmlXPathNodeSetMergeAndClearNoDupls;
10951*6777b538SAndroid Build Coastguard Worker break;
10952*6777b538SAndroid Build Coastguard Worker }
10953*6777b538SAndroid Build Coastguard Worker
10954*6777b538SAndroid Build Coastguard Worker if (next == NULL) {
10955*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(xpctxt, obj);
10956*6777b538SAndroid Build Coastguard Worker return(0);
10957*6777b538SAndroid Build Coastguard Worker }
10958*6777b538SAndroid Build Coastguard Worker contextSeq = obj->nodesetval;
10959*6777b538SAndroid Build Coastguard Worker if ((contextSeq == NULL) || (contextSeq->nodeNr <= 0)) {
10960*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, obj);
10961*6777b538SAndroid Build Coastguard Worker return(0);
10962*6777b538SAndroid Build Coastguard Worker }
10963*6777b538SAndroid Build Coastguard Worker /*
10964*6777b538SAndroid Build Coastguard Worker * Predicate optimization ---------------------------------------------
10965*6777b538SAndroid Build Coastguard Worker * If this step has a last predicate, which contains a position(),
10966*6777b538SAndroid Build Coastguard Worker * then we'll optimize (although not exactly "position()", but only
10967*6777b538SAndroid Build Coastguard Worker * the short-hand form, i.e., "[n]".
10968*6777b538SAndroid Build Coastguard Worker *
10969*6777b538SAndroid Build Coastguard Worker * Example - expression "/foo[parent::bar][1]":
10970*6777b538SAndroid Build Coastguard Worker *
10971*6777b538SAndroid Build Coastguard Worker * COLLECT 'child' 'name' 'node' foo -- op (we are here)
10972*6777b538SAndroid Build Coastguard Worker * ROOT -- op->ch1
10973*6777b538SAndroid Build Coastguard Worker * PREDICATE -- op->ch2 (predOp)
10974*6777b538SAndroid Build Coastguard Worker * PREDICATE -- predOp->ch1 = [parent::bar]
10975*6777b538SAndroid Build Coastguard Worker * SORT
10976*6777b538SAndroid Build Coastguard Worker * COLLECT 'parent' 'name' 'node' bar
10977*6777b538SAndroid Build Coastguard Worker * NODE
10978*6777b538SAndroid Build Coastguard Worker * ELEM Object is a number : 1 -- predOp->ch2 = [1]
10979*6777b538SAndroid Build Coastguard Worker *
10980*6777b538SAndroid Build Coastguard Worker */
10981*6777b538SAndroid Build Coastguard Worker maxPos = 0;
10982*6777b538SAndroid Build Coastguard Worker predOp = NULL;
10983*6777b538SAndroid Build Coastguard Worker hasPredicateRange = 0;
10984*6777b538SAndroid Build Coastguard Worker hasAxisRange = 0;
10985*6777b538SAndroid Build Coastguard Worker if (op->ch2 != -1) {
10986*6777b538SAndroid Build Coastguard Worker /*
10987*6777b538SAndroid Build Coastguard Worker * There's at least one predicate. 16 == XPATH_OP_PREDICATE
10988*6777b538SAndroid Build Coastguard Worker */
10989*6777b538SAndroid Build Coastguard Worker predOp = &ctxt->comp->steps[op->ch2];
10990*6777b538SAndroid Build Coastguard Worker if (xmlXPathIsPositionalPredicate(ctxt, predOp, &maxPos)) {
10991*6777b538SAndroid Build Coastguard Worker if (predOp->ch1 != -1) {
10992*6777b538SAndroid Build Coastguard Worker /*
10993*6777b538SAndroid Build Coastguard Worker * Use the next inner predicate operator.
10994*6777b538SAndroid Build Coastguard Worker */
10995*6777b538SAndroid Build Coastguard Worker predOp = &ctxt->comp->steps[predOp->ch1];
10996*6777b538SAndroid Build Coastguard Worker hasPredicateRange = 1;
10997*6777b538SAndroid Build Coastguard Worker } else {
10998*6777b538SAndroid Build Coastguard Worker /*
10999*6777b538SAndroid Build Coastguard Worker * There's no other predicate than the [n] predicate.
11000*6777b538SAndroid Build Coastguard Worker */
11001*6777b538SAndroid Build Coastguard Worker predOp = NULL;
11002*6777b538SAndroid Build Coastguard Worker hasAxisRange = 1;
11003*6777b538SAndroid Build Coastguard Worker }
11004*6777b538SAndroid Build Coastguard Worker }
11005*6777b538SAndroid Build Coastguard Worker }
11006*6777b538SAndroid Build Coastguard Worker breakOnFirstHit = ((toBool) && (predOp == NULL)) ? 1 : 0;
11007*6777b538SAndroid Build Coastguard Worker /*
11008*6777b538SAndroid Build Coastguard Worker * Axis traversal -----------------------------------------------------
11009*6777b538SAndroid Build Coastguard Worker */
11010*6777b538SAndroid Build Coastguard Worker /*
11011*6777b538SAndroid Build Coastguard Worker * 2.3 Node Tests
11012*6777b538SAndroid Build Coastguard Worker * - For the attribute axis, the principal node type is attribute.
11013*6777b538SAndroid Build Coastguard Worker * - For the namespace axis, the principal node type is namespace.
11014*6777b538SAndroid Build Coastguard Worker * - For other axes, the principal node type is element.
11015*6777b538SAndroid Build Coastguard Worker *
11016*6777b538SAndroid Build Coastguard Worker * A node test * is true for any node of the
11017*6777b538SAndroid Build Coastguard Worker * principal node type. For example, child::* will
11018*6777b538SAndroid Build Coastguard Worker * select all element children of the context node
11019*6777b538SAndroid Build Coastguard Worker */
11020*6777b538SAndroid Build Coastguard Worker oldContextNode = xpctxt->node;
11021*6777b538SAndroid Build Coastguard Worker addNode = xmlXPathNodeSetAddUnique;
11022*6777b538SAndroid Build Coastguard Worker outSeq = NULL;
11023*6777b538SAndroid Build Coastguard Worker seq = NULL;
11024*6777b538SAndroid Build Coastguard Worker contextNode = NULL;
11025*6777b538SAndroid Build Coastguard Worker contextIdx = 0;
11026*6777b538SAndroid Build Coastguard Worker
11027*6777b538SAndroid Build Coastguard Worker
11028*6777b538SAndroid Build Coastguard Worker while (((contextIdx < contextSeq->nodeNr) || (contextNode != NULL)) &&
11029*6777b538SAndroid Build Coastguard Worker (ctxt->error == XPATH_EXPRESSION_OK)) {
11030*6777b538SAndroid Build Coastguard Worker xpctxt->node = contextSeq->nodeTab[contextIdx++];
11031*6777b538SAndroid Build Coastguard Worker
11032*6777b538SAndroid Build Coastguard Worker if (seq == NULL) {
11033*6777b538SAndroid Build Coastguard Worker seq = xmlXPathNodeSetCreate(NULL);
11034*6777b538SAndroid Build Coastguard Worker if (seq == NULL) {
11035*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
11036*6777b538SAndroid Build Coastguard Worker total = 0;
11037*6777b538SAndroid Build Coastguard Worker goto error;
11038*6777b538SAndroid Build Coastguard Worker }
11039*6777b538SAndroid Build Coastguard Worker }
11040*6777b538SAndroid Build Coastguard Worker /*
11041*6777b538SAndroid Build Coastguard Worker * Traverse the axis and test the nodes.
11042*6777b538SAndroid Build Coastguard Worker */
11043*6777b538SAndroid Build Coastguard Worker pos = 0;
11044*6777b538SAndroid Build Coastguard Worker cur = NULL;
11045*6777b538SAndroid Build Coastguard Worker hasNsNodes = 0;
11046*6777b538SAndroid Build Coastguard Worker do {
11047*6777b538SAndroid Build Coastguard Worker if (OP_LIMIT_EXCEEDED(ctxt, 1))
11048*6777b538SAndroid Build Coastguard Worker goto error;
11049*6777b538SAndroid Build Coastguard Worker
11050*6777b538SAndroid Build Coastguard Worker cur = next(ctxt, cur);
11051*6777b538SAndroid Build Coastguard Worker if (cur == NULL)
11052*6777b538SAndroid Build Coastguard Worker break;
11053*6777b538SAndroid Build Coastguard Worker
11054*6777b538SAndroid Build Coastguard Worker /*
11055*6777b538SAndroid Build Coastguard Worker * QUESTION TODO: What does the "first" and "last" stuff do?
11056*6777b538SAndroid Build Coastguard Worker */
11057*6777b538SAndroid Build Coastguard Worker if ((first != NULL) && (*first != NULL)) {
11058*6777b538SAndroid Build Coastguard Worker if (*first == cur)
11059*6777b538SAndroid Build Coastguard Worker break;
11060*6777b538SAndroid Build Coastguard Worker if (((total % 256) == 0) &&
11061*6777b538SAndroid Build Coastguard Worker #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
11062*6777b538SAndroid Build Coastguard Worker (xmlXPathCmpNodesExt(*first, cur) >= 0))
11063*6777b538SAndroid Build Coastguard Worker #else
11064*6777b538SAndroid Build Coastguard Worker (xmlXPathCmpNodes(*first, cur) >= 0))
11065*6777b538SAndroid Build Coastguard Worker #endif
11066*6777b538SAndroid Build Coastguard Worker {
11067*6777b538SAndroid Build Coastguard Worker break;
11068*6777b538SAndroid Build Coastguard Worker }
11069*6777b538SAndroid Build Coastguard Worker }
11070*6777b538SAndroid Build Coastguard Worker if ((last != NULL) && (*last != NULL)) {
11071*6777b538SAndroid Build Coastguard Worker if (*last == cur)
11072*6777b538SAndroid Build Coastguard Worker break;
11073*6777b538SAndroid Build Coastguard Worker if (((total % 256) == 0) &&
11074*6777b538SAndroid Build Coastguard Worker #ifdef XP_OPTIMIZED_NON_ELEM_COMPARISON
11075*6777b538SAndroid Build Coastguard Worker (xmlXPathCmpNodesExt(cur, *last) >= 0))
11076*6777b538SAndroid Build Coastguard Worker #else
11077*6777b538SAndroid Build Coastguard Worker (xmlXPathCmpNodes(cur, *last) >= 0))
11078*6777b538SAndroid Build Coastguard Worker #endif
11079*6777b538SAndroid Build Coastguard Worker {
11080*6777b538SAndroid Build Coastguard Worker break;
11081*6777b538SAndroid Build Coastguard Worker }
11082*6777b538SAndroid Build Coastguard Worker }
11083*6777b538SAndroid Build Coastguard Worker
11084*6777b538SAndroid Build Coastguard Worker total++;
11085*6777b538SAndroid Build Coastguard Worker
11086*6777b538SAndroid Build Coastguard Worker switch (test) {
11087*6777b538SAndroid Build Coastguard Worker case NODE_TEST_NONE:
11088*6777b538SAndroid Build Coastguard Worker total = 0;
11089*6777b538SAndroid Build Coastguard Worker goto error;
11090*6777b538SAndroid Build Coastguard Worker case NODE_TEST_TYPE:
11091*6777b538SAndroid Build Coastguard Worker if (type == NODE_TYPE_NODE) {
11092*6777b538SAndroid Build Coastguard Worker switch (cur->type) {
11093*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_NODE:
11094*6777b538SAndroid Build Coastguard Worker case XML_HTML_DOCUMENT_NODE:
11095*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
11096*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE:
11097*6777b538SAndroid Build Coastguard Worker case XML_PI_NODE:
11098*6777b538SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
11099*6777b538SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
11100*6777b538SAndroid Build Coastguard Worker case XML_TEXT_NODE:
11101*6777b538SAndroid Build Coastguard Worker XP_TEST_HIT
11102*6777b538SAndroid Build Coastguard Worker break;
11103*6777b538SAndroid Build Coastguard Worker case XML_NAMESPACE_DECL: {
11104*6777b538SAndroid Build Coastguard Worker if (axis == AXIS_NAMESPACE) {
11105*6777b538SAndroid Build Coastguard Worker XP_TEST_HIT_NS
11106*6777b538SAndroid Build Coastguard Worker } else {
11107*6777b538SAndroid Build Coastguard Worker hasNsNodes = 1;
11108*6777b538SAndroid Build Coastguard Worker XP_TEST_HIT
11109*6777b538SAndroid Build Coastguard Worker }
11110*6777b538SAndroid Build Coastguard Worker break;
11111*6777b538SAndroid Build Coastguard Worker }
11112*6777b538SAndroid Build Coastguard Worker default:
11113*6777b538SAndroid Build Coastguard Worker break;
11114*6777b538SAndroid Build Coastguard Worker }
11115*6777b538SAndroid Build Coastguard Worker } else if (cur->type == (xmlElementType) type) {
11116*6777b538SAndroid Build Coastguard Worker if (cur->type == XML_NAMESPACE_DECL)
11117*6777b538SAndroid Build Coastguard Worker XP_TEST_HIT_NS
11118*6777b538SAndroid Build Coastguard Worker else
11119*6777b538SAndroid Build Coastguard Worker XP_TEST_HIT
11120*6777b538SAndroid Build Coastguard Worker } else if ((type == NODE_TYPE_TEXT) &&
11121*6777b538SAndroid Build Coastguard Worker (cur->type == XML_CDATA_SECTION_NODE))
11122*6777b538SAndroid Build Coastguard Worker {
11123*6777b538SAndroid Build Coastguard Worker XP_TEST_HIT
11124*6777b538SAndroid Build Coastguard Worker }
11125*6777b538SAndroid Build Coastguard Worker break;
11126*6777b538SAndroid Build Coastguard Worker case NODE_TEST_PI:
11127*6777b538SAndroid Build Coastguard Worker if ((cur->type == XML_PI_NODE) &&
11128*6777b538SAndroid Build Coastguard Worker ((name == NULL) || xmlStrEqual(name, cur->name)))
11129*6777b538SAndroid Build Coastguard Worker {
11130*6777b538SAndroid Build Coastguard Worker XP_TEST_HIT
11131*6777b538SAndroid Build Coastguard Worker }
11132*6777b538SAndroid Build Coastguard Worker break;
11133*6777b538SAndroid Build Coastguard Worker case NODE_TEST_ALL:
11134*6777b538SAndroid Build Coastguard Worker if (axis == AXIS_ATTRIBUTE) {
11135*6777b538SAndroid Build Coastguard Worker if (cur->type == XML_ATTRIBUTE_NODE)
11136*6777b538SAndroid Build Coastguard Worker {
11137*6777b538SAndroid Build Coastguard Worker if (prefix == NULL)
11138*6777b538SAndroid Build Coastguard Worker {
11139*6777b538SAndroid Build Coastguard Worker XP_TEST_HIT
11140*6777b538SAndroid Build Coastguard Worker } else if ((cur->ns != NULL) &&
11141*6777b538SAndroid Build Coastguard Worker (xmlStrEqual(URI, cur->ns->href)))
11142*6777b538SAndroid Build Coastguard Worker {
11143*6777b538SAndroid Build Coastguard Worker XP_TEST_HIT
11144*6777b538SAndroid Build Coastguard Worker }
11145*6777b538SAndroid Build Coastguard Worker }
11146*6777b538SAndroid Build Coastguard Worker } else if (axis == AXIS_NAMESPACE) {
11147*6777b538SAndroid Build Coastguard Worker if (cur->type == XML_NAMESPACE_DECL)
11148*6777b538SAndroid Build Coastguard Worker {
11149*6777b538SAndroid Build Coastguard Worker XP_TEST_HIT_NS
11150*6777b538SAndroid Build Coastguard Worker }
11151*6777b538SAndroid Build Coastguard Worker } else {
11152*6777b538SAndroid Build Coastguard Worker if (cur->type == XML_ELEMENT_NODE) {
11153*6777b538SAndroid Build Coastguard Worker if (prefix == NULL)
11154*6777b538SAndroid Build Coastguard Worker {
11155*6777b538SAndroid Build Coastguard Worker XP_TEST_HIT
11156*6777b538SAndroid Build Coastguard Worker
11157*6777b538SAndroid Build Coastguard Worker } else if ((cur->ns != NULL) &&
11158*6777b538SAndroid Build Coastguard Worker (xmlStrEqual(URI, cur->ns->href)))
11159*6777b538SAndroid Build Coastguard Worker {
11160*6777b538SAndroid Build Coastguard Worker XP_TEST_HIT
11161*6777b538SAndroid Build Coastguard Worker }
11162*6777b538SAndroid Build Coastguard Worker }
11163*6777b538SAndroid Build Coastguard Worker }
11164*6777b538SAndroid Build Coastguard Worker break;
11165*6777b538SAndroid Build Coastguard Worker case NODE_TEST_NS:{
11166*6777b538SAndroid Build Coastguard Worker /* TODO */
11167*6777b538SAndroid Build Coastguard Worker break;
11168*6777b538SAndroid Build Coastguard Worker }
11169*6777b538SAndroid Build Coastguard Worker case NODE_TEST_NAME:
11170*6777b538SAndroid Build Coastguard Worker if (axis == AXIS_ATTRIBUTE) {
11171*6777b538SAndroid Build Coastguard Worker if (cur->type != XML_ATTRIBUTE_NODE)
11172*6777b538SAndroid Build Coastguard Worker break;
11173*6777b538SAndroid Build Coastguard Worker } else if (axis == AXIS_NAMESPACE) {
11174*6777b538SAndroid Build Coastguard Worker if (cur->type != XML_NAMESPACE_DECL)
11175*6777b538SAndroid Build Coastguard Worker break;
11176*6777b538SAndroid Build Coastguard Worker } else {
11177*6777b538SAndroid Build Coastguard Worker if (cur->type != XML_ELEMENT_NODE)
11178*6777b538SAndroid Build Coastguard Worker break;
11179*6777b538SAndroid Build Coastguard Worker }
11180*6777b538SAndroid Build Coastguard Worker switch (cur->type) {
11181*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
11182*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(name, cur->name)) {
11183*6777b538SAndroid Build Coastguard Worker if (prefix == NULL) {
11184*6777b538SAndroid Build Coastguard Worker if (cur->ns == NULL)
11185*6777b538SAndroid Build Coastguard Worker {
11186*6777b538SAndroid Build Coastguard Worker XP_TEST_HIT
11187*6777b538SAndroid Build Coastguard Worker }
11188*6777b538SAndroid Build Coastguard Worker } else {
11189*6777b538SAndroid Build Coastguard Worker if ((cur->ns != NULL) &&
11190*6777b538SAndroid Build Coastguard Worker (xmlStrEqual(URI, cur->ns->href)))
11191*6777b538SAndroid Build Coastguard Worker {
11192*6777b538SAndroid Build Coastguard Worker XP_TEST_HIT
11193*6777b538SAndroid Build Coastguard Worker }
11194*6777b538SAndroid Build Coastguard Worker }
11195*6777b538SAndroid Build Coastguard Worker }
11196*6777b538SAndroid Build Coastguard Worker break;
11197*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE:{
11198*6777b538SAndroid Build Coastguard Worker xmlAttrPtr attr = (xmlAttrPtr) cur;
11199*6777b538SAndroid Build Coastguard Worker
11200*6777b538SAndroid Build Coastguard Worker if (xmlStrEqual(name, attr->name)) {
11201*6777b538SAndroid Build Coastguard Worker if (prefix == NULL) {
11202*6777b538SAndroid Build Coastguard Worker if ((attr->ns == NULL) ||
11203*6777b538SAndroid Build Coastguard Worker (attr->ns->prefix == NULL))
11204*6777b538SAndroid Build Coastguard Worker {
11205*6777b538SAndroid Build Coastguard Worker XP_TEST_HIT
11206*6777b538SAndroid Build Coastguard Worker }
11207*6777b538SAndroid Build Coastguard Worker } else {
11208*6777b538SAndroid Build Coastguard Worker if ((attr->ns != NULL) &&
11209*6777b538SAndroid Build Coastguard Worker (xmlStrEqual(URI,
11210*6777b538SAndroid Build Coastguard Worker attr->ns->href)))
11211*6777b538SAndroid Build Coastguard Worker {
11212*6777b538SAndroid Build Coastguard Worker XP_TEST_HIT
11213*6777b538SAndroid Build Coastguard Worker }
11214*6777b538SAndroid Build Coastguard Worker }
11215*6777b538SAndroid Build Coastguard Worker }
11216*6777b538SAndroid Build Coastguard Worker break;
11217*6777b538SAndroid Build Coastguard Worker }
11218*6777b538SAndroid Build Coastguard Worker case XML_NAMESPACE_DECL:
11219*6777b538SAndroid Build Coastguard Worker if (cur->type == XML_NAMESPACE_DECL) {
11220*6777b538SAndroid Build Coastguard Worker xmlNsPtr ns = (xmlNsPtr) cur;
11221*6777b538SAndroid Build Coastguard Worker
11222*6777b538SAndroid Build Coastguard Worker if ((ns->prefix != NULL) && (name != NULL)
11223*6777b538SAndroid Build Coastguard Worker && (xmlStrEqual(ns->prefix, name)))
11224*6777b538SAndroid Build Coastguard Worker {
11225*6777b538SAndroid Build Coastguard Worker XP_TEST_HIT_NS
11226*6777b538SAndroid Build Coastguard Worker }
11227*6777b538SAndroid Build Coastguard Worker }
11228*6777b538SAndroid Build Coastguard Worker break;
11229*6777b538SAndroid Build Coastguard Worker default:
11230*6777b538SAndroid Build Coastguard Worker break;
11231*6777b538SAndroid Build Coastguard Worker }
11232*6777b538SAndroid Build Coastguard Worker break;
11233*6777b538SAndroid Build Coastguard Worker } /* switch(test) */
11234*6777b538SAndroid Build Coastguard Worker } while ((cur != NULL) && (ctxt->error == XPATH_EXPRESSION_OK));
11235*6777b538SAndroid Build Coastguard Worker
11236*6777b538SAndroid Build Coastguard Worker goto apply_predicates;
11237*6777b538SAndroid Build Coastguard Worker
11238*6777b538SAndroid Build Coastguard Worker axis_range_end: /* ----------------------------------------------------- */
11239*6777b538SAndroid Build Coastguard Worker /*
11240*6777b538SAndroid Build Coastguard Worker * We have a "/foo[n]", and position() = n was reached.
11241*6777b538SAndroid Build Coastguard Worker * Note that we can have as well "/foo/::parent::foo[1]", so
11242*6777b538SAndroid Build Coastguard Worker * a duplicate-aware merge is still needed.
11243*6777b538SAndroid Build Coastguard Worker * Merge with the result.
11244*6777b538SAndroid Build Coastguard Worker */
11245*6777b538SAndroid Build Coastguard Worker if (outSeq == NULL) {
11246*6777b538SAndroid Build Coastguard Worker outSeq = seq;
11247*6777b538SAndroid Build Coastguard Worker seq = NULL;
11248*6777b538SAndroid Build Coastguard Worker } else {
11249*6777b538SAndroid Build Coastguard Worker outSeq = mergeAndClear(outSeq, seq);
11250*6777b538SAndroid Build Coastguard Worker if (outSeq == NULL)
11251*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
11252*6777b538SAndroid Build Coastguard Worker }
11253*6777b538SAndroid Build Coastguard Worker /*
11254*6777b538SAndroid Build Coastguard Worker * Break if only a true/false result was requested.
11255*6777b538SAndroid Build Coastguard Worker */
11256*6777b538SAndroid Build Coastguard Worker if (toBool)
11257*6777b538SAndroid Build Coastguard Worker break;
11258*6777b538SAndroid Build Coastguard Worker continue;
11259*6777b538SAndroid Build Coastguard Worker
11260*6777b538SAndroid Build Coastguard Worker first_hit: /* ---------------------------------------------------------- */
11261*6777b538SAndroid Build Coastguard Worker /*
11262*6777b538SAndroid Build Coastguard Worker * Break if only a true/false result was requested and
11263*6777b538SAndroid Build Coastguard Worker * no predicates existed and a node test succeeded.
11264*6777b538SAndroid Build Coastguard Worker */
11265*6777b538SAndroid Build Coastguard Worker if (outSeq == NULL) {
11266*6777b538SAndroid Build Coastguard Worker outSeq = seq;
11267*6777b538SAndroid Build Coastguard Worker seq = NULL;
11268*6777b538SAndroid Build Coastguard Worker } else {
11269*6777b538SAndroid Build Coastguard Worker outSeq = mergeAndClear(outSeq, seq);
11270*6777b538SAndroid Build Coastguard Worker if (outSeq == NULL)
11271*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
11272*6777b538SAndroid Build Coastguard Worker }
11273*6777b538SAndroid Build Coastguard Worker break;
11274*6777b538SAndroid Build Coastguard Worker
11275*6777b538SAndroid Build Coastguard Worker apply_predicates: /* --------------------------------------------------- */
11276*6777b538SAndroid Build Coastguard Worker if (ctxt->error != XPATH_EXPRESSION_OK)
11277*6777b538SAndroid Build Coastguard Worker goto error;
11278*6777b538SAndroid Build Coastguard Worker
11279*6777b538SAndroid Build Coastguard Worker /*
11280*6777b538SAndroid Build Coastguard Worker * Apply predicates.
11281*6777b538SAndroid Build Coastguard Worker */
11282*6777b538SAndroid Build Coastguard Worker if ((predOp != NULL) && (seq->nodeNr > 0)) {
11283*6777b538SAndroid Build Coastguard Worker /*
11284*6777b538SAndroid Build Coastguard Worker * E.g. when we have a "/foo[some expression][n]".
11285*6777b538SAndroid Build Coastguard Worker */
11286*6777b538SAndroid Build Coastguard Worker /*
11287*6777b538SAndroid Build Coastguard Worker * QUESTION TODO: The old predicate evaluation took into
11288*6777b538SAndroid Build Coastguard Worker * account location-sets.
11289*6777b538SAndroid Build Coastguard Worker * (E.g. ctxt->value->type == XPATH_LOCATIONSET)
11290*6777b538SAndroid Build Coastguard Worker * Do we expect such a set here?
11291*6777b538SAndroid Build Coastguard Worker * All what I learned now from the evaluation semantics
11292*6777b538SAndroid Build Coastguard Worker * does not indicate that a location-set will be processed
11293*6777b538SAndroid Build Coastguard Worker * here, so this looks OK.
11294*6777b538SAndroid Build Coastguard Worker */
11295*6777b538SAndroid Build Coastguard Worker /*
11296*6777b538SAndroid Build Coastguard Worker * Iterate over all predicates, starting with the outermost
11297*6777b538SAndroid Build Coastguard Worker * predicate.
11298*6777b538SAndroid Build Coastguard Worker * TODO: Problem: we cannot execute the inner predicates first
11299*6777b538SAndroid Build Coastguard Worker * since we cannot go back *up* the operator tree!
11300*6777b538SAndroid Build Coastguard Worker * Options we have:
11301*6777b538SAndroid Build Coastguard Worker * 1) Use of recursive functions (like is it currently done
11302*6777b538SAndroid Build Coastguard Worker * via xmlXPathCompOpEval())
11303*6777b538SAndroid Build Coastguard Worker * 2) Add a predicate evaluation information stack to the
11304*6777b538SAndroid Build Coastguard Worker * context struct
11305*6777b538SAndroid Build Coastguard Worker * 3) Change the way the operators are linked; we need a
11306*6777b538SAndroid Build Coastguard Worker * "parent" field on xmlXPathStepOp
11307*6777b538SAndroid Build Coastguard Worker *
11308*6777b538SAndroid Build Coastguard Worker * For the moment, I'll try to solve this with a recursive
11309*6777b538SAndroid Build Coastguard Worker * function: xmlXPathCompOpEvalPredicate().
11310*6777b538SAndroid Build Coastguard Worker */
11311*6777b538SAndroid Build Coastguard Worker if (hasPredicateRange != 0)
11312*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEvalPredicate(ctxt, predOp, seq, maxPos, maxPos,
11313*6777b538SAndroid Build Coastguard Worker hasNsNodes);
11314*6777b538SAndroid Build Coastguard Worker else
11315*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEvalPredicate(ctxt, predOp, seq, 1, seq->nodeNr,
11316*6777b538SAndroid Build Coastguard Worker hasNsNodes);
11317*6777b538SAndroid Build Coastguard Worker
11318*6777b538SAndroid Build Coastguard Worker if (ctxt->error != XPATH_EXPRESSION_OK) {
11319*6777b538SAndroid Build Coastguard Worker total = 0;
11320*6777b538SAndroid Build Coastguard Worker goto error;
11321*6777b538SAndroid Build Coastguard Worker }
11322*6777b538SAndroid Build Coastguard Worker }
11323*6777b538SAndroid Build Coastguard Worker
11324*6777b538SAndroid Build Coastguard Worker if (seq->nodeNr > 0) {
11325*6777b538SAndroid Build Coastguard Worker /*
11326*6777b538SAndroid Build Coastguard Worker * Add to result set.
11327*6777b538SAndroid Build Coastguard Worker */
11328*6777b538SAndroid Build Coastguard Worker if (outSeq == NULL) {
11329*6777b538SAndroid Build Coastguard Worker outSeq = seq;
11330*6777b538SAndroid Build Coastguard Worker seq = NULL;
11331*6777b538SAndroid Build Coastguard Worker } else {
11332*6777b538SAndroid Build Coastguard Worker outSeq = mergeAndClear(outSeq, seq);
11333*6777b538SAndroid Build Coastguard Worker if (outSeq == NULL)
11334*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
11335*6777b538SAndroid Build Coastguard Worker }
11336*6777b538SAndroid Build Coastguard Worker
11337*6777b538SAndroid Build Coastguard Worker if (toBool)
11338*6777b538SAndroid Build Coastguard Worker break;
11339*6777b538SAndroid Build Coastguard Worker }
11340*6777b538SAndroid Build Coastguard Worker }
11341*6777b538SAndroid Build Coastguard Worker
11342*6777b538SAndroid Build Coastguard Worker error:
11343*6777b538SAndroid Build Coastguard Worker if ((obj->boolval) && (obj->user != NULL)) {
11344*6777b538SAndroid Build Coastguard Worker /*
11345*6777b538SAndroid Build Coastguard Worker * QUESTION TODO: What does this do and why?
11346*6777b538SAndroid Build Coastguard Worker * TODO: Do we have to do this also for the "error"
11347*6777b538SAndroid Build Coastguard Worker * cleanup further down?
11348*6777b538SAndroid Build Coastguard Worker */
11349*6777b538SAndroid Build Coastguard Worker ctxt->value->boolval = 1;
11350*6777b538SAndroid Build Coastguard Worker ctxt->value->user = obj->user;
11351*6777b538SAndroid Build Coastguard Worker obj->user = NULL;
11352*6777b538SAndroid Build Coastguard Worker obj->boolval = 0;
11353*6777b538SAndroid Build Coastguard Worker }
11354*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(xpctxt, obj);
11355*6777b538SAndroid Build Coastguard Worker
11356*6777b538SAndroid Build Coastguard Worker /*
11357*6777b538SAndroid Build Coastguard Worker * Ensure we return at least an empty set.
11358*6777b538SAndroid Build Coastguard Worker */
11359*6777b538SAndroid Build Coastguard Worker if (outSeq == NULL) {
11360*6777b538SAndroid Build Coastguard Worker if ((seq != NULL) && (seq->nodeNr == 0)) {
11361*6777b538SAndroid Build Coastguard Worker outSeq = seq;
11362*6777b538SAndroid Build Coastguard Worker } else {
11363*6777b538SAndroid Build Coastguard Worker outSeq = xmlXPathNodeSetCreate(NULL);
11364*6777b538SAndroid Build Coastguard Worker if (outSeq == NULL)
11365*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
11366*6777b538SAndroid Build Coastguard Worker }
11367*6777b538SAndroid Build Coastguard Worker }
11368*6777b538SAndroid Build Coastguard Worker if ((seq != NULL) && (seq != outSeq)) {
11369*6777b538SAndroid Build Coastguard Worker xmlXPathFreeNodeSet(seq);
11370*6777b538SAndroid Build Coastguard Worker }
11371*6777b538SAndroid Build Coastguard Worker /*
11372*6777b538SAndroid Build Coastguard Worker * Hand over the result. Better to push the set also in
11373*6777b538SAndroid Build Coastguard Worker * case of errors.
11374*6777b538SAndroid Build Coastguard Worker */
11375*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheWrapNodeSet(ctxt, outSeq));
11376*6777b538SAndroid Build Coastguard Worker /*
11377*6777b538SAndroid Build Coastguard Worker * Reset the context node.
11378*6777b538SAndroid Build Coastguard Worker */
11379*6777b538SAndroid Build Coastguard Worker xpctxt->node = oldContextNode;
11380*6777b538SAndroid Build Coastguard Worker /*
11381*6777b538SAndroid Build Coastguard Worker * When traversing the namespace axis in "toBool" mode, it's
11382*6777b538SAndroid Build Coastguard Worker * possible that tmpNsList wasn't freed.
11383*6777b538SAndroid Build Coastguard Worker */
11384*6777b538SAndroid Build Coastguard Worker if (xpctxt->tmpNsList != NULL) {
11385*6777b538SAndroid Build Coastguard Worker xmlFree(xpctxt->tmpNsList);
11386*6777b538SAndroid Build Coastguard Worker xpctxt->tmpNsList = NULL;
11387*6777b538SAndroid Build Coastguard Worker }
11388*6777b538SAndroid Build Coastguard Worker
11389*6777b538SAndroid Build Coastguard Worker return(total);
11390*6777b538SAndroid Build Coastguard Worker }
11391*6777b538SAndroid Build Coastguard Worker
11392*6777b538SAndroid Build Coastguard Worker static int
11393*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
11394*6777b538SAndroid Build Coastguard Worker xmlXPathStepOpPtr op, xmlNodePtr * first);
11395*6777b538SAndroid Build Coastguard Worker
11396*6777b538SAndroid Build Coastguard Worker /**
11397*6777b538SAndroid Build Coastguard Worker * xmlXPathCompOpEvalFirst:
11398*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath parser context with the compiled expression
11399*6777b538SAndroid Build Coastguard Worker * @op: an XPath compiled operation
11400*6777b538SAndroid Build Coastguard Worker * @first: the first elem found so far
11401*6777b538SAndroid Build Coastguard Worker *
11402*6777b538SAndroid Build Coastguard Worker * Evaluate the Precompiled XPath operation searching only the first
11403*6777b538SAndroid Build Coastguard Worker * element in document order
11404*6777b538SAndroid Build Coastguard Worker *
11405*6777b538SAndroid Build Coastguard Worker * Returns the number of examined objects.
11406*6777b538SAndroid Build Coastguard Worker */
11407*6777b538SAndroid Build Coastguard Worker static int
xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt,xmlXPathStepOpPtr op,xmlNodePtr * first)11408*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEvalFirst(xmlXPathParserContextPtr ctxt,
11409*6777b538SAndroid Build Coastguard Worker xmlXPathStepOpPtr op, xmlNodePtr * first)
11410*6777b538SAndroid Build Coastguard Worker {
11411*6777b538SAndroid Build Coastguard Worker int total = 0, cur;
11412*6777b538SAndroid Build Coastguard Worker xmlXPathCompExprPtr comp;
11413*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr arg1, arg2;
11414*6777b538SAndroid Build Coastguard Worker
11415*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11416*6777b538SAndroid Build Coastguard Worker if (OP_LIMIT_EXCEEDED(ctxt, 1))
11417*6777b538SAndroid Build Coastguard Worker return(0);
11418*6777b538SAndroid Build Coastguard Worker if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH)
11419*6777b538SAndroid Build Coastguard Worker XP_ERROR0(XPATH_RECURSION_LIMIT_EXCEEDED);
11420*6777b538SAndroid Build Coastguard Worker ctxt->context->depth += 1;
11421*6777b538SAndroid Build Coastguard Worker comp = ctxt->comp;
11422*6777b538SAndroid Build Coastguard Worker switch (op->op) {
11423*6777b538SAndroid Build Coastguard Worker case XPATH_OP_END:
11424*6777b538SAndroid Build Coastguard Worker break;
11425*6777b538SAndroid Build Coastguard Worker case XPATH_OP_UNION:
11426*6777b538SAndroid Build Coastguard Worker total =
11427*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch1],
11428*6777b538SAndroid Build Coastguard Worker first);
11429*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11430*6777b538SAndroid Build Coastguard Worker if ((ctxt->value != NULL)
11431*6777b538SAndroid Build Coastguard Worker && (ctxt->value->type == XPATH_NODESET)
11432*6777b538SAndroid Build Coastguard Worker && (ctxt->value->nodesetval != NULL)
11433*6777b538SAndroid Build Coastguard Worker && (ctxt->value->nodesetval->nodeNr >= 1)) {
11434*6777b538SAndroid Build Coastguard Worker /*
11435*6777b538SAndroid Build Coastguard Worker * limit tree traversing to first node in the result
11436*6777b538SAndroid Build Coastguard Worker */
11437*6777b538SAndroid Build Coastguard Worker /*
11438*6777b538SAndroid Build Coastguard Worker * OPTIMIZE TODO: This implicitly sorts
11439*6777b538SAndroid Build Coastguard Worker * the result, even if not needed. E.g. if the argument
11440*6777b538SAndroid Build Coastguard Worker * of the count() function, no sorting is needed.
11441*6777b538SAndroid Build Coastguard Worker * OPTIMIZE TODO: How do we know if the node-list wasn't
11442*6777b538SAndroid Build Coastguard Worker * already sorted?
11443*6777b538SAndroid Build Coastguard Worker */
11444*6777b538SAndroid Build Coastguard Worker if (ctxt->value->nodesetval->nodeNr > 1)
11445*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetSort(ctxt->value->nodesetval);
11446*6777b538SAndroid Build Coastguard Worker *first = ctxt->value->nodesetval->nodeTab[0];
11447*6777b538SAndroid Build Coastguard Worker }
11448*6777b538SAndroid Build Coastguard Worker cur =
11449*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch2],
11450*6777b538SAndroid Build Coastguard Worker first);
11451*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11452*6777b538SAndroid Build Coastguard Worker
11453*6777b538SAndroid Build Coastguard Worker arg2 = valuePop(ctxt);
11454*6777b538SAndroid Build Coastguard Worker arg1 = valuePop(ctxt);
11455*6777b538SAndroid Build Coastguard Worker if ((arg1 == NULL) || (arg1->type != XPATH_NODESET) ||
11456*6777b538SAndroid Build Coastguard Worker (arg2 == NULL) || (arg2->type != XPATH_NODESET)) {
11457*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
11458*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
11459*6777b538SAndroid Build Coastguard Worker XP_ERROR0(XPATH_INVALID_TYPE);
11460*6777b538SAndroid Build Coastguard Worker }
11461*6777b538SAndroid Build Coastguard Worker if ((ctxt->context->opLimit != 0) &&
11462*6777b538SAndroid Build Coastguard Worker (((arg1->nodesetval != NULL) &&
11463*6777b538SAndroid Build Coastguard Worker (xmlXPathCheckOpLimit(ctxt,
11464*6777b538SAndroid Build Coastguard Worker arg1->nodesetval->nodeNr) < 0)) ||
11465*6777b538SAndroid Build Coastguard Worker ((arg2->nodesetval != NULL) &&
11466*6777b538SAndroid Build Coastguard Worker (xmlXPathCheckOpLimit(ctxt,
11467*6777b538SAndroid Build Coastguard Worker arg2->nodesetval->nodeNr) < 0)))) {
11468*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
11469*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
11470*6777b538SAndroid Build Coastguard Worker break;
11471*6777b538SAndroid Build Coastguard Worker }
11472*6777b538SAndroid Build Coastguard Worker
11473*6777b538SAndroid Build Coastguard Worker if ((arg2->nodesetval != NULL) &&
11474*6777b538SAndroid Build Coastguard Worker (arg2->nodesetval->nodeNr != 0)) {
11475*6777b538SAndroid Build Coastguard Worker arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
11476*6777b538SAndroid Build Coastguard Worker arg2->nodesetval);
11477*6777b538SAndroid Build Coastguard Worker if (arg1->nodesetval == NULL)
11478*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
11479*6777b538SAndroid Build Coastguard Worker }
11480*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, arg1);
11481*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
11482*6777b538SAndroid Build Coastguard Worker /* optimizer */
11483*6777b538SAndroid Build Coastguard Worker if (total > cur)
11484*6777b538SAndroid Build Coastguard Worker xmlXPathCompSwap(op);
11485*6777b538SAndroid Build Coastguard Worker total += cur;
11486*6777b538SAndroid Build Coastguard Worker break;
11487*6777b538SAndroid Build Coastguard Worker case XPATH_OP_ROOT:
11488*6777b538SAndroid Build Coastguard Worker xmlXPathRoot(ctxt);
11489*6777b538SAndroid Build Coastguard Worker break;
11490*6777b538SAndroid Build Coastguard Worker case XPATH_OP_NODE:
11491*6777b538SAndroid Build Coastguard Worker if (op->ch1 != -1)
11492*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11493*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11494*6777b538SAndroid Build Coastguard Worker if (op->ch2 != -1)
11495*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11496*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11497*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt,
11498*6777b538SAndroid Build Coastguard Worker ctxt->context->node));
11499*6777b538SAndroid Build Coastguard Worker break;
11500*6777b538SAndroid Build Coastguard Worker case XPATH_OP_COLLECT:{
11501*6777b538SAndroid Build Coastguard Worker if (op->ch1 == -1)
11502*6777b538SAndroid Build Coastguard Worker break;
11503*6777b538SAndroid Build Coastguard Worker
11504*6777b538SAndroid Build Coastguard Worker total = xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11505*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11506*6777b538SAndroid Build Coastguard Worker
11507*6777b538SAndroid Build Coastguard Worker total += xmlXPathNodeCollectAndTest(ctxt, op, first, NULL, 0);
11508*6777b538SAndroid Build Coastguard Worker break;
11509*6777b538SAndroid Build Coastguard Worker }
11510*6777b538SAndroid Build Coastguard Worker case XPATH_OP_VALUE:
11511*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt, op->value4));
11512*6777b538SAndroid Build Coastguard Worker break;
11513*6777b538SAndroid Build Coastguard Worker case XPATH_OP_SORT:
11514*6777b538SAndroid Build Coastguard Worker if (op->ch1 != -1)
11515*6777b538SAndroid Build Coastguard Worker total +=
11516*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEvalFirst(ctxt, &comp->steps[op->ch1],
11517*6777b538SAndroid Build Coastguard Worker first);
11518*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11519*6777b538SAndroid Build Coastguard Worker if ((ctxt->value != NULL)
11520*6777b538SAndroid Build Coastguard Worker && (ctxt->value->type == XPATH_NODESET)
11521*6777b538SAndroid Build Coastguard Worker && (ctxt->value->nodesetval != NULL)
11522*6777b538SAndroid Build Coastguard Worker && (ctxt->value->nodesetval->nodeNr > 1))
11523*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetSort(ctxt->value->nodesetval);
11524*6777b538SAndroid Build Coastguard Worker break;
11525*6777b538SAndroid Build Coastguard Worker #ifdef XP_OPTIMIZED_FILTER_FIRST
11526*6777b538SAndroid Build Coastguard Worker case XPATH_OP_FILTER:
11527*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEvalFilterFirst(ctxt, op, first);
11528*6777b538SAndroid Build Coastguard Worker break;
11529*6777b538SAndroid Build Coastguard Worker #endif
11530*6777b538SAndroid Build Coastguard Worker default:
11531*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, op);
11532*6777b538SAndroid Build Coastguard Worker break;
11533*6777b538SAndroid Build Coastguard Worker }
11534*6777b538SAndroid Build Coastguard Worker
11535*6777b538SAndroid Build Coastguard Worker ctxt->context->depth -= 1;
11536*6777b538SAndroid Build Coastguard Worker return(total);
11537*6777b538SAndroid Build Coastguard Worker }
11538*6777b538SAndroid Build Coastguard Worker
11539*6777b538SAndroid Build Coastguard Worker /**
11540*6777b538SAndroid Build Coastguard Worker * xmlXPathCompOpEvalLast:
11541*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath parser context with the compiled expression
11542*6777b538SAndroid Build Coastguard Worker * @op: an XPath compiled operation
11543*6777b538SAndroid Build Coastguard Worker * @last: the last elem found so far
11544*6777b538SAndroid Build Coastguard Worker *
11545*6777b538SAndroid Build Coastguard Worker * Evaluate the Precompiled XPath operation searching only the last
11546*6777b538SAndroid Build Coastguard Worker * element in document order
11547*6777b538SAndroid Build Coastguard Worker *
11548*6777b538SAndroid Build Coastguard Worker * Returns the number of nodes traversed
11549*6777b538SAndroid Build Coastguard Worker */
11550*6777b538SAndroid Build Coastguard Worker static int
xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt,xmlXPathStepOpPtr op,xmlNodePtr * last)11551*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEvalLast(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op,
11552*6777b538SAndroid Build Coastguard Worker xmlNodePtr * last)
11553*6777b538SAndroid Build Coastguard Worker {
11554*6777b538SAndroid Build Coastguard Worker int total = 0, cur;
11555*6777b538SAndroid Build Coastguard Worker xmlXPathCompExprPtr comp;
11556*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr arg1, arg2;
11557*6777b538SAndroid Build Coastguard Worker
11558*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11559*6777b538SAndroid Build Coastguard Worker if (OP_LIMIT_EXCEEDED(ctxt, 1))
11560*6777b538SAndroid Build Coastguard Worker return(0);
11561*6777b538SAndroid Build Coastguard Worker if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH)
11562*6777b538SAndroid Build Coastguard Worker XP_ERROR0(XPATH_RECURSION_LIMIT_EXCEEDED);
11563*6777b538SAndroid Build Coastguard Worker ctxt->context->depth += 1;
11564*6777b538SAndroid Build Coastguard Worker comp = ctxt->comp;
11565*6777b538SAndroid Build Coastguard Worker switch (op->op) {
11566*6777b538SAndroid Build Coastguard Worker case XPATH_OP_END:
11567*6777b538SAndroid Build Coastguard Worker break;
11568*6777b538SAndroid Build Coastguard Worker case XPATH_OP_UNION:
11569*6777b538SAndroid Build Coastguard Worker total =
11570*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch1], last);
11571*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11572*6777b538SAndroid Build Coastguard Worker if ((ctxt->value != NULL)
11573*6777b538SAndroid Build Coastguard Worker && (ctxt->value->type == XPATH_NODESET)
11574*6777b538SAndroid Build Coastguard Worker && (ctxt->value->nodesetval != NULL)
11575*6777b538SAndroid Build Coastguard Worker && (ctxt->value->nodesetval->nodeNr >= 1)) {
11576*6777b538SAndroid Build Coastguard Worker /*
11577*6777b538SAndroid Build Coastguard Worker * limit tree traversing to first node in the result
11578*6777b538SAndroid Build Coastguard Worker */
11579*6777b538SAndroid Build Coastguard Worker if (ctxt->value->nodesetval->nodeNr > 1)
11580*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetSort(ctxt->value->nodesetval);
11581*6777b538SAndroid Build Coastguard Worker *last =
11582*6777b538SAndroid Build Coastguard Worker ctxt->value->nodesetval->nodeTab[ctxt->value->
11583*6777b538SAndroid Build Coastguard Worker nodesetval->nodeNr -
11584*6777b538SAndroid Build Coastguard Worker 1];
11585*6777b538SAndroid Build Coastguard Worker }
11586*6777b538SAndroid Build Coastguard Worker cur =
11587*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch2], last);
11588*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11589*6777b538SAndroid Build Coastguard Worker if ((ctxt->value != NULL)
11590*6777b538SAndroid Build Coastguard Worker && (ctxt->value->type == XPATH_NODESET)
11591*6777b538SAndroid Build Coastguard Worker && (ctxt->value->nodesetval != NULL)
11592*6777b538SAndroid Build Coastguard Worker && (ctxt->value->nodesetval->nodeNr >= 1)) { /* TODO: NOP ? */
11593*6777b538SAndroid Build Coastguard Worker }
11594*6777b538SAndroid Build Coastguard Worker
11595*6777b538SAndroid Build Coastguard Worker arg2 = valuePop(ctxt);
11596*6777b538SAndroid Build Coastguard Worker arg1 = valuePop(ctxt);
11597*6777b538SAndroid Build Coastguard Worker if ((arg1 == NULL) || (arg1->type != XPATH_NODESET) ||
11598*6777b538SAndroid Build Coastguard Worker (arg2 == NULL) || (arg2->type != XPATH_NODESET)) {
11599*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
11600*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
11601*6777b538SAndroid Build Coastguard Worker XP_ERROR0(XPATH_INVALID_TYPE);
11602*6777b538SAndroid Build Coastguard Worker }
11603*6777b538SAndroid Build Coastguard Worker if ((ctxt->context->opLimit != 0) &&
11604*6777b538SAndroid Build Coastguard Worker (((arg1->nodesetval != NULL) &&
11605*6777b538SAndroid Build Coastguard Worker (xmlXPathCheckOpLimit(ctxt,
11606*6777b538SAndroid Build Coastguard Worker arg1->nodesetval->nodeNr) < 0)) ||
11607*6777b538SAndroid Build Coastguard Worker ((arg2->nodesetval != NULL) &&
11608*6777b538SAndroid Build Coastguard Worker (xmlXPathCheckOpLimit(ctxt,
11609*6777b538SAndroid Build Coastguard Worker arg2->nodesetval->nodeNr) < 0)))) {
11610*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
11611*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
11612*6777b538SAndroid Build Coastguard Worker break;
11613*6777b538SAndroid Build Coastguard Worker }
11614*6777b538SAndroid Build Coastguard Worker
11615*6777b538SAndroid Build Coastguard Worker if ((arg2->nodesetval != NULL) &&
11616*6777b538SAndroid Build Coastguard Worker (arg2->nodesetval->nodeNr != 0)) {
11617*6777b538SAndroid Build Coastguard Worker arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
11618*6777b538SAndroid Build Coastguard Worker arg2->nodesetval);
11619*6777b538SAndroid Build Coastguard Worker if (arg1->nodesetval == NULL)
11620*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
11621*6777b538SAndroid Build Coastguard Worker }
11622*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, arg1);
11623*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
11624*6777b538SAndroid Build Coastguard Worker /* optimizer */
11625*6777b538SAndroid Build Coastguard Worker if (total > cur)
11626*6777b538SAndroid Build Coastguard Worker xmlXPathCompSwap(op);
11627*6777b538SAndroid Build Coastguard Worker total += cur;
11628*6777b538SAndroid Build Coastguard Worker break;
11629*6777b538SAndroid Build Coastguard Worker case XPATH_OP_ROOT:
11630*6777b538SAndroid Build Coastguard Worker xmlXPathRoot(ctxt);
11631*6777b538SAndroid Build Coastguard Worker break;
11632*6777b538SAndroid Build Coastguard Worker case XPATH_OP_NODE:
11633*6777b538SAndroid Build Coastguard Worker if (op->ch1 != -1)
11634*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11635*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11636*6777b538SAndroid Build Coastguard Worker if (op->ch2 != -1)
11637*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11638*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11639*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt,
11640*6777b538SAndroid Build Coastguard Worker ctxt->context->node));
11641*6777b538SAndroid Build Coastguard Worker break;
11642*6777b538SAndroid Build Coastguard Worker case XPATH_OP_COLLECT:{
11643*6777b538SAndroid Build Coastguard Worker if (op->ch1 == -1)
11644*6777b538SAndroid Build Coastguard Worker break;
11645*6777b538SAndroid Build Coastguard Worker
11646*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11647*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11648*6777b538SAndroid Build Coastguard Worker
11649*6777b538SAndroid Build Coastguard Worker total += xmlXPathNodeCollectAndTest(ctxt, op, NULL, last, 0);
11650*6777b538SAndroid Build Coastguard Worker break;
11651*6777b538SAndroid Build Coastguard Worker }
11652*6777b538SAndroid Build Coastguard Worker case XPATH_OP_VALUE:
11653*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt, op->value4));
11654*6777b538SAndroid Build Coastguard Worker break;
11655*6777b538SAndroid Build Coastguard Worker case XPATH_OP_SORT:
11656*6777b538SAndroid Build Coastguard Worker if (op->ch1 != -1)
11657*6777b538SAndroid Build Coastguard Worker total +=
11658*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEvalLast(ctxt, &comp->steps[op->ch1],
11659*6777b538SAndroid Build Coastguard Worker last);
11660*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11661*6777b538SAndroid Build Coastguard Worker if ((ctxt->value != NULL)
11662*6777b538SAndroid Build Coastguard Worker && (ctxt->value->type == XPATH_NODESET)
11663*6777b538SAndroid Build Coastguard Worker && (ctxt->value->nodesetval != NULL)
11664*6777b538SAndroid Build Coastguard Worker && (ctxt->value->nodesetval->nodeNr > 1))
11665*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetSort(ctxt->value->nodesetval);
11666*6777b538SAndroid Build Coastguard Worker break;
11667*6777b538SAndroid Build Coastguard Worker default:
11668*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, op);
11669*6777b538SAndroid Build Coastguard Worker break;
11670*6777b538SAndroid Build Coastguard Worker }
11671*6777b538SAndroid Build Coastguard Worker
11672*6777b538SAndroid Build Coastguard Worker ctxt->context->depth -= 1;
11673*6777b538SAndroid Build Coastguard Worker return (total);
11674*6777b538SAndroid Build Coastguard Worker }
11675*6777b538SAndroid Build Coastguard Worker
11676*6777b538SAndroid Build Coastguard Worker #ifdef XP_OPTIMIZED_FILTER_FIRST
11677*6777b538SAndroid Build Coastguard Worker static int
xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,xmlXPathStepOpPtr op,xmlNodePtr * first)11678*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEvalFilterFirst(xmlXPathParserContextPtr ctxt,
11679*6777b538SAndroid Build Coastguard Worker xmlXPathStepOpPtr op, xmlNodePtr * first)
11680*6777b538SAndroid Build Coastguard Worker {
11681*6777b538SAndroid Build Coastguard Worker int total = 0;
11682*6777b538SAndroid Build Coastguard Worker xmlXPathCompExprPtr comp;
11683*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr obj;
11684*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr set;
11685*6777b538SAndroid Build Coastguard Worker
11686*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11687*6777b538SAndroid Build Coastguard Worker comp = ctxt->comp;
11688*6777b538SAndroid Build Coastguard Worker /*
11689*6777b538SAndroid Build Coastguard Worker * Optimization for ()[last()] selection i.e. the last elem
11690*6777b538SAndroid Build Coastguard Worker */
11691*6777b538SAndroid Build Coastguard Worker if ((op->ch1 != -1) && (op->ch2 != -1) &&
11692*6777b538SAndroid Build Coastguard Worker (comp->steps[op->ch1].op == XPATH_OP_SORT) &&
11693*6777b538SAndroid Build Coastguard Worker (comp->steps[op->ch2].op == XPATH_OP_SORT)) {
11694*6777b538SAndroid Build Coastguard Worker int f = comp->steps[op->ch2].ch1;
11695*6777b538SAndroid Build Coastguard Worker
11696*6777b538SAndroid Build Coastguard Worker if ((f != -1) &&
11697*6777b538SAndroid Build Coastguard Worker (comp->steps[f].op == XPATH_OP_FUNCTION) &&
11698*6777b538SAndroid Build Coastguard Worker (comp->steps[f].value5 == NULL) &&
11699*6777b538SAndroid Build Coastguard Worker (comp->steps[f].value == 0) &&
11700*6777b538SAndroid Build Coastguard Worker (comp->steps[f].value4 != NULL) &&
11701*6777b538SAndroid Build Coastguard Worker (xmlStrEqual
11702*6777b538SAndroid Build Coastguard Worker (comp->steps[f].value4, BAD_CAST "last"))) {
11703*6777b538SAndroid Build Coastguard Worker xmlNodePtr last = NULL;
11704*6777b538SAndroid Build Coastguard Worker
11705*6777b538SAndroid Build Coastguard Worker total +=
11706*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEvalLast(ctxt,
11707*6777b538SAndroid Build Coastguard Worker &comp->steps[op->ch1],
11708*6777b538SAndroid Build Coastguard Worker &last);
11709*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11710*6777b538SAndroid Build Coastguard Worker /*
11711*6777b538SAndroid Build Coastguard Worker * The nodeset should be in document order,
11712*6777b538SAndroid Build Coastguard Worker * Keep only the last value
11713*6777b538SAndroid Build Coastguard Worker */
11714*6777b538SAndroid Build Coastguard Worker if ((ctxt->value != NULL) &&
11715*6777b538SAndroid Build Coastguard Worker (ctxt->value->type == XPATH_NODESET) &&
11716*6777b538SAndroid Build Coastguard Worker (ctxt->value->nodesetval != NULL) &&
11717*6777b538SAndroid Build Coastguard Worker (ctxt->value->nodesetval->nodeTab != NULL) &&
11718*6777b538SAndroid Build Coastguard Worker (ctxt->value->nodesetval->nodeNr > 1)) {
11719*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetKeepLast(ctxt->value->nodesetval);
11720*6777b538SAndroid Build Coastguard Worker *first = *(ctxt->value->nodesetval->nodeTab);
11721*6777b538SAndroid Build Coastguard Worker }
11722*6777b538SAndroid Build Coastguard Worker return (total);
11723*6777b538SAndroid Build Coastguard Worker }
11724*6777b538SAndroid Build Coastguard Worker }
11725*6777b538SAndroid Build Coastguard Worker
11726*6777b538SAndroid Build Coastguard Worker if (op->ch1 != -1)
11727*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11728*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11729*6777b538SAndroid Build Coastguard Worker if (op->ch2 == -1)
11730*6777b538SAndroid Build Coastguard Worker return (total);
11731*6777b538SAndroid Build Coastguard Worker if (ctxt->value == NULL)
11732*6777b538SAndroid Build Coastguard Worker return (total);
11733*6777b538SAndroid Build Coastguard Worker
11734*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
11735*6777b538SAndroid Build Coastguard Worker /*
11736*6777b538SAndroid Build Coastguard Worker * Hum are we filtering the result of an XPointer expression
11737*6777b538SAndroid Build Coastguard Worker */
11738*6777b538SAndroid Build Coastguard Worker if (ctxt->value->type == XPATH_LOCATIONSET) {
11739*6777b538SAndroid Build Coastguard Worker xmlLocationSetPtr locset = ctxt->value->user;
11740*6777b538SAndroid Build Coastguard Worker
11741*6777b538SAndroid Build Coastguard Worker if (locset != NULL) {
11742*6777b538SAndroid Build Coastguard Worker xmlXPathLocationSetFilter(ctxt, locset, op->ch2, 1, 1);
11743*6777b538SAndroid Build Coastguard Worker if (locset->locNr > 0)
11744*6777b538SAndroid Build Coastguard Worker *first = (xmlNodePtr) locset->locTab[0]->user;
11745*6777b538SAndroid Build Coastguard Worker }
11746*6777b538SAndroid Build Coastguard Worker
11747*6777b538SAndroid Build Coastguard Worker return (total);
11748*6777b538SAndroid Build Coastguard Worker }
11749*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_XPTR_LOCS_ENABLED */
11750*6777b538SAndroid Build Coastguard Worker
11751*6777b538SAndroid Build Coastguard Worker /*
11752*6777b538SAndroid Build Coastguard Worker * In case of errors, xmlXPathNodeSetFilter can pop additional nodes from
11753*6777b538SAndroid Build Coastguard Worker * the stack. We have to temporarily remove the nodeset object from the
11754*6777b538SAndroid Build Coastguard Worker * stack to avoid freeing it prematurely.
11755*6777b538SAndroid Build Coastguard Worker */
11756*6777b538SAndroid Build Coastguard Worker CHECK_TYPE0(XPATH_NODESET);
11757*6777b538SAndroid Build Coastguard Worker obj = valuePop(ctxt);
11758*6777b538SAndroid Build Coastguard Worker set = obj->nodesetval;
11759*6777b538SAndroid Build Coastguard Worker if (set != NULL) {
11760*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetFilter(ctxt, set, op->ch2, 1, 1, 1);
11761*6777b538SAndroid Build Coastguard Worker if (set->nodeNr > 0)
11762*6777b538SAndroid Build Coastguard Worker *first = set->nodeTab[0];
11763*6777b538SAndroid Build Coastguard Worker }
11764*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, obj);
11765*6777b538SAndroid Build Coastguard Worker
11766*6777b538SAndroid Build Coastguard Worker return (total);
11767*6777b538SAndroid Build Coastguard Worker }
11768*6777b538SAndroid Build Coastguard Worker #endif /* XP_OPTIMIZED_FILTER_FIRST */
11769*6777b538SAndroid Build Coastguard Worker
11770*6777b538SAndroid Build Coastguard Worker /**
11771*6777b538SAndroid Build Coastguard Worker * xmlXPathCompOpEval:
11772*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath parser context with the compiled expression
11773*6777b538SAndroid Build Coastguard Worker * @op: an XPath compiled operation
11774*6777b538SAndroid Build Coastguard Worker *
11775*6777b538SAndroid Build Coastguard Worker * Evaluate the Precompiled XPath operation
11776*6777b538SAndroid Build Coastguard Worker * Returns the number of nodes traversed
11777*6777b538SAndroid Build Coastguard Worker */
11778*6777b538SAndroid Build Coastguard Worker static int
xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt,xmlXPathStepOpPtr op)11779*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEval(xmlXPathParserContextPtr ctxt, xmlXPathStepOpPtr op)
11780*6777b538SAndroid Build Coastguard Worker {
11781*6777b538SAndroid Build Coastguard Worker int total = 0;
11782*6777b538SAndroid Build Coastguard Worker int equal, ret;
11783*6777b538SAndroid Build Coastguard Worker xmlXPathCompExprPtr comp;
11784*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr arg1, arg2;
11785*6777b538SAndroid Build Coastguard Worker
11786*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11787*6777b538SAndroid Build Coastguard Worker if (OP_LIMIT_EXCEEDED(ctxt, 1))
11788*6777b538SAndroid Build Coastguard Worker return(0);
11789*6777b538SAndroid Build Coastguard Worker if (ctxt->context->depth >= XPATH_MAX_RECURSION_DEPTH)
11790*6777b538SAndroid Build Coastguard Worker XP_ERROR0(XPATH_RECURSION_LIMIT_EXCEEDED);
11791*6777b538SAndroid Build Coastguard Worker ctxt->context->depth += 1;
11792*6777b538SAndroid Build Coastguard Worker comp = ctxt->comp;
11793*6777b538SAndroid Build Coastguard Worker switch (op->op) {
11794*6777b538SAndroid Build Coastguard Worker case XPATH_OP_END:
11795*6777b538SAndroid Build Coastguard Worker break;
11796*6777b538SAndroid Build Coastguard Worker case XPATH_OP_AND:
11797*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11798*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11799*6777b538SAndroid Build Coastguard Worker xmlXPathBooleanFunction(ctxt, 1);
11800*6777b538SAndroid Build Coastguard Worker if ((ctxt->value == NULL) || (ctxt->value->boolval == 0))
11801*6777b538SAndroid Build Coastguard Worker break;
11802*6777b538SAndroid Build Coastguard Worker arg2 = valuePop(ctxt);
11803*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11804*6777b538SAndroid Build Coastguard Worker if (ctxt->error) {
11805*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject(arg2);
11806*6777b538SAndroid Build Coastguard Worker break;
11807*6777b538SAndroid Build Coastguard Worker }
11808*6777b538SAndroid Build Coastguard Worker xmlXPathBooleanFunction(ctxt, 1);
11809*6777b538SAndroid Build Coastguard Worker if (ctxt->value != NULL)
11810*6777b538SAndroid Build Coastguard Worker ctxt->value->boolval &= arg2->boolval;
11811*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
11812*6777b538SAndroid Build Coastguard Worker break;
11813*6777b538SAndroid Build Coastguard Worker case XPATH_OP_OR:
11814*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11815*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11816*6777b538SAndroid Build Coastguard Worker xmlXPathBooleanFunction(ctxt, 1);
11817*6777b538SAndroid Build Coastguard Worker if ((ctxt->value == NULL) || (ctxt->value->boolval == 1))
11818*6777b538SAndroid Build Coastguard Worker break;
11819*6777b538SAndroid Build Coastguard Worker arg2 = valuePop(ctxt);
11820*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11821*6777b538SAndroid Build Coastguard Worker if (ctxt->error) {
11822*6777b538SAndroid Build Coastguard Worker xmlXPathFreeObject(arg2);
11823*6777b538SAndroid Build Coastguard Worker break;
11824*6777b538SAndroid Build Coastguard Worker }
11825*6777b538SAndroid Build Coastguard Worker xmlXPathBooleanFunction(ctxt, 1);
11826*6777b538SAndroid Build Coastguard Worker if (ctxt->value != NULL)
11827*6777b538SAndroid Build Coastguard Worker ctxt->value->boolval |= arg2->boolval;
11828*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
11829*6777b538SAndroid Build Coastguard Worker break;
11830*6777b538SAndroid Build Coastguard Worker case XPATH_OP_EQUAL:
11831*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11832*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11833*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11834*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11835*6777b538SAndroid Build Coastguard Worker if (op->value)
11836*6777b538SAndroid Build Coastguard Worker equal = xmlXPathEqualValues(ctxt);
11837*6777b538SAndroid Build Coastguard Worker else
11838*6777b538SAndroid Build Coastguard Worker equal = xmlXPathNotEqualValues(ctxt);
11839*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, equal));
11840*6777b538SAndroid Build Coastguard Worker break;
11841*6777b538SAndroid Build Coastguard Worker case XPATH_OP_CMP:
11842*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11843*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11844*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11845*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11846*6777b538SAndroid Build Coastguard Worker ret = xmlXPathCompareValues(ctxt, op->value, op->value2);
11847*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, ret));
11848*6777b538SAndroid Build Coastguard Worker break;
11849*6777b538SAndroid Build Coastguard Worker case XPATH_OP_PLUS:
11850*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11851*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11852*6777b538SAndroid Build Coastguard Worker if (op->ch2 != -1) {
11853*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11854*6777b538SAndroid Build Coastguard Worker }
11855*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11856*6777b538SAndroid Build Coastguard Worker if (op->value == 0)
11857*6777b538SAndroid Build Coastguard Worker xmlXPathSubValues(ctxt);
11858*6777b538SAndroid Build Coastguard Worker else if (op->value == 1)
11859*6777b538SAndroid Build Coastguard Worker xmlXPathAddValues(ctxt);
11860*6777b538SAndroid Build Coastguard Worker else if (op->value == 2)
11861*6777b538SAndroid Build Coastguard Worker xmlXPathValueFlipSign(ctxt);
11862*6777b538SAndroid Build Coastguard Worker else if (op->value == 3) {
11863*6777b538SAndroid Build Coastguard Worker CAST_TO_NUMBER;
11864*6777b538SAndroid Build Coastguard Worker CHECK_TYPE0(XPATH_NUMBER);
11865*6777b538SAndroid Build Coastguard Worker }
11866*6777b538SAndroid Build Coastguard Worker break;
11867*6777b538SAndroid Build Coastguard Worker case XPATH_OP_MULT:
11868*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11869*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11870*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11871*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11872*6777b538SAndroid Build Coastguard Worker if (op->value == 0)
11873*6777b538SAndroid Build Coastguard Worker xmlXPathMultValues(ctxt);
11874*6777b538SAndroid Build Coastguard Worker else if (op->value == 1)
11875*6777b538SAndroid Build Coastguard Worker xmlXPathDivValues(ctxt);
11876*6777b538SAndroid Build Coastguard Worker else if (op->value == 2)
11877*6777b538SAndroid Build Coastguard Worker xmlXPathModValues(ctxt);
11878*6777b538SAndroid Build Coastguard Worker break;
11879*6777b538SAndroid Build Coastguard Worker case XPATH_OP_UNION:
11880*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11881*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11882*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11883*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11884*6777b538SAndroid Build Coastguard Worker
11885*6777b538SAndroid Build Coastguard Worker arg2 = valuePop(ctxt);
11886*6777b538SAndroid Build Coastguard Worker arg1 = valuePop(ctxt);
11887*6777b538SAndroid Build Coastguard Worker if ((arg1 == NULL) || (arg1->type != XPATH_NODESET) ||
11888*6777b538SAndroid Build Coastguard Worker (arg2 == NULL) || (arg2->type != XPATH_NODESET)) {
11889*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
11890*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
11891*6777b538SAndroid Build Coastguard Worker XP_ERROR0(XPATH_INVALID_TYPE);
11892*6777b538SAndroid Build Coastguard Worker }
11893*6777b538SAndroid Build Coastguard Worker if ((ctxt->context->opLimit != 0) &&
11894*6777b538SAndroid Build Coastguard Worker (((arg1->nodesetval != NULL) &&
11895*6777b538SAndroid Build Coastguard Worker (xmlXPathCheckOpLimit(ctxt,
11896*6777b538SAndroid Build Coastguard Worker arg1->nodesetval->nodeNr) < 0)) ||
11897*6777b538SAndroid Build Coastguard Worker ((arg2->nodesetval != NULL) &&
11898*6777b538SAndroid Build Coastguard Worker (xmlXPathCheckOpLimit(ctxt,
11899*6777b538SAndroid Build Coastguard Worker arg2->nodesetval->nodeNr) < 0)))) {
11900*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg1);
11901*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
11902*6777b538SAndroid Build Coastguard Worker break;
11903*6777b538SAndroid Build Coastguard Worker }
11904*6777b538SAndroid Build Coastguard Worker
11905*6777b538SAndroid Build Coastguard Worker if (((arg2->nodesetval != NULL) &&
11906*6777b538SAndroid Build Coastguard Worker (arg2->nodesetval->nodeNr != 0)))
11907*6777b538SAndroid Build Coastguard Worker {
11908*6777b538SAndroid Build Coastguard Worker arg1->nodesetval = xmlXPathNodeSetMerge(arg1->nodesetval,
11909*6777b538SAndroid Build Coastguard Worker arg2->nodesetval);
11910*6777b538SAndroid Build Coastguard Worker if (arg1->nodesetval == NULL)
11911*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
11912*6777b538SAndroid Build Coastguard Worker }
11913*6777b538SAndroid Build Coastguard Worker
11914*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, arg1);
11915*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, arg2);
11916*6777b538SAndroid Build Coastguard Worker break;
11917*6777b538SAndroid Build Coastguard Worker case XPATH_OP_ROOT:
11918*6777b538SAndroid Build Coastguard Worker xmlXPathRoot(ctxt);
11919*6777b538SAndroid Build Coastguard Worker break;
11920*6777b538SAndroid Build Coastguard Worker case XPATH_OP_NODE:
11921*6777b538SAndroid Build Coastguard Worker if (op->ch1 != -1)
11922*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11923*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11924*6777b538SAndroid Build Coastguard Worker if (op->ch2 != -1)
11925*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
11926*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11927*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewNodeSet(ctxt,
11928*6777b538SAndroid Build Coastguard Worker ctxt->context->node));
11929*6777b538SAndroid Build Coastguard Worker break;
11930*6777b538SAndroid Build Coastguard Worker case XPATH_OP_COLLECT:{
11931*6777b538SAndroid Build Coastguard Worker if (op->ch1 == -1)
11932*6777b538SAndroid Build Coastguard Worker break;
11933*6777b538SAndroid Build Coastguard Worker
11934*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11935*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
11936*6777b538SAndroid Build Coastguard Worker
11937*6777b538SAndroid Build Coastguard Worker total += xmlXPathNodeCollectAndTest(ctxt, op, NULL, NULL, 0);
11938*6777b538SAndroid Build Coastguard Worker break;
11939*6777b538SAndroid Build Coastguard Worker }
11940*6777b538SAndroid Build Coastguard Worker case XPATH_OP_VALUE:
11941*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheObjectCopy(ctxt, op->value4));
11942*6777b538SAndroid Build Coastguard Worker break;
11943*6777b538SAndroid Build Coastguard Worker case XPATH_OP_VARIABLE:{
11944*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr val;
11945*6777b538SAndroid Build Coastguard Worker
11946*6777b538SAndroid Build Coastguard Worker if (op->ch1 != -1)
11947*6777b538SAndroid Build Coastguard Worker total +=
11948*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11949*6777b538SAndroid Build Coastguard Worker if (op->value5 == NULL) {
11950*6777b538SAndroid Build Coastguard Worker val = xmlXPathVariableLookup(ctxt->context, op->value4);
11951*6777b538SAndroid Build Coastguard Worker if (val == NULL)
11952*6777b538SAndroid Build Coastguard Worker XP_ERROR0(XPATH_UNDEF_VARIABLE_ERROR);
11953*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, val);
11954*6777b538SAndroid Build Coastguard Worker } else {
11955*6777b538SAndroid Build Coastguard Worker const xmlChar *URI;
11956*6777b538SAndroid Build Coastguard Worker
11957*6777b538SAndroid Build Coastguard Worker URI = xmlXPathNsLookup(ctxt->context, op->value5);
11958*6777b538SAndroid Build Coastguard Worker if (URI == NULL) {
11959*6777b538SAndroid Build Coastguard Worker XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
11960*6777b538SAndroid Build Coastguard Worker break;
11961*6777b538SAndroid Build Coastguard Worker }
11962*6777b538SAndroid Build Coastguard Worker val = xmlXPathVariableLookupNS(ctxt->context,
11963*6777b538SAndroid Build Coastguard Worker op->value4, URI);
11964*6777b538SAndroid Build Coastguard Worker if (val == NULL)
11965*6777b538SAndroid Build Coastguard Worker XP_ERROR0(XPATH_UNDEF_VARIABLE_ERROR);
11966*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, val);
11967*6777b538SAndroid Build Coastguard Worker }
11968*6777b538SAndroid Build Coastguard Worker break;
11969*6777b538SAndroid Build Coastguard Worker }
11970*6777b538SAndroid Build Coastguard Worker case XPATH_OP_FUNCTION:{
11971*6777b538SAndroid Build Coastguard Worker xmlXPathFunction func;
11972*6777b538SAndroid Build Coastguard Worker const xmlChar *oldFunc, *oldFuncURI;
11973*6777b538SAndroid Build Coastguard Worker int i;
11974*6777b538SAndroid Build Coastguard Worker int frame;
11975*6777b538SAndroid Build Coastguard Worker
11976*6777b538SAndroid Build Coastguard Worker frame = ctxt->valueNr;
11977*6777b538SAndroid Build Coastguard Worker if (op->ch1 != -1) {
11978*6777b538SAndroid Build Coastguard Worker total +=
11979*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
11980*6777b538SAndroid Build Coastguard Worker if (ctxt->error != XPATH_EXPRESSION_OK)
11981*6777b538SAndroid Build Coastguard Worker break;
11982*6777b538SAndroid Build Coastguard Worker }
11983*6777b538SAndroid Build Coastguard Worker if (ctxt->valueNr < frame + op->value)
11984*6777b538SAndroid Build Coastguard Worker XP_ERROR0(XPATH_INVALID_OPERAND);
11985*6777b538SAndroid Build Coastguard Worker for (i = 0; i < op->value; i++) {
11986*6777b538SAndroid Build Coastguard Worker if (ctxt->valueTab[(ctxt->valueNr - 1) - i] == NULL)
11987*6777b538SAndroid Build Coastguard Worker XP_ERROR0(XPATH_INVALID_OPERAND);
11988*6777b538SAndroid Build Coastguard Worker }
11989*6777b538SAndroid Build Coastguard Worker if (op->cache != NULL)
11990*6777b538SAndroid Build Coastguard Worker func = op->cache;
11991*6777b538SAndroid Build Coastguard Worker else {
11992*6777b538SAndroid Build Coastguard Worker const xmlChar *URI = NULL;
11993*6777b538SAndroid Build Coastguard Worker
11994*6777b538SAndroid Build Coastguard Worker if (op->value5 == NULL)
11995*6777b538SAndroid Build Coastguard Worker func =
11996*6777b538SAndroid Build Coastguard Worker xmlXPathFunctionLookup(ctxt->context,
11997*6777b538SAndroid Build Coastguard Worker op->value4);
11998*6777b538SAndroid Build Coastguard Worker else {
11999*6777b538SAndroid Build Coastguard Worker URI = xmlXPathNsLookup(ctxt->context, op->value5);
12000*6777b538SAndroid Build Coastguard Worker if (URI == NULL)
12001*6777b538SAndroid Build Coastguard Worker XP_ERROR0(XPATH_UNDEF_PREFIX_ERROR);
12002*6777b538SAndroid Build Coastguard Worker func = xmlXPathFunctionLookupNS(ctxt->context,
12003*6777b538SAndroid Build Coastguard Worker op->value4, URI);
12004*6777b538SAndroid Build Coastguard Worker }
12005*6777b538SAndroid Build Coastguard Worker if (func == NULL)
12006*6777b538SAndroid Build Coastguard Worker XP_ERROR0(XPATH_UNKNOWN_FUNC_ERROR);
12007*6777b538SAndroid Build Coastguard Worker op->cache = func;
12008*6777b538SAndroid Build Coastguard Worker op->cacheURI = (void *) URI;
12009*6777b538SAndroid Build Coastguard Worker }
12010*6777b538SAndroid Build Coastguard Worker oldFunc = ctxt->context->function;
12011*6777b538SAndroid Build Coastguard Worker oldFuncURI = ctxt->context->functionURI;
12012*6777b538SAndroid Build Coastguard Worker ctxt->context->function = op->value4;
12013*6777b538SAndroid Build Coastguard Worker ctxt->context->functionURI = op->cacheURI;
12014*6777b538SAndroid Build Coastguard Worker func(ctxt, op->value);
12015*6777b538SAndroid Build Coastguard Worker ctxt->context->function = oldFunc;
12016*6777b538SAndroid Build Coastguard Worker ctxt->context->functionURI = oldFuncURI;
12017*6777b538SAndroid Build Coastguard Worker if ((ctxt->error == XPATH_EXPRESSION_OK) &&
12018*6777b538SAndroid Build Coastguard Worker (ctxt->valueNr != frame + 1))
12019*6777b538SAndroid Build Coastguard Worker XP_ERROR0(XPATH_STACK_ERROR);
12020*6777b538SAndroid Build Coastguard Worker break;
12021*6777b538SAndroid Build Coastguard Worker }
12022*6777b538SAndroid Build Coastguard Worker case XPATH_OP_ARG:
12023*6777b538SAndroid Build Coastguard Worker if (op->ch1 != -1) {
12024*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
12025*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
12026*6777b538SAndroid Build Coastguard Worker }
12027*6777b538SAndroid Build Coastguard Worker if (op->ch2 != -1) {
12028*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch2]);
12029*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
12030*6777b538SAndroid Build Coastguard Worker }
12031*6777b538SAndroid Build Coastguard Worker break;
12032*6777b538SAndroid Build Coastguard Worker case XPATH_OP_PREDICATE:
12033*6777b538SAndroid Build Coastguard Worker case XPATH_OP_FILTER:{
12034*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr obj;
12035*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr set;
12036*6777b538SAndroid Build Coastguard Worker
12037*6777b538SAndroid Build Coastguard Worker /*
12038*6777b538SAndroid Build Coastguard Worker * Optimization for ()[1] selection i.e. the first elem
12039*6777b538SAndroid Build Coastguard Worker */
12040*6777b538SAndroid Build Coastguard Worker if ((op->ch1 != -1) && (op->ch2 != -1) &&
12041*6777b538SAndroid Build Coastguard Worker #ifdef XP_OPTIMIZED_FILTER_FIRST
12042*6777b538SAndroid Build Coastguard Worker /*
12043*6777b538SAndroid Build Coastguard Worker * FILTER TODO: Can we assume that the inner processing
12044*6777b538SAndroid Build Coastguard Worker * will result in an ordered list if we have an
12045*6777b538SAndroid Build Coastguard Worker * XPATH_OP_FILTER?
12046*6777b538SAndroid Build Coastguard Worker * What about an additional field or flag on
12047*6777b538SAndroid Build Coastguard Worker * xmlXPathObject like @sorted ? This way we wouldn't need
12048*6777b538SAndroid Build Coastguard Worker * to assume anything, so it would be more robust and
12049*6777b538SAndroid Build Coastguard Worker * easier to optimize.
12050*6777b538SAndroid Build Coastguard Worker */
12051*6777b538SAndroid Build Coastguard Worker ((comp->steps[op->ch1].op == XPATH_OP_SORT) || /* 18 */
12052*6777b538SAndroid Build Coastguard Worker (comp->steps[op->ch1].op == XPATH_OP_FILTER)) && /* 17 */
12053*6777b538SAndroid Build Coastguard Worker #else
12054*6777b538SAndroid Build Coastguard Worker (comp->steps[op->ch1].op == XPATH_OP_SORT) &&
12055*6777b538SAndroid Build Coastguard Worker #endif
12056*6777b538SAndroid Build Coastguard Worker (comp->steps[op->ch2].op == XPATH_OP_VALUE)) { /* 12 */
12057*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr val;
12058*6777b538SAndroid Build Coastguard Worker
12059*6777b538SAndroid Build Coastguard Worker val = comp->steps[op->ch2].value4;
12060*6777b538SAndroid Build Coastguard Worker if ((val != NULL) && (val->type == XPATH_NUMBER) &&
12061*6777b538SAndroid Build Coastguard Worker (val->floatval == 1.0)) {
12062*6777b538SAndroid Build Coastguard Worker xmlNodePtr first = NULL;
12063*6777b538SAndroid Build Coastguard Worker
12064*6777b538SAndroid Build Coastguard Worker total +=
12065*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEvalFirst(ctxt,
12066*6777b538SAndroid Build Coastguard Worker &comp->steps[op->ch1],
12067*6777b538SAndroid Build Coastguard Worker &first);
12068*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
12069*6777b538SAndroid Build Coastguard Worker /*
12070*6777b538SAndroid Build Coastguard Worker * The nodeset should be in document order,
12071*6777b538SAndroid Build Coastguard Worker * Keep only the first value
12072*6777b538SAndroid Build Coastguard Worker */
12073*6777b538SAndroid Build Coastguard Worker if ((ctxt->value != NULL) &&
12074*6777b538SAndroid Build Coastguard Worker (ctxt->value->type == XPATH_NODESET) &&
12075*6777b538SAndroid Build Coastguard Worker (ctxt->value->nodesetval != NULL) &&
12076*6777b538SAndroid Build Coastguard Worker (ctxt->value->nodesetval->nodeNr > 1))
12077*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetClearFromPos(ctxt->value->nodesetval,
12078*6777b538SAndroid Build Coastguard Worker 1, 1);
12079*6777b538SAndroid Build Coastguard Worker break;
12080*6777b538SAndroid Build Coastguard Worker }
12081*6777b538SAndroid Build Coastguard Worker }
12082*6777b538SAndroid Build Coastguard Worker /*
12083*6777b538SAndroid Build Coastguard Worker * Optimization for ()[last()] selection i.e. the last elem
12084*6777b538SAndroid Build Coastguard Worker */
12085*6777b538SAndroid Build Coastguard Worker if ((op->ch1 != -1) && (op->ch2 != -1) &&
12086*6777b538SAndroid Build Coastguard Worker (comp->steps[op->ch1].op == XPATH_OP_SORT) &&
12087*6777b538SAndroid Build Coastguard Worker (comp->steps[op->ch2].op == XPATH_OP_SORT)) {
12088*6777b538SAndroid Build Coastguard Worker int f = comp->steps[op->ch2].ch1;
12089*6777b538SAndroid Build Coastguard Worker
12090*6777b538SAndroid Build Coastguard Worker if ((f != -1) &&
12091*6777b538SAndroid Build Coastguard Worker (comp->steps[f].op == XPATH_OP_FUNCTION) &&
12092*6777b538SAndroid Build Coastguard Worker (comp->steps[f].value5 == NULL) &&
12093*6777b538SAndroid Build Coastguard Worker (comp->steps[f].value == 0) &&
12094*6777b538SAndroid Build Coastguard Worker (comp->steps[f].value4 != NULL) &&
12095*6777b538SAndroid Build Coastguard Worker (xmlStrEqual
12096*6777b538SAndroid Build Coastguard Worker (comp->steps[f].value4, BAD_CAST "last"))) {
12097*6777b538SAndroid Build Coastguard Worker xmlNodePtr last = NULL;
12098*6777b538SAndroid Build Coastguard Worker
12099*6777b538SAndroid Build Coastguard Worker total +=
12100*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEvalLast(ctxt,
12101*6777b538SAndroid Build Coastguard Worker &comp->steps[op->ch1],
12102*6777b538SAndroid Build Coastguard Worker &last);
12103*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
12104*6777b538SAndroid Build Coastguard Worker /*
12105*6777b538SAndroid Build Coastguard Worker * The nodeset should be in document order,
12106*6777b538SAndroid Build Coastguard Worker * Keep only the last value
12107*6777b538SAndroid Build Coastguard Worker */
12108*6777b538SAndroid Build Coastguard Worker if ((ctxt->value != NULL) &&
12109*6777b538SAndroid Build Coastguard Worker (ctxt->value->type == XPATH_NODESET) &&
12110*6777b538SAndroid Build Coastguard Worker (ctxt->value->nodesetval != NULL) &&
12111*6777b538SAndroid Build Coastguard Worker (ctxt->value->nodesetval->nodeTab != NULL) &&
12112*6777b538SAndroid Build Coastguard Worker (ctxt->value->nodesetval->nodeNr > 1))
12113*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetKeepLast(ctxt->value->nodesetval);
12114*6777b538SAndroid Build Coastguard Worker break;
12115*6777b538SAndroid Build Coastguard Worker }
12116*6777b538SAndroid Build Coastguard Worker }
12117*6777b538SAndroid Build Coastguard Worker /*
12118*6777b538SAndroid Build Coastguard Worker * Process inner predicates first.
12119*6777b538SAndroid Build Coastguard Worker * Example "index[parent::book][1]":
12120*6777b538SAndroid Build Coastguard Worker * ...
12121*6777b538SAndroid Build Coastguard Worker * PREDICATE <-- we are here "[1]"
12122*6777b538SAndroid Build Coastguard Worker * PREDICATE <-- process "[parent::book]" first
12123*6777b538SAndroid Build Coastguard Worker * SORT
12124*6777b538SAndroid Build Coastguard Worker * COLLECT 'parent' 'name' 'node' book
12125*6777b538SAndroid Build Coastguard Worker * NODE
12126*6777b538SAndroid Build Coastguard Worker * ELEM Object is a number : 1
12127*6777b538SAndroid Build Coastguard Worker */
12128*6777b538SAndroid Build Coastguard Worker if (op->ch1 != -1)
12129*6777b538SAndroid Build Coastguard Worker total +=
12130*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
12131*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
12132*6777b538SAndroid Build Coastguard Worker if (op->ch2 == -1)
12133*6777b538SAndroid Build Coastguard Worker break;
12134*6777b538SAndroid Build Coastguard Worker if (ctxt->value == NULL)
12135*6777b538SAndroid Build Coastguard Worker break;
12136*6777b538SAndroid Build Coastguard Worker
12137*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
12138*6777b538SAndroid Build Coastguard Worker /*
12139*6777b538SAndroid Build Coastguard Worker * Hum are we filtering the result of an XPointer expression
12140*6777b538SAndroid Build Coastguard Worker */
12141*6777b538SAndroid Build Coastguard Worker if (ctxt->value->type == XPATH_LOCATIONSET) {
12142*6777b538SAndroid Build Coastguard Worker xmlLocationSetPtr locset = ctxt->value->user;
12143*6777b538SAndroid Build Coastguard Worker xmlXPathLocationSetFilter(ctxt, locset, op->ch2,
12144*6777b538SAndroid Build Coastguard Worker 1, locset->locNr);
12145*6777b538SAndroid Build Coastguard Worker break;
12146*6777b538SAndroid Build Coastguard Worker }
12147*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_XPTR_LOCS_ENABLED */
12148*6777b538SAndroid Build Coastguard Worker
12149*6777b538SAndroid Build Coastguard Worker /*
12150*6777b538SAndroid Build Coastguard Worker * In case of errors, xmlXPathNodeSetFilter can pop additional
12151*6777b538SAndroid Build Coastguard Worker * nodes from the stack. We have to temporarily remove the
12152*6777b538SAndroid Build Coastguard Worker * nodeset object from the stack to avoid freeing it
12153*6777b538SAndroid Build Coastguard Worker * prematurely.
12154*6777b538SAndroid Build Coastguard Worker */
12155*6777b538SAndroid Build Coastguard Worker CHECK_TYPE0(XPATH_NODESET);
12156*6777b538SAndroid Build Coastguard Worker obj = valuePop(ctxt);
12157*6777b538SAndroid Build Coastguard Worker set = obj->nodesetval;
12158*6777b538SAndroid Build Coastguard Worker if (set != NULL)
12159*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetFilter(ctxt, set, op->ch2,
12160*6777b538SAndroid Build Coastguard Worker 1, set->nodeNr, 1);
12161*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, obj);
12162*6777b538SAndroid Build Coastguard Worker break;
12163*6777b538SAndroid Build Coastguard Worker }
12164*6777b538SAndroid Build Coastguard Worker case XPATH_OP_SORT:
12165*6777b538SAndroid Build Coastguard Worker if (op->ch1 != -1)
12166*6777b538SAndroid Build Coastguard Worker total += xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
12167*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
12168*6777b538SAndroid Build Coastguard Worker if ((ctxt->value != NULL) &&
12169*6777b538SAndroid Build Coastguard Worker (ctxt->value->type == XPATH_NODESET) &&
12170*6777b538SAndroid Build Coastguard Worker (ctxt->value->nodesetval != NULL) &&
12171*6777b538SAndroid Build Coastguard Worker (ctxt->value->nodesetval->nodeNr > 1))
12172*6777b538SAndroid Build Coastguard Worker {
12173*6777b538SAndroid Build Coastguard Worker xmlXPathNodeSetSort(ctxt->value->nodesetval);
12174*6777b538SAndroid Build Coastguard Worker }
12175*6777b538SAndroid Build Coastguard Worker break;
12176*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
12177*6777b538SAndroid Build Coastguard Worker case XPATH_OP_RANGETO:{
12178*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr range;
12179*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr res, obj;
12180*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr tmp;
12181*6777b538SAndroid Build Coastguard Worker xmlLocationSetPtr newlocset = NULL;
12182*6777b538SAndroid Build Coastguard Worker xmlLocationSetPtr oldlocset;
12183*6777b538SAndroid Build Coastguard Worker xmlNodeSetPtr oldset;
12184*6777b538SAndroid Build Coastguard Worker xmlNodePtr oldnode = ctxt->context->node;
12185*6777b538SAndroid Build Coastguard Worker int oldcs = ctxt->context->contextSize;
12186*6777b538SAndroid Build Coastguard Worker int oldpp = ctxt->context->proximityPosition;
12187*6777b538SAndroid Build Coastguard Worker int i, j;
12188*6777b538SAndroid Build Coastguard Worker
12189*6777b538SAndroid Build Coastguard Worker if (op->ch1 != -1) {
12190*6777b538SAndroid Build Coastguard Worker total +=
12191*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEval(ctxt, &comp->steps[op->ch1]);
12192*6777b538SAndroid Build Coastguard Worker CHECK_ERROR0;
12193*6777b538SAndroid Build Coastguard Worker }
12194*6777b538SAndroid Build Coastguard Worker if (ctxt->value == NULL) {
12195*6777b538SAndroid Build Coastguard Worker XP_ERROR0(XPATH_INVALID_OPERAND);
12196*6777b538SAndroid Build Coastguard Worker }
12197*6777b538SAndroid Build Coastguard Worker if (op->ch2 == -1)
12198*6777b538SAndroid Build Coastguard Worker break;
12199*6777b538SAndroid Build Coastguard Worker
12200*6777b538SAndroid Build Coastguard Worker if (ctxt->value->type == XPATH_LOCATIONSET) {
12201*6777b538SAndroid Build Coastguard Worker /*
12202*6777b538SAndroid Build Coastguard Worker * Extract the old locset, and then evaluate the result of the
12203*6777b538SAndroid Build Coastguard Worker * expression for all the element in the locset. use it to grow
12204*6777b538SAndroid Build Coastguard Worker * up a new locset.
12205*6777b538SAndroid Build Coastguard Worker */
12206*6777b538SAndroid Build Coastguard Worker CHECK_TYPE0(XPATH_LOCATIONSET);
12207*6777b538SAndroid Build Coastguard Worker
12208*6777b538SAndroid Build Coastguard Worker if ((ctxt->value->user == NULL) ||
12209*6777b538SAndroid Build Coastguard Worker (((xmlLocationSetPtr) ctxt->value->user)->locNr == 0))
12210*6777b538SAndroid Build Coastguard Worker break;
12211*6777b538SAndroid Build Coastguard Worker
12212*6777b538SAndroid Build Coastguard Worker obj = valuePop(ctxt);
12213*6777b538SAndroid Build Coastguard Worker oldlocset = obj->user;
12214*6777b538SAndroid Build Coastguard Worker
12215*6777b538SAndroid Build Coastguard Worker newlocset = xmlXPtrLocationSetCreate(NULL);
12216*6777b538SAndroid Build Coastguard Worker
12217*6777b538SAndroid Build Coastguard Worker for (i = 0; i < oldlocset->locNr; i++) {
12218*6777b538SAndroid Build Coastguard Worker /*
12219*6777b538SAndroid Build Coastguard Worker * Run the evaluation with a node list made of a
12220*6777b538SAndroid Build Coastguard Worker * single item in the nodelocset.
12221*6777b538SAndroid Build Coastguard Worker */
12222*6777b538SAndroid Build Coastguard Worker ctxt->context->node = oldlocset->locTab[i]->user;
12223*6777b538SAndroid Build Coastguard Worker ctxt->context->contextSize = oldlocset->locNr;
12224*6777b538SAndroid Build Coastguard Worker ctxt->context->proximityPosition = i + 1;
12225*6777b538SAndroid Build Coastguard Worker tmp = xmlXPathCacheNewNodeSet(ctxt,
12226*6777b538SAndroid Build Coastguard Worker ctxt->context->node);
12227*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, tmp);
12228*6777b538SAndroid Build Coastguard Worker
12229*6777b538SAndroid Build Coastguard Worker if (op->ch2 != -1)
12230*6777b538SAndroid Build Coastguard Worker total +=
12231*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEval(ctxt,
12232*6777b538SAndroid Build Coastguard Worker &comp->steps[op->ch2]);
12233*6777b538SAndroid Build Coastguard Worker if (ctxt->error != XPATH_EXPRESSION_OK) {
12234*6777b538SAndroid Build Coastguard Worker xmlXPtrFreeLocationSet(newlocset);
12235*6777b538SAndroid Build Coastguard Worker goto rangeto_error;
12236*6777b538SAndroid Build Coastguard Worker }
12237*6777b538SAndroid Build Coastguard Worker
12238*6777b538SAndroid Build Coastguard Worker res = valuePop(ctxt);
12239*6777b538SAndroid Build Coastguard Worker if (res->type == XPATH_LOCATIONSET) {
12240*6777b538SAndroid Build Coastguard Worker xmlLocationSetPtr rloc =
12241*6777b538SAndroid Build Coastguard Worker (xmlLocationSetPtr)res->user;
12242*6777b538SAndroid Build Coastguard Worker for (j=0; j<rloc->locNr; j++) {
12243*6777b538SAndroid Build Coastguard Worker range = xmlXPtrNewRange(
12244*6777b538SAndroid Build Coastguard Worker oldlocset->locTab[i]->user,
12245*6777b538SAndroid Build Coastguard Worker oldlocset->locTab[i]->index,
12246*6777b538SAndroid Build Coastguard Worker rloc->locTab[j]->user2,
12247*6777b538SAndroid Build Coastguard Worker rloc->locTab[j]->index2);
12248*6777b538SAndroid Build Coastguard Worker if (range != NULL) {
12249*6777b538SAndroid Build Coastguard Worker xmlXPtrLocationSetAdd(newlocset, range);
12250*6777b538SAndroid Build Coastguard Worker }
12251*6777b538SAndroid Build Coastguard Worker }
12252*6777b538SAndroid Build Coastguard Worker } else {
12253*6777b538SAndroid Build Coastguard Worker range = xmlXPtrNewRangeNodeObject(
12254*6777b538SAndroid Build Coastguard Worker (xmlNodePtr)oldlocset->locTab[i]->user, res);
12255*6777b538SAndroid Build Coastguard Worker if (range != NULL) {
12256*6777b538SAndroid Build Coastguard Worker xmlXPtrLocationSetAdd(newlocset,range);
12257*6777b538SAndroid Build Coastguard Worker }
12258*6777b538SAndroid Build Coastguard Worker }
12259*6777b538SAndroid Build Coastguard Worker
12260*6777b538SAndroid Build Coastguard Worker /*
12261*6777b538SAndroid Build Coastguard Worker * Cleanup
12262*6777b538SAndroid Build Coastguard Worker */
12263*6777b538SAndroid Build Coastguard Worker if (res != NULL) {
12264*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, res);
12265*6777b538SAndroid Build Coastguard Worker }
12266*6777b538SAndroid Build Coastguard Worker if (ctxt->value == tmp) {
12267*6777b538SAndroid Build Coastguard Worker res = valuePop(ctxt);
12268*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, res);
12269*6777b538SAndroid Build Coastguard Worker }
12270*6777b538SAndroid Build Coastguard Worker }
12271*6777b538SAndroid Build Coastguard Worker } else { /* Not a location set */
12272*6777b538SAndroid Build Coastguard Worker CHECK_TYPE0(XPATH_NODESET);
12273*6777b538SAndroid Build Coastguard Worker obj = valuePop(ctxt);
12274*6777b538SAndroid Build Coastguard Worker oldset = obj->nodesetval;
12275*6777b538SAndroid Build Coastguard Worker
12276*6777b538SAndroid Build Coastguard Worker newlocset = xmlXPtrLocationSetCreate(NULL);
12277*6777b538SAndroid Build Coastguard Worker
12278*6777b538SAndroid Build Coastguard Worker if (oldset != NULL) {
12279*6777b538SAndroid Build Coastguard Worker for (i = 0; i < oldset->nodeNr; i++) {
12280*6777b538SAndroid Build Coastguard Worker /*
12281*6777b538SAndroid Build Coastguard Worker * Run the evaluation with a node list made of a single item
12282*6777b538SAndroid Build Coastguard Worker * in the nodeset.
12283*6777b538SAndroid Build Coastguard Worker */
12284*6777b538SAndroid Build Coastguard Worker ctxt->context->node = oldset->nodeTab[i];
12285*6777b538SAndroid Build Coastguard Worker /*
12286*6777b538SAndroid Build Coastguard Worker * OPTIMIZE TODO: Avoid recreation for every iteration.
12287*6777b538SAndroid Build Coastguard Worker */
12288*6777b538SAndroid Build Coastguard Worker tmp = xmlXPathCacheNewNodeSet(ctxt,
12289*6777b538SAndroid Build Coastguard Worker ctxt->context->node);
12290*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, tmp);
12291*6777b538SAndroid Build Coastguard Worker
12292*6777b538SAndroid Build Coastguard Worker if (op->ch2 != -1)
12293*6777b538SAndroid Build Coastguard Worker total +=
12294*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEval(ctxt,
12295*6777b538SAndroid Build Coastguard Worker &comp->steps[op->ch2]);
12296*6777b538SAndroid Build Coastguard Worker if (ctxt->error != XPATH_EXPRESSION_OK) {
12297*6777b538SAndroid Build Coastguard Worker xmlXPtrFreeLocationSet(newlocset);
12298*6777b538SAndroid Build Coastguard Worker goto rangeto_error;
12299*6777b538SAndroid Build Coastguard Worker }
12300*6777b538SAndroid Build Coastguard Worker
12301*6777b538SAndroid Build Coastguard Worker res = valuePop(ctxt);
12302*6777b538SAndroid Build Coastguard Worker range =
12303*6777b538SAndroid Build Coastguard Worker xmlXPtrNewRangeNodeObject(oldset->nodeTab[i],
12304*6777b538SAndroid Build Coastguard Worker res);
12305*6777b538SAndroid Build Coastguard Worker if (range != NULL) {
12306*6777b538SAndroid Build Coastguard Worker xmlXPtrLocationSetAdd(newlocset, range);
12307*6777b538SAndroid Build Coastguard Worker }
12308*6777b538SAndroid Build Coastguard Worker
12309*6777b538SAndroid Build Coastguard Worker /*
12310*6777b538SAndroid Build Coastguard Worker * Cleanup
12311*6777b538SAndroid Build Coastguard Worker */
12312*6777b538SAndroid Build Coastguard Worker if (res != NULL) {
12313*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, res);
12314*6777b538SAndroid Build Coastguard Worker }
12315*6777b538SAndroid Build Coastguard Worker if (ctxt->value == tmp) {
12316*6777b538SAndroid Build Coastguard Worker res = valuePop(ctxt);
12317*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, res);
12318*6777b538SAndroid Build Coastguard Worker }
12319*6777b538SAndroid Build Coastguard Worker }
12320*6777b538SAndroid Build Coastguard Worker }
12321*6777b538SAndroid Build Coastguard Worker }
12322*6777b538SAndroid Build Coastguard Worker
12323*6777b538SAndroid Build Coastguard Worker /*
12324*6777b538SAndroid Build Coastguard Worker * The result is used as the new evaluation set.
12325*6777b538SAndroid Build Coastguard Worker */
12326*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPtrWrapLocationSet(newlocset));
12327*6777b538SAndroid Build Coastguard Worker rangeto_error:
12328*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, obj);
12329*6777b538SAndroid Build Coastguard Worker ctxt->context->node = oldnode;
12330*6777b538SAndroid Build Coastguard Worker ctxt->context->contextSize = oldcs;
12331*6777b538SAndroid Build Coastguard Worker ctxt->context->proximityPosition = oldpp;
12332*6777b538SAndroid Build Coastguard Worker break;
12333*6777b538SAndroid Build Coastguard Worker }
12334*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_XPTR_LOCS_ENABLED */
12335*6777b538SAndroid Build Coastguard Worker default:
12336*6777b538SAndroid Build Coastguard Worker XP_ERROR0(XPATH_INVALID_OPERAND);
12337*6777b538SAndroid Build Coastguard Worker break;
12338*6777b538SAndroid Build Coastguard Worker }
12339*6777b538SAndroid Build Coastguard Worker
12340*6777b538SAndroid Build Coastguard Worker ctxt->context->depth -= 1;
12341*6777b538SAndroid Build Coastguard Worker return (total);
12342*6777b538SAndroid Build Coastguard Worker }
12343*6777b538SAndroid Build Coastguard Worker
12344*6777b538SAndroid Build Coastguard Worker /**
12345*6777b538SAndroid Build Coastguard Worker * xmlXPathCompOpEvalToBoolean:
12346*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath parser context
12347*6777b538SAndroid Build Coastguard Worker *
12348*6777b538SAndroid Build Coastguard Worker * Evaluates if the expression evaluates to true.
12349*6777b538SAndroid Build Coastguard Worker *
12350*6777b538SAndroid Build Coastguard Worker * Returns 1 if true, 0 if false and -1 on API or internal errors.
12351*6777b538SAndroid Build Coastguard Worker */
12352*6777b538SAndroid Build Coastguard Worker static int
xmlXPathCompOpEvalToBoolean(xmlXPathParserContextPtr ctxt,xmlXPathStepOpPtr op,int isPredicate)12353*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEvalToBoolean(xmlXPathParserContextPtr ctxt,
12354*6777b538SAndroid Build Coastguard Worker xmlXPathStepOpPtr op,
12355*6777b538SAndroid Build Coastguard Worker int isPredicate)
12356*6777b538SAndroid Build Coastguard Worker {
12357*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr resObj = NULL;
12358*6777b538SAndroid Build Coastguard Worker
12359*6777b538SAndroid Build Coastguard Worker start:
12360*6777b538SAndroid Build Coastguard Worker if (OP_LIMIT_EXCEEDED(ctxt, 1))
12361*6777b538SAndroid Build Coastguard Worker return(0);
12362*6777b538SAndroid Build Coastguard Worker /* comp = ctxt->comp; */
12363*6777b538SAndroid Build Coastguard Worker switch (op->op) {
12364*6777b538SAndroid Build Coastguard Worker case XPATH_OP_END:
12365*6777b538SAndroid Build Coastguard Worker return (0);
12366*6777b538SAndroid Build Coastguard Worker case XPATH_OP_VALUE:
12367*6777b538SAndroid Build Coastguard Worker resObj = (xmlXPathObjectPtr) op->value4;
12368*6777b538SAndroid Build Coastguard Worker if (isPredicate)
12369*6777b538SAndroid Build Coastguard Worker return(xmlXPathEvaluatePredicateResult(ctxt, resObj));
12370*6777b538SAndroid Build Coastguard Worker return(xmlXPathCastToBoolean(resObj));
12371*6777b538SAndroid Build Coastguard Worker case XPATH_OP_SORT:
12372*6777b538SAndroid Build Coastguard Worker /*
12373*6777b538SAndroid Build Coastguard Worker * We don't need sorting for boolean results. Skip this one.
12374*6777b538SAndroid Build Coastguard Worker */
12375*6777b538SAndroid Build Coastguard Worker if (op->ch1 != -1) {
12376*6777b538SAndroid Build Coastguard Worker op = &ctxt->comp->steps[op->ch1];
12377*6777b538SAndroid Build Coastguard Worker goto start;
12378*6777b538SAndroid Build Coastguard Worker }
12379*6777b538SAndroid Build Coastguard Worker return(0);
12380*6777b538SAndroid Build Coastguard Worker case XPATH_OP_COLLECT:
12381*6777b538SAndroid Build Coastguard Worker if (op->ch1 == -1)
12382*6777b538SAndroid Build Coastguard Worker return(0);
12383*6777b538SAndroid Build Coastguard Worker
12384*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEval(ctxt, &ctxt->comp->steps[op->ch1]);
12385*6777b538SAndroid Build Coastguard Worker if (ctxt->error != XPATH_EXPRESSION_OK)
12386*6777b538SAndroid Build Coastguard Worker return(-1);
12387*6777b538SAndroid Build Coastguard Worker
12388*6777b538SAndroid Build Coastguard Worker xmlXPathNodeCollectAndTest(ctxt, op, NULL, NULL, 1);
12389*6777b538SAndroid Build Coastguard Worker if (ctxt->error != XPATH_EXPRESSION_OK)
12390*6777b538SAndroid Build Coastguard Worker return(-1);
12391*6777b538SAndroid Build Coastguard Worker
12392*6777b538SAndroid Build Coastguard Worker resObj = valuePop(ctxt);
12393*6777b538SAndroid Build Coastguard Worker if (resObj == NULL)
12394*6777b538SAndroid Build Coastguard Worker return(-1);
12395*6777b538SAndroid Build Coastguard Worker break;
12396*6777b538SAndroid Build Coastguard Worker default:
12397*6777b538SAndroid Build Coastguard Worker /*
12398*6777b538SAndroid Build Coastguard Worker * Fallback to call xmlXPathCompOpEval().
12399*6777b538SAndroid Build Coastguard Worker */
12400*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEval(ctxt, op);
12401*6777b538SAndroid Build Coastguard Worker if (ctxt->error != XPATH_EXPRESSION_OK)
12402*6777b538SAndroid Build Coastguard Worker return(-1);
12403*6777b538SAndroid Build Coastguard Worker
12404*6777b538SAndroid Build Coastguard Worker resObj = valuePop(ctxt);
12405*6777b538SAndroid Build Coastguard Worker if (resObj == NULL)
12406*6777b538SAndroid Build Coastguard Worker return(-1);
12407*6777b538SAndroid Build Coastguard Worker break;
12408*6777b538SAndroid Build Coastguard Worker }
12409*6777b538SAndroid Build Coastguard Worker
12410*6777b538SAndroid Build Coastguard Worker if (resObj) {
12411*6777b538SAndroid Build Coastguard Worker int res;
12412*6777b538SAndroid Build Coastguard Worker
12413*6777b538SAndroid Build Coastguard Worker if (resObj->type == XPATH_BOOLEAN) {
12414*6777b538SAndroid Build Coastguard Worker res = resObj->boolval;
12415*6777b538SAndroid Build Coastguard Worker } else if (isPredicate) {
12416*6777b538SAndroid Build Coastguard Worker /*
12417*6777b538SAndroid Build Coastguard Worker * For predicates a result of type "number" is handled
12418*6777b538SAndroid Build Coastguard Worker * differently:
12419*6777b538SAndroid Build Coastguard Worker * SPEC XPath 1.0:
12420*6777b538SAndroid Build Coastguard Worker * "If the result is a number, the result will be converted
12421*6777b538SAndroid Build Coastguard Worker * to true if the number is equal to the context position
12422*6777b538SAndroid Build Coastguard Worker * and will be converted to false otherwise;"
12423*6777b538SAndroid Build Coastguard Worker */
12424*6777b538SAndroid Build Coastguard Worker res = xmlXPathEvaluatePredicateResult(ctxt, resObj);
12425*6777b538SAndroid Build Coastguard Worker } else {
12426*6777b538SAndroid Build Coastguard Worker res = xmlXPathCastToBoolean(resObj);
12427*6777b538SAndroid Build Coastguard Worker }
12428*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, resObj);
12429*6777b538SAndroid Build Coastguard Worker return(res);
12430*6777b538SAndroid Build Coastguard Worker }
12431*6777b538SAndroid Build Coastguard Worker
12432*6777b538SAndroid Build Coastguard Worker return(0);
12433*6777b538SAndroid Build Coastguard Worker }
12434*6777b538SAndroid Build Coastguard Worker
12435*6777b538SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
12436*6777b538SAndroid Build Coastguard Worker /**
12437*6777b538SAndroid Build Coastguard Worker * xmlXPathRunStreamEval:
12438*6777b538SAndroid Build Coastguard Worker * @pctxt: the XPath parser context with the compiled expression
12439*6777b538SAndroid Build Coastguard Worker *
12440*6777b538SAndroid Build Coastguard Worker * Evaluate the Precompiled Streamable XPath expression in the given context.
12441*6777b538SAndroid Build Coastguard Worker */
12442*6777b538SAndroid Build Coastguard Worker static int
xmlXPathRunStreamEval(xmlXPathParserContextPtr pctxt,xmlPatternPtr comp,xmlXPathObjectPtr * resultSeq,int toBool)12443*6777b538SAndroid Build Coastguard Worker xmlXPathRunStreamEval(xmlXPathParserContextPtr pctxt, xmlPatternPtr comp,
12444*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr *resultSeq, int toBool)
12445*6777b538SAndroid Build Coastguard Worker {
12446*6777b538SAndroid Build Coastguard Worker int max_depth, min_depth;
12447*6777b538SAndroid Build Coastguard Worker int from_root;
12448*6777b538SAndroid Build Coastguard Worker int ret, depth;
12449*6777b538SAndroid Build Coastguard Worker int eval_all_nodes;
12450*6777b538SAndroid Build Coastguard Worker xmlNodePtr cur = NULL, limit = NULL;
12451*6777b538SAndroid Build Coastguard Worker xmlStreamCtxtPtr patstream = NULL;
12452*6777b538SAndroid Build Coastguard Worker xmlXPathContextPtr ctxt = pctxt->context;
12453*6777b538SAndroid Build Coastguard Worker
12454*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (comp == NULL))
12455*6777b538SAndroid Build Coastguard Worker return(-1);
12456*6777b538SAndroid Build Coastguard Worker max_depth = xmlPatternMaxDepth(comp);
12457*6777b538SAndroid Build Coastguard Worker if (max_depth == -1)
12458*6777b538SAndroid Build Coastguard Worker return(-1);
12459*6777b538SAndroid Build Coastguard Worker if (max_depth == -2)
12460*6777b538SAndroid Build Coastguard Worker max_depth = 10000;
12461*6777b538SAndroid Build Coastguard Worker min_depth = xmlPatternMinDepth(comp);
12462*6777b538SAndroid Build Coastguard Worker if (min_depth == -1)
12463*6777b538SAndroid Build Coastguard Worker return(-1);
12464*6777b538SAndroid Build Coastguard Worker from_root = xmlPatternFromRoot(comp);
12465*6777b538SAndroid Build Coastguard Worker if (from_root < 0)
12466*6777b538SAndroid Build Coastguard Worker return(-1);
12467*6777b538SAndroid Build Coastguard Worker #if 0
12468*6777b538SAndroid Build Coastguard Worker printf("stream eval: depth %d from root %d\n", max_depth, from_root);
12469*6777b538SAndroid Build Coastguard Worker #endif
12470*6777b538SAndroid Build Coastguard Worker
12471*6777b538SAndroid Build Coastguard Worker if (! toBool) {
12472*6777b538SAndroid Build Coastguard Worker if (resultSeq == NULL)
12473*6777b538SAndroid Build Coastguard Worker return(-1);
12474*6777b538SAndroid Build Coastguard Worker *resultSeq = xmlXPathCacheNewNodeSet(pctxt, NULL);
12475*6777b538SAndroid Build Coastguard Worker if (*resultSeq == NULL)
12476*6777b538SAndroid Build Coastguard Worker return(-1);
12477*6777b538SAndroid Build Coastguard Worker }
12478*6777b538SAndroid Build Coastguard Worker
12479*6777b538SAndroid Build Coastguard Worker /*
12480*6777b538SAndroid Build Coastguard Worker * handle the special cases of "/" amd "." being matched
12481*6777b538SAndroid Build Coastguard Worker */
12482*6777b538SAndroid Build Coastguard Worker if (min_depth == 0) {
12483*6777b538SAndroid Build Coastguard Worker int res;
12484*6777b538SAndroid Build Coastguard Worker
12485*6777b538SAndroid Build Coastguard Worker if (from_root) {
12486*6777b538SAndroid Build Coastguard Worker /* Select "/" */
12487*6777b538SAndroid Build Coastguard Worker if (toBool)
12488*6777b538SAndroid Build Coastguard Worker return(1);
12489*6777b538SAndroid Build Coastguard Worker res = xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval,
12490*6777b538SAndroid Build Coastguard Worker (xmlNodePtr) ctxt->doc);
12491*6777b538SAndroid Build Coastguard Worker } else {
12492*6777b538SAndroid Build Coastguard Worker /* Select "self::node()" */
12493*6777b538SAndroid Build Coastguard Worker if (toBool)
12494*6777b538SAndroid Build Coastguard Worker return(1);
12495*6777b538SAndroid Build Coastguard Worker res = xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval,
12496*6777b538SAndroid Build Coastguard Worker ctxt->node);
12497*6777b538SAndroid Build Coastguard Worker }
12498*6777b538SAndroid Build Coastguard Worker
12499*6777b538SAndroid Build Coastguard Worker if (res < 0)
12500*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
12501*6777b538SAndroid Build Coastguard Worker }
12502*6777b538SAndroid Build Coastguard Worker if (max_depth == 0) {
12503*6777b538SAndroid Build Coastguard Worker return(0);
12504*6777b538SAndroid Build Coastguard Worker }
12505*6777b538SAndroid Build Coastguard Worker
12506*6777b538SAndroid Build Coastguard Worker if (from_root) {
12507*6777b538SAndroid Build Coastguard Worker cur = (xmlNodePtr)ctxt->doc;
12508*6777b538SAndroid Build Coastguard Worker } else if (ctxt->node != NULL) {
12509*6777b538SAndroid Build Coastguard Worker switch (ctxt->node->type) {
12510*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
12511*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_NODE:
12512*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_FRAG_NODE:
12513*6777b538SAndroid Build Coastguard Worker case XML_HTML_DOCUMENT_NODE:
12514*6777b538SAndroid Build Coastguard Worker cur = ctxt->node;
12515*6777b538SAndroid Build Coastguard Worker break;
12516*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_NODE:
12517*6777b538SAndroid Build Coastguard Worker case XML_TEXT_NODE:
12518*6777b538SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
12519*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_REF_NODE:
12520*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_NODE:
12521*6777b538SAndroid Build Coastguard Worker case XML_PI_NODE:
12522*6777b538SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
12523*6777b538SAndroid Build Coastguard Worker case XML_NOTATION_NODE:
12524*6777b538SAndroid Build Coastguard Worker case XML_DTD_NODE:
12525*6777b538SAndroid Build Coastguard Worker case XML_DOCUMENT_TYPE_NODE:
12526*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_DECL:
12527*6777b538SAndroid Build Coastguard Worker case XML_ATTRIBUTE_DECL:
12528*6777b538SAndroid Build Coastguard Worker case XML_ENTITY_DECL:
12529*6777b538SAndroid Build Coastguard Worker case XML_NAMESPACE_DECL:
12530*6777b538SAndroid Build Coastguard Worker case XML_XINCLUDE_START:
12531*6777b538SAndroid Build Coastguard Worker case XML_XINCLUDE_END:
12532*6777b538SAndroid Build Coastguard Worker break;
12533*6777b538SAndroid Build Coastguard Worker }
12534*6777b538SAndroid Build Coastguard Worker limit = cur;
12535*6777b538SAndroid Build Coastguard Worker }
12536*6777b538SAndroid Build Coastguard Worker if (cur == NULL) {
12537*6777b538SAndroid Build Coastguard Worker return(0);
12538*6777b538SAndroid Build Coastguard Worker }
12539*6777b538SAndroid Build Coastguard Worker
12540*6777b538SAndroid Build Coastguard Worker patstream = xmlPatternGetStreamCtxt(comp);
12541*6777b538SAndroid Build Coastguard Worker if (patstream == NULL) {
12542*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
12543*6777b538SAndroid Build Coastguard Worker return(-1);
12544*6777b538SAndroid Build Coastguard Worker }
12545*6777b538SAndroid Build Coastguard Worker
12546*6777b538SAndroid Build Coastguard Worker eval_all_nodes = xmlStreamWantsAnyNode(patstream);
12547*6777b538SAndroid Build Coastguard Worker
12548*6777b538SAndroid Build Coastguard Worker if (from_root) {
12549*6777b538SAndroid Build Coastguard Worker ret = xmlStreamPush(patstream, NULL, NULL);
12550*6777b538SAndroid Build Coastguard Worker if (ret < 0) {
12551*6777b538SAndroid Build Coastguard Worker } else if (ret == 1) {
12552*6777b538SAndroid Build Coastguard Worker if (toBool)
12553*6777b538SAndroid Build Coastguard Worker goto return_1;
12554*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval, cur) < 0)
12555*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
12556*6777b538SAndroid Build Coastguard Worker }
12557*6777b538SAndroid Build Coastguard Worker }
12558*6777b538SAndroid Build Coastguard Worker depth = 0;
12559*6777b538SAndroid Build Coastguard Worker goto scan_children;
12560*6777b538SAndroid Build Coastguard Worker next_node:
12561*6777b538SAndroid Build Coastguard Worker do {
12562*6777b538SAndroid Build Coastguard Worker if (ctxt->opLimit != 0) {
12563*6777b538SAndroid Build Coastguard Worker if (ctxt->opCount >= ctxt->opLimit) {
12564*6777b538SAndroid Build Coastguard Worker xmlXPathErr(ctxt, XPATH_RECURSION_LIMIT_EXCEEDED);
12565*6777b538SAndroid Build Coastguard Worker xmlFreeStreamCtxt(patstream);
12566*6777b538SAndroid Build Coastguard Worker return(-1);
12567*6777b538SAndroid Build Coastguard Worker }
12568*6777b538SAndroid Build Coastguard Worker ctxt->opCount++;
12569*6777b538SAndroid Build Coastguard Worker }
12570*6777b538SAndroid Build Coastguard Worker
12571*6777b538SAndroid Build Coastguard Worker switch (cur->type) {
12572*6777b538SAndroid Build Coastguard Worker case XML_ELEMENT_NODE:
12573*6777b538SAndroid Build Coastguard Worker case XML_TEXT_NODE:
12574*6777b538SAndroid Build Coastguard Worker case XML_CDATA_SECTION_NODE:
12575*6777b538SAndroid Build Coastguard Worker case XML_COMMENT_NODE:
12576*6777b538SAndroid Build Coastguard Worker case XML_PI_NODE:
12577*6777b538SAndroid Build Coastguard Worker if (cur->type == XML_ELEMENT_NODE) {
12578*6777b538SAndroid Build Coastguard Worker ret = xmlStreamPush(patstream, cur->name,
12579*6777b538SAndroid Build Coastguard Worker (cur->ns ? cur->ns->href : NULL));
12580*6777b538SAndroid Build Coastguard Worker } else if (eval_all_nodes)
12581*6777b538SAndroid Build Coastguard Worker ret = xmlStreamPushNode(patstream, NULL, NULL, cur->type);
12582*6777b538SAndroid Build Coastguard Worker else
12583*6777b538SAndroid Build Coastguard Worker break;
12584*6777b538SAndroid Build Coastguard Worker
12585*6777b538SAndroid Build Coastguard Worker if (ret < 0) {
12586*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
12587*6777b538SAndroid Build Coastguard Worker } else if (ret == 1) {
12588*6777b538SAndroid Build Coastguard Worker if (toBool)
12589*6777b538SAndroid Build Coastguard Worker goto return_1;
12590*6777b538SAndroid Build Coastguard Worker if (xmlXPathNodeSetAddUnique((*resultSeq)->nodesetval,
12591*6777b538SAndroid Build Coastguard Worker cur) < 0)
12592*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(pctxt);
12593*6777b538SAndroid Build Coastguard Worker }
12594*6777b538SAndroid Build Coastguard Worker if ((cur->children == NULL) || (depth >= max_depth)) {
12595*6777b538SAndroid Build Coastguard Worker ret = xmlStreamPop(patstream);
12596*6777b538SAndroid Build Coastguard Worker while (cur->next != NULL) {
12597*6777b538SAndroid Build Coastguard Worker cur = cur->next;
12598*6777b538SAndroid Build Coastguard Worker if ((cur->type != XML_ENTITY_DECL) &&
12599*6777b538SAndroid Build Coastguard Worker (cur->type != XML_DTD_NODE))
12600*6777b538SAndroid Build Coastguard Worker goto next_node;
12601*6777b538SAndroid Build Coastguard Worker }
12602*6777b538SAndroid Build Coastguard Worker }
12603*6777b538SAndroid Build Coastguard Worker default:
12604*6777b538SAndroid Build Coastguard Worker break;
12605*6777b538SAndroid Build Coastguard Worker }
12606*6777b538SAndroid Build Coastguard Worker
12607*6777b538SAndroid Build Coastguard Worker scan_children:
12608*6777b538SAndroid Build Coastguard Worker if (cur->type == XML_NAMESPACE_DECL) break;
12609*6777b538SAndroid Build Coastguard Worker if ((cur->children != NULL) && (depth < max_depth)) {
12610*6777b538SAndroid Build Coastguard Worker /*
12611*6777b538SAndroid Build Coastguard Worker * Do not descend on entities declarations
12612*6777b538SAndroid Build Coastguard Worker */
12613*6777b538SAndroid Build Coastguard Worker if (cur->children->type != XML_ENTITY_DECL) {
12614*6777b538SAndroid Build Coastguard Worker cur = cur->children;
12615*6777b538SAndroid Build Coastguard Worker depth++;
12616*6777b538SAndroid Build Coastguard Worker /*
12617*6777b538SAndroid Build Coastguard Worker * Skip DTDs
12618*6777b538SAndroid Build Coastguard Worker */
12619*6777b538SAndroid Build Coastguard Worker if (cur->type != XML_DTD_NODE)
12620*6777b538SAndroid Build Coastguard Worker continue;
12621*6777b538SAndroid Build Coastguard Worker }
12622*6777b538SAndroid Build Coastguard Worker }
12623*6777b538SAndroid Build Coastguard Worker
12624*6777b538SAndroid Build Coastguard Worker if (cur == limit)
12625*6777b538SAndroid Build Coastguard Worker break;
12626*6777b538SAndroid Build Coastguard Worker
12627*6777b538SAndroid Build Coastguard Worker while (cur->next != NULL) {
12628*6777b538SAndroid Build Coastguard Worker cur = cur->next;
12629*6777b538SAndroid Build Coastguard Worker if ((cur->type != XML_ENTITY_DECL) &&
12630*6777b538SAndroid Build Coastguard Worker (cur->type != XML_DTD_NODE))
12631*6777b538SAndroid Build Coastguard Worker goto next_node;
12632*6777b538SAndroid Build Coastguard Worker }
12633*6777b538SAndroid Build Coastguard Worker
12634*6777b538SAndroid Build Coastguard Worker do {
12635*6777b538SAndroid Build Coastguard Worker cur = cur->parent;
12636*6777b538SAndroid Build Coastguard Worker depth--;
12637*6777b538SAndroid Build Coastguard Worker if ((cur == NULL) || (cur == limit) ||
12638*6777b538SAndroid Build Coastguard Worker (cur->type == XML_DOCUMENT_NODE))
12639*6777b538SAndroid Build Coastguard Worker goto done;
12640*6777b538SAndroid Build Coastguard Worker if (cur->type == XML_ELEMENT_NODE) {
12641*6777b538SAndroid Build Coastguard Worker ret = xmlStreamPop(patstream);
12642*6777b538SAndroid Build Coastguard Worker } else if ((eval_all_nodes) &&
12643*6777b538SAndroid Build Coastguard Worker ((cur->type == XML_TEXT_NODE) ||
12644*6777b538SAndroid Build Coastguard Worker (cur->type == XML_CDATA_SECTION_NODE) ||
12645*6777b538SAndroid Build Coastguard Worker (cur->type == XML_COMMENT_NODE) ||
12646*6777b538SAndroid Build Coastguard Worker (cur->type == XML_PI_NODE)))
12647*6777b538SAndroid Build Coastguard Worker {
12648*6777b538SAndroid Build Coastguard Worker ret = xmlStreamPop(patstream);
12649*6777b538SAndroid Build Coastguard Worker }
12650*6777b538SAndroid Build Coastguard Worker if (cur->next != NULL) {
12651*6777b538SAndroid Build Coastguard Worker cur = cur->next;
12652*6777b538SAndroid Build Coastguard Worker break;
12653*6777b538SAndroid Build Coastguard Worker }
12654*6777b538SAndroid Build Coastguard Worker } while (cur != NULL);
12655*6777b538SAndroid Build Coastguard Worker
12656*6777b538SAndroid Build Coastguard Worker } while ((cur != NULL) && (depth >= 0));
12657*6777b538SAndroid Build Coastguard Worker
12658*6777b538SAndroid Build Coastguard Worker done:
12659*6777b538SAndroid Build Coastguard Worker
12660*6777b538SAndroid Build Coastguard Worker if (patstream)
12661*6777b538SAndroid Build Coastguard Worker xmlFreeStreamCtxt(patstream);
12662*6777b538SAndroid Build Coastguard Worker return(0);
12663*6777b538SAndroid Build Coastguard Worker
12664*6777b538SAndroid Build Coastguard Worker return_1:
12665*6777b538SAndroid Build Coastguard Worker if (patstream)
12666*6777b538SAndroid Build Coastguard Worker xmlFreeStreamCtxt(patstream);
12667*6777b538SAndroid Build Coastguard Worker return(1);
12668*6777b538SAndroid Build Coastguard Worker }
12669*6777b538SAndroid Build Coastguard Worker #endif /* XPATH_STREAMING */
12670*6777b538SAndroid Build Coastguard Worker
12671*6777b538SAndroid Build Coastguard Worker /**
12672*6777b538SAndroid Build Coastguard Worker * xmlXPathRunEval:
12673*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath parser context with the compiled expression
12674*6777b538SAndroid Build Coastguard Worker * @toBool: evaluate to a boolean result
12675*6777b538SAndroid Build Coastguard Worker *
12676*6777b538SAndroid Build Coastguard Worker * Evaluate the Precompiled XPath expression in the given context.
12677*6777b538SAndroid Build Coastguard Worker */
12678*6777b538SAndroid Build Coastguard Worker static int
xmlXPathRunEval(xmlXPathParserContextPtr ctxt,int toBool)12679*6777b538SAndroid Build Coastguard Worker xmlXPathRunEval(xmlXPathParserContextPtr ctxt, int toBool)
12680*6777b538SAndroid Build Coastguard Worker {
12681*6777b538SAndroid Build Coastguard Worker xmlXPathCompExprPtr comp;
12682*6777b538SAndroid Build Coastguard Worker int oldDepth;
12683*6777b538SAndroid Build Coastguard Worker
12684*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (ctxt->comp == NULL))
12685*6777b538SAndroid Build Coastguard Worker return(-1);
12686*6777b538SAndroid Build Coastguard Worker
12687*6777b538SAndroid Build Coastguard Worker if (ctxt->valueTab == NULL) {
12688*6777b538SAndroid Build Coastguard Worker /* Allocate the value stack */
12689*6777b538SAndroid Build Coastguard Worker ctxt->valueTab = (xmlXPathObjectPtr *)
12690*6777b538SAndroid Build Coastguard Worker xmlMalloc(10 * sizeof(xmlXPathObjectPtr));
12691*6777b538SAndroid Build Coastguard Worker if (ctxt->valueTab == NULL) {
12692*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
12693*6777b538SAndroid Build Coastguard Worker return(-1);
12694*6777b538SAndroid Build Coastguard Worker }
12695*6777b538SAndroid Build Coastguard Worker ctxt->valueNr = 0;
12696*6777b538SAndroid Build Coastguard Worker ctxt->valueMax = 10;
12697*6777b538SAndroid Build Coastguard Worker ctxt->value = NULL;
12698*6777b538SAndroid Build Coastguard Worker }
12699*6777b538SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
12700*6777b538SAndroid Build Coastguard Worker if (ctxt->comp->stream) {
12701*6777b538SAndroid Build Coastguard Worker int res;
12702*6777b538SAndroid Build Coastguard Worker
12703*6777b538SAndroid Build Coastguard Worker if (toBool) {
12704*6777b538SAndroid Build Coastguard Worker /*
12705*6777b538SAndroid Build Coastguard Worker * Evaluation to boolean result.
12706*6777b538SAndroid Build Coastguard Worker */
12707*6777b538SAndroid Build Coastguard Worker res = xmlXPathRunStreamEval(ctxt, ctxt->comp->stream, NULL, 1);
12708*6777b538SAndroid Build Coastguard Worker if (res != -1)
12709*6777b538SAndroid Build Coastguard Worker return(res);
12710*6777b538SAndroid Build Coastguard Worker } else {
12711*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr resObj = NULL;
12712*6777b538SAndroid Build Coastguard Worker
12713*6777b538SAndroid Build Coastguard Worker /*
12714*6777b538SAndroid Build Coastguard Worker * Evaluation to a sequence.
12715*6777b538SAndroid Build Coastguard Worker */
12716*6777b538SAndroid Build Coastguard Worker res = xmlXPathRunStreamEval(ctxt, ctxt->comp->stream, &resObj, 0);
12717*6777b538SAndroid Build Coastguard Worker
12718*6777b538SAndroid Build Coastguard Worker if ((res != -1) && (resObj != NULL)) {
12719*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, resObj);
12720*6777b538SAndroid Build Coastguard Worker return(0);
12721*6777b538SAndroid Build Coastguard Worker }
12722*6777b538SAndroid Build Coastguard Worker if (resObj != NULL)
12723*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, resObj);
12724*6777b538SAndroid Build Coastguard Worker }
12725*6777b538SAndroid Build Coastguard Worker /*
12726*6777b538SAndroid Build Coastguard Worker * QUESTION TODO: This falls back to normal XPath evaluation
12727*6777b538SAndroid Build Coastguard Worker * if res == -1. Is this intended?
12728*6777b538SAndroid Build Coastguard Worker */
12729*6777b538SAndroid Build Coastguard Worker }
12730*6777b538SAndroid Build Coastguard Worker #endif
12731*6777b538SAndroid Build Coastguard Worker comp = ctxt->comp;
12732*6777b538SAndroid Build Coastguard Worker if (comp->last < 0) {
12733*6777b538SAndroid Build Coastguard Worker xmlXPathErr(ctxt, XPATH_STACK_ERROR);
12734*6777b538SAndroid Build Coastguard Worker return(-1);
12735*6777b538SAndroid Build Coastguard Worker }
12736*6777b538SAndroid Build Coastguard Worker oldDepth = ctxt->context->depth;
12737*6777b538SAndroid Build Coastguard Worker if (toBool)
12738*6777b538SAndroid Build Coastguard Worker return(xmlXPathCompOpEvalToBoolean(ctxt,
12739*6777b538SAndroid Build Coastguard Worker &comp->steps[comp->last], 0));
12740*6777b538SAndroid Build Coastguard Worker else
12741*6777b538SAndroid Build Coastguard Worker xmlXPathCompOpEval(ctxt, &comp->steps[comp->last]);
12742*6777b538SAndroid Build Coastguard Worker ctxt->context->depth = oldDepth;
12743*6777b538SAndroid Build Coastguard Worker
12744*6777b538SAndroid Build Coastguard Worker return(0);
12745*6777b538SAndroid Build Coastguard Worker }
12746*6777b538SAndroid Build Coastguard Worker
12747*6777b538SAndroid Build Coastguard Worker /************************************************************************
12748*6777b538SAndroid Build Coastguard Worker * *
12749*6777b538SAndroid Build Coastguard Worker * Public interfaces *
12750*6777b538SAndroid Build Coastguard Worker * *
12751*6777b538SAndroid Build Coastguard Worker ************************************************************************/
12752*6777b538SAndroid Build Coastguard Worker
12753*6777b538SAndroid Build Coastguard Worker /**
12754*6777b538SAndroid Build Coastguard Worker * xmlXPathEvalPredicate:
12755*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath context
12756*6777b538SAndroid Build Coastguard Worker * @res: the Predicate Expression evaluation result
12757*6777b538SAndroid Build Coastguard Worker *
12758*6777b538SAndroid Build Coastguard Worker * Evaluate a predicate result for the current node.
12759*6777b538SAndroid Build Coastguard Worker * A PredicateExpr is evaluated by evaluating the Expr and converting
12760*6777b538SAndroid Build Coastguard Worker * the result to a boolean. If the result is a number, the result will
12761*6777b538SAndroid Build Coastguard Worker * be converted to true if the number is equal to the position of the
12762*6777b538SAndroid Build Coastguard Worker * context node in the context node list (as returned by the position
12763*6777b538SAndroid Build Coastguard Worker * function) and will be converted to false otherwise; if the result
12764*6777b538SAndroid Build Coastguard Worker * is not a number, then the result will be converted as if by a call
12765*6777b538SAndroid Build Coastguard Worker * to the boolean function.
12766*6777b538SAndroid Build Coastguard Worker *
12767*6777b538SAndroid Build Coastguard Worker * Returns 1 if predicate is true, 0 otherwise
12768*6777b538SAndroid Build Coastguard Worker */
12769*6777b538SAndroid Build Coastguard Worker int
xmlXPathEvalPredicate(xmlXPathContextPtr ctxt,xmlXPathObjectPtr res)12770*6777b538SAndroid Build Coastguard Worker xmlXPathEvalPredicate(xmlXPathContextPtr ctxt, xmlXPathObjectPtr res) {
12771*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (res == NULL)) return(0);
12772*6777b538SAndroid Build Coastguard Worker switch (res->type) {
12773*6777b538SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
12774*6777b538SAndroid Build Coastguard Worker return(res->boolval);
12775*6777b538SAndroid Build Coastguard Worker case XPATH_NUMBER:
12776*6777b538SAndroid Build Coastguard Worker return(res->floatval == ctxt->proximityPosition);
12777*6777b538SAndroid Build Coastguard Worker case XPATH_NODESET:
12778*6777b538SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
12779*6777b538SAndroid Build Coastguard Worker if (res->nodesetval == NULL)
12780*6777b538SAndroid Build Coastguard Worker return(0);
12781*6777b538SAndroid Build Coastguard Worker return(res->nodesetval->nodeNr != 0);
12782*6777b538SAndroid Build Coastguard Worker case XPATH_STRING:
12783*6777b538SAndroid Build Coastguard Worker return((res->stringval != NULL) &&
12784*6777b538SAndroid Build Coastguard Worker (xmlStrlen(res->stringval) != 0));
12785*6777b538SAndroid Build Coastguard Worker default:
12786*6777b538SAndroid Build Coastguard Worker break;
12787*6777b538SAndroid Build Coastguard Worker }
12788*6777b538SAndroid Build Coastguard Worker return(0);
12789*6777b538SAndroid Build Coastguard Worker }
12790*6777b538SAndroid Build Coastguard Worker
12791*6777b538SAndroid Build Coastguard Worker /**
12792*6777b538SAndroid Build Coastguard Worker * xmlXPathEvaluatePredicateResult:
12793*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
12794*6777b538SAndroid Build Coastguard Worker * @res: the Predicate Expression evaluation result
12795*6777b538SAndroid Build Coastguard Worker *
12796*6777b538SAndroid Build Coastguard Worker * Evaluate a predicate result for the current node.
12797*6777b538SAndroid Build Coastguard Worker * A PredicateExpr is evaluated by evaluating the Expr and converting
12798*6777b538SAndroid Build Coastguard Worker * the result to a boolean. If the result is a number, the result will
12799*6777b538SAndroid Build Coastguard Worker * be converted to true if the number is equal to the position of the
12800*6777b538SAndroid Build Coastguard Worker * context node in the context node list (as returned by the position
12801*6777b538SAndroid Build Coastguard Worker * function) and will be converted to false otherwise; if the result
12802*6777b538SAndroid Build Coastguard Worker * is not a number, then the result will be converted as if by a call
12803*6777b538SAndroid Build Coastguard Worker * to the boolean function.
12804*6777b538SAndroid Build Coastguard Worker *
12805*6777b538SAndroid Build Coastguard Worker * Returns 1 if predicate is true, 0 otherwise
12806*6777b538SAndroid Build Coastguard Worker */
12807*6777b538SAndroid Build Coastguard Worker int
xmlXPathEvaluatePredicateResult(xmlXPathParserContextPtr ctxt,xmlXPathObjectPtr res)12808*6777b538SAndroid Build Coastguard Worker xmlXPathEvaluatePredicateResult(xmlXPathParserContextPtr ctxt,
12809*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr res) {
12810*6777b538SAndroid Build Coastguard Worker if ((ctxt == NULL) || (res == NULL)) return(0);
12811*6777b538SAndroid Build Coastguard Worker switch (res->type) {
12812*6777b538SAndroid Build Coastguard Worker case XPATH_BOOLEAN:
12813*6777b538SAndroid Build Coastguard Worker return(res->boolval);
12814*6777b538SAndroid Build Coastguard Worker case XPATH_NUMBER:
12815*6777b538SAndroid Build Coastguard Worker #if defined(__BORLANDC__) || (defined(_MSC_VER) && (_MSC_VER == 1200))
12816*6777b538SAndroid Build Coastguard Worker return((res->floatval == ctxt->context->proximityPosition) &&
12817*6777b538SAndroid Build Coastguard Worker (!xmlXPathIsNaN(res->floatval))); /* MSC pbm Mark Vakoc !*/
12818*6777b538SAndroid Build Coastguard Worker #else
12819*6777b538SAndroid Build Coastguard Worker return(res->floatval == ctxt->context->proximityPosition);
12820*6777b538SAndroid Build Coastguard Worker #endif
12821*6777b538SAndroid Build Coastguard Worker case XPATH_NODESET:
12822*6777b538SAndroid Build Coastguard Worker case XPATH_XSLT_TREE:
12823*6777b538SAndroid Build Coastguard Worker if (res->nodesetval == NULL)
12824*6777b538SAndroid Build Coastguard Worker return(0);
12825*6777b538SAndroid Build Coastguard Worker return(res->nodesetval->nodeNr != 0);
12826*6777b538SAndroid Build Coastguard Worker case XPATH_STRING:
12827*6777b538SAndroid Build Coastguard Worker return((res->stringval != NULL) && (res->stringval[0] != 0));
12828*6777b538SAndroid Build Coastguard Worker #ifdef LIBXML_XPTR_LOCS_ENABLED
12829*6777b538SAndroid Build Coastguard Worker case XPATH_LOCATIONSET:{
12830*6777b538SAndroid Build Coastguard Worker xmlLocationSetPtr ptr = res->user;
12831*6777b538SAndroid Build Coastguard Worker if (ptr == NULL)
12832*6777b538SAndroid Build Coastguard Worker return(0);
12833*6777b538SAndroid Build Coastguard Worker return (ptr->locNr != 0);
12834*6777b538SAndroid Build Coastguard Worker }
12835*6777b538SAndroid Build Coastguard Worker #endif
12836*6777b538SAndroid Build Coastguard Worker default:
12837*6777b538SAndroid Build Coastguard Worker break;
12838*6777b538SAndroid Build Coastguard Worker }
12839*6777b538SAndroid Build Coastguard Worker return(0);
12840*6777b538SAndroid Build Coastguard Worker }
12841*6777b538SAndroid Build Coastguard Worker
12842*6777b538SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
12843*6777b538SAndroid Build Coastguard Worker /**
12844*6777b538SAndroid Build Coastguard Worker * xmlXPathTryStreamCompile:
12845*6777b538SAndroid Build Coastguard Worker * @ctxt: an XPath context
12846*6777b538SAndroid Build Coastguard Worker * @str: the XPath expression
12847*6777b538SAndroid Build Coastguard Worker *
12848*6777b538SAndroid Build Coastguard Worker * Try to compile the XPath expression as a streamable subset.
12849*6777b538SAndroid Build Coastguard Worker *
12850*6777b538SAndroid Build Coastguard Worker * Returns the compiled expression or NULL if failed to compile.
12851*6777b538SAndroid Build Coastguard Worker */
12852*6777b538SAndroid Build Coastguard Worker static xmlXPathCompExprPtr
xmlXPathTryStreamCompile(xmlXPathContextPtr ctxt,const xmlChar * str)12853*6777b538SAndroid Build Coastguard Worker xmlXPathTryStreamCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
12854*6777b538SAndroid Build Coastguard Worker /*
12855*6777b538SAndroid Build Coastguard Worker * Optimization: use streaming patterns when the XPath expression can
12856*6777b538SAndroid Build Coastguard Worker * be compiled to a stream lookup
12857*6777b538SAndroid Build Coastguard Worker */
12858*6777b538SAndroid Build Coastguard Worker xmlPatternPtr stream;
12859*6777b538SAndroid Build Coastguard Worker xmlXPathCompExprPtr comp;
12860*6777b538SAndroid Build Coastguard Worker xmlDictPtr dict = NULL;
12861*6777b538SAndroid Build Coastguard Worker const xmlChar **namespaces = NULL;
12862*6777b538SAndroid Build Coastguard Worker xmlNsPtr ns;
12863*6777b538SAndroid Build Coastguard Worker int i, j;
12864*6777b538SAndroid Build Coastguard Worker
12865*6777b538SAndroid Build Coastguard Worker if ((!xmlStrchr(str, '[')) && (!xmlStrchr(str, '(')) &&
12866*6777b538SAndroid Build Coastguard Worker (!xmlStrchr(str, '@'))) {
12867*6777b538SAndroid Build Coastguard Worker const xmlChar *tmp;
12868*6777b538SAndroid Build Coastguard Worker int res;
12869*6777b538SAndroid Build Coastguard Worker
12870*6777b538SAndroid Build Coastguard Worker /*
12871*6777b538SAndroid Build Coastguard Worker * We don't try to handle expressions using the verbose axis
12872*6777b538SAndroid Build Coastguard Worker * specifiers ("::"), just the simplified form at this point.
12873*6777b538SAndroid Build Coastguard Worker * Additionally, if there is no list of namespaces available and
12874*6777b538SAndroid Build Coastguard Worker * there's a ":" in the expression, indicating a prefixed QName,
12875*6777b538SAndroid Build Coastguard Worker * then we won't try to compile either. xmlPatterncompile() needs
12876*6777b538SAndroid Build Coastguard Worker * to have a list of namespaces at compilation time in order to
12877*6777b538SAndroid Build Coastguard Worker * compile prefixed name tests.
12878*6777b538SAndroid Build Coastguard Worker */
12879*6777b538SAndroid Build Coastguard Worker tmp = xmlStrchr(str, ':');
12880*6777b538SAndroid Build Coastguard Worker if ((tmp != NULL) &&
12881*6777b538SAndroid Build Coastguard Worker ((ctxt == NULL) || (ctxt->nsNr == 0) || (tmp[1] == ':')))
12882*6777b538SAndroid Build Coastguard Worker return(NULL);
12883*6777b538SAndroid Build Coastguard Worker
12884*6777b538SAndroid Build Coastguard Worker if (ctxt != NULL) {
12885*6777b538SAndroid Build Coastguard Worker dict = ctxt->dict;
12886*6777b538SAndroid Build Coastguard Worker if (ctxt->nsNr > 0) {
12887*6777b538SAndroid Build Coastguard Worker namespaces = xmlMalloc(2 * (ctxt->nsNr + 1) * sizeof(xmlChar*));
12888*6777b538SAndroid Build Coastguard Worker if (namespaces == NULL) {
12889*6777b538SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt);
12890*6777b538SAndroid Build Coastguard Worker return(NULL);
12891*6777b538SAndroid Build Coastguard Worker }
12892*6777b538SAndroid Build Coastguard Worker for (i = 0, j = 0; (j < ctxt->nsNr); j++) {
12893*6777b538SAndroid Build Coastguard Worker ns = ctxt->namespaces[j];
12894*6777b538SAndroid Build Coastguard Worker namespaces[i++] = ns->href;
12895*6777b538SAndroid Build Coastguard Worker namespaces[i++] = ns->prefix;
12896*6777b538SAndroid Build Coastguard Worker }
12897*6777b538SAndroid Build Coastguard Worker namespaces[i++] = NULL;
12898*6777b538SAndroid Build Coastguard Worker namespaces[i] = NULL;
12899*6777b538SAndroid Build Coastguard Worker }
12900*6777b538SAndroid Build Coastguard Worker }
12901*6777b538SAndroid Build Coastguard Worker
12902*6777b538SAndroid Build Coastguard Worker res = xmlPatternCompileSafe(str, dict, XML_PATTERN_XPATH, namespaces,
12903*6777b538SAndroid Build Coastguard Worker &stream);
12904*6777b538SAndroid Build Coastguard Worker if (namespaces != NULL) {
12905*6777b538SAndroid Build Coastguard Worker xmlFree((xmlChar **)namespaces);
12906*6777b538SAndroid Build Coastguard Worker }
12907*6777b538SAndroid Build Coastguard Worker if (res < 0) {
12908*6777b538SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt);
12909*6777b538SAndroid Build Coastguard Worker return(NULL);
12910*6777b538SAndroid Build Coastguard Worker }
12911*6777b538SAndroid Build Coastguard Worker if ((stream != NULL) && (xmlPatternStreamable(stream) == 1)) {
12912*6777b538SAndroid Build Coastguard Worker comp = xmlXPathNewCompExpr();
12913*6777b538SAndroid Build Coastguard Worker if (comp == NULL) {
12914*6777b538SAndroid Build Coastguard Worker xmlXPathErrMemory(ctxt);
12915*6777b538SAndroid Build Coastguard Worker xmlFreePattern(stream);
12916*6777b538SAndroid Build Coastguard Worker return(NULL);
12917*6777b538SAndroid Build Coastguard Worker }
12918*6777b538SAndroid Build Coastguard Worker comp->stream = stream;
12919*6777b538SAndroid Build Coastguard Worker comp->dict = dict;
12920*6777b538SAndroid Build Coastguard Worker if (comp->dict)
12921*6777b538SAndroid Build Coastguard Worker xmlDictReference(comp->dict);
12922*6777b538SAndroid Build Coastguard Worker return(comp);
12923*6777b538SAndroid Build Coastguard Worker }
12924*6777b538SAndroid Build Coastguard Worker xmlFreePattern(stream);
12925*6777b538SAndroid Build Coastguard Worker }
12926*6777b538SAndroid Build Coastguard Worker return(NULL);
12927*6777b538SAndroid Build Coastguard Worker }
12928*6777b538SAndroid Build Coastguard Worker #endif /* XPATH_STREAMING */
12929*6777b538SAndroid Build Coastguard Worker
12930*6777b538SAndroid Build Coastguard Worker static void
xmlXPathOptimizeExpression(xmlXPathParserContextPtr pctxt,xmlXPathStepOpPtr op)12931*6777b538SAndroid Build Coastguard Worker xmlXPathOptimizeExpression(xmlXPathParserContextPtr pctxt,
12932*6777b538SAndroid Build Coastguard Worker xmlXPathStepOpPtr op)
12933*6777b538SAndroid Build Coastguard Worker {
12934*6777b538SAndroid Build Coastguard Worker xmlXPathCompExprPtr comp = pctxt->comp;
12935*6777b538SAndroid Build Coastguard Worker xmlXPathContextPtr ctxt;
12936*6777b538SAndroid Build Coastguard Worker
12937*6777b538SAndroid Build Coastguard Worker /*
12938*6777b538SAndroid Build Coastguard Worker * Try to rewrite "descendant-or-self::node()/foo" to an optimized
12939*6777b538SAndroid Build Coastguard Worker * internal representation.
12940*6777b538SAndroid Build Coastguard Worker */
12941*6777b538SAndroid Build Coastguard Worker
12942*6777b538SAndroid Build Coastguard Worker if ((op->op == XPATH_OP_COLLECT /* 11 */) &&
12943*6777b538SAndroid Build Coastguard Worker (op->ch1 != -1) &&
12944*6777b538SAndroid Build Coastguard Worker (op->ch2 == -1 /* no predicate */))
12945*6777b538SAndroid Build Coastguard Worker {
12946*6777b538SAndroid Build Coastguard Worker xmlXPathStepOpPtr prevop = &comp->steps[op->ch1];
12947*6777b538SAndroid Build Coastguard Worker
12948*6777b538SAndroid Build Coastguard Worker if ((prevop->op == XPATH_OP_COLLECT /* 11 */) &&
12949*6777b538SAndroid Build Coastguard Worker ((xmlXPathAxisVal) prevop->value ==
12950*6777b538SAndroid Build Coastguard Worker AXIS_DESCENDANT_OR_SELF) &&
12951*6777b538SAndroid Build Coastguard Worker (prevop->ch2 == -1) &&
12952*6777b538SAndroid Build Coastguard Worker ((xmlXPathTestVal) prevop->value2 == NODE_TEST_TYPE) &&
12953*6777b538SAndroid Build Coastguard Worker ((xmlXPathTypeVal) prevop->value3 == NODE_TYPE_NODE))
12954*6777b538SAndroid Build Coastguard Worker {
12955*6777b538SAndroid Build Coastguard Worker /*
12956*6777b538SAndroid Build Coastguard Worker * This is a "descendant-or-self::node()" without predicates.
12957*6777b538SAndroid Build Coastguard Worker * Try to eliminate it.
12958*6777b538SAndroid Build Coastguard Worker */
12959*6777b538SAndroid Build Coastguard Worker
12960*6777b538SAndroid Build Coastguard Worker switch ((xmlXPathAxisVal) op->value) {
12961*6777b538SAndroid Build Coastguard Worker case AXIS_CHILD:
12962*6777b538SAndroid Build Coastguard Worker case AXIS_DESCENDANT:
12963*6777b538SAndroid Build Coastguard Worker /*
12964*6777b538SAndroid Build Coastguard Worker * Convert "descendant-or-self::node()/child::" or
12965*6777b538SAndroid Build Coastguard Worker * "descendant-or-self::node()/descendant::" to
12966*6777b538SAndroid Build Coastguard Worker * "descendant::"
12967*6777b538SAndroid Build Coastguard Worker */
12968*6777b538SAndroid Build Coastguard Worker op->ch1 = prevop->ch1;
12969*6777b538SAndroid Build Coastguard Worker op->value = AXIS_DESCENDANT;
12970*6777b538SAndroid Build Coastguard Worker break;
12971*6777b538SAndroid Build Coastguard Worker case AXIS_SELF:
12972*6777b538SAndroid Build Coastguard Worker case AXIS_DESCENDANT_OR_SELF:
12973*6777b538SAndroid Build Coastguard Worker /*
12974*6777b538SAndroid Build Coastguard Worker * Convert "descendant-or-self::node()/self::" or
12975*6777b538SAndroid Build Coastguard Worker * "descendant-or-self::node()/descendant-or-self::" to
12976*6777b538SAndroid Build Coastguard Worker * to "descendant-or-self::"
12977*6777b538SAndroid Build Coastguard Worker */
12978*6777b538SAndroid Build Coastguard Worker op->ch1 = prevop->ch1;
12979*6777b538SAndroid Build Coastguard Worker op->value = AXIS_DESCENDANT_OR_SELF;
12980*6777b538SAndroid Build Coastguard Worker break;
12981*6777b538SAndroid Build Coastguard Worker default:
12982*6777b538SAndroid Build Coastguard Worker break;
12983*6777b538SAndroid Build Coastguard Worker }
12984*6777b538SAndroid Build Coastguard Worker }
12985*6777b538SAndroid Build Coastguard Worker }
12986*6777b538SAndroid Build Coastguard Worker
12987*6777b538SAndroid Build Coastguard Worker /* OP_VALUE has invalid ch1. */
12988*6777b538SAndroid Build Coastguard Worker if (op->op == XPATH_OP_VALUE)
12989*6777b538SAndroid Build Coastguard Worker return;
12990*6777b538SAndroid Build Coastguard Worker
12991*6777b538SAndroid Build Coastguard Worker /* Recurse */
12992*6777b538SAndroid Build Coastguard Worker ctxt = pctxt->context;
12993*6777b538SAndroid Build Coastguard Worker if (ctxt != NULL) {
12994*6777b538SAndroid Build Coastguard Worker if (ctxt->depth >= XPATH_MAX_RECURSION_DEPTH)
12995*6777b538SAndroid Build Coastguard Worker return;
12996*6777b538SAndroid Build Coastguard Worker ctxt->depth += 1;
12997*6777b538SAndroid Build Coastguard Worker }
12998*6777b538SAndroid Build Coastguard Worker if (op->ch1 != -1)
12999*6777b538SAndroid Build Coastguard Worker xmlXPathOptimizeExpression(pctxt, &comp->steps[op->ch1]);
13000*6777b538SAndroid Build Coastguard Worker if (op->ch2 != -1)
13001*6777b538SAndroid Build Coastguard Worker xmlXPathOptimizeExpression(pctxt, &comp->steps[op->ch2]);
13002*6777b538SAndroid Build Coastguard Worker if (ctxt != NULL)
13003*6777b538SAndroid Build Coastguard Worker ctxt->depth -= 1;
13004*6777b538SAndroid Build Coastguard Worker }
13005*6777b538SAndroid Build Coastguard Worker
13006*6777b538SAndroid Build Coastguard Worker /**
13007*6777b538SAndroid Build Coastguard Worker * xmlXPathCtxtCompile:
13008*6777b538SAndroid Build Coastguard Worker * @ctxt: an XPath context
13009*6777b538SAndroid Build Coastguard Worker * @str: the XPath expression
13010*6777b538SAndroid Build Coastguard Worker *
13011*6777b538SAndroid Build Coastguard Worker * Compile an XPath expression
13012*6777b538SAndroid Build Coastguard Worker *
13013*6777b538SAndroid Build Coastguard Worker * Returns the xmlXPathCompExprPtr resulting from the compilation or NULL.
13014*6777b538SAndroid Build Coastguard Worker * the caller has to free the object.
13015*6777b538SAndroid Build Coastguard Worker */
13016*6777b538SAndroid Build Coastguard Worker xmlXPathCompExprPtr
xmlXPathCtxtCompile(xmlXPathContextPtr ctxt,const xmlChar * str)13017*6777b538SAndroid Build Coastguard Worker xmlXPathCtxtCompile(xmlXPathContextPtr ctxt, const xmlChar *str) {
13018*6777b538SAndroid Build Coastguard Worker xmlXPathParserContextPtr pctxt;
13019*6777b538SAndroid Build Coastguard Worker xmlXPathCompExprPtr comp;
13020*6777b538SAndroid Build Coastguard Worker int oldDepth = 0;
13021*6777b538SAndroid Build Coastguard Worker
13022*6777b538SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
13023*6777b538SAndroid Build Coastguard Worker comp = xmlXPathTryStreamCompile(ctxt, str);
13024*6777b538SAndroid Build Coastguard Worker if (comp != NULL)
13025*6777b538SAndroid Build Coastguard Worker return(comp);
13026*6777b538SAndroid Build Coastguard Worker #endif
13027*6777b538SAndroid Build Coastguard Worker
13028*6777b538SAndroid Build Coastguard Worker xmlInitParser();
13029*6777b538SAndroid Build Coastguard Worker
13030*6777b538SAndroid Build Coastguard Worker pctxt = xmlXPathNewParserContext(str, ctxt);
13031*6777b538SAndroid Build Coastguard Worker if (pctxt == NULL)
13032*6777b538SAndroid Build Coastguard Worker return NULL;
13033*6777b538SAndroid Build Coastguard Worker if (ctxt != NULL)
13034*6777b538SAndroid Build Coastguard Worker oldDepth = ctxt->depth;
13035*6777b538SAndroid Build Coastguard Worker xmlXPathCompileExpr(pctxt, 1);
13036*6777b538SAndroid Build Coastguard Worker if (ctxt != NULL)
13037*6777b538SAndroid Build Coastguard Worker ctxt->depth = oldDepth;
13038*6777b538SAndroid Build Coastguard Worker
13039*6777b538SAndroid Build Coastguard Worker if( pctxt->error != XPATH_EXPRESSION_OK )
13040*6777b538SAndroid Build Coastguard Worker {
13041*6777b538SAndroid Build Coastguard Worker xmlXPathFreeParserContext(pctxt);
13042*6777b538SAndroid Build Coastguard Worker return(NULL);
13043*6777b538SAndroid Build Coastguard Worker }
13044*6777b538SAndroid Build Coastguard Worker
13045*6777b538SAndroid Build Coastguard Worker if (*pctxt->cur != 0) {
13046*6777b538SAndroid Build Coastguard Worker /*
13047*6777b538SAndroid Build Coastguard Worker * aleksey: in some cases this line prints *second* error message
13048*6777b538SAndroid Build Coastguard Worker * (see bug #78858) and probably this should be fixed.
13049*6777b538SAndroid Build Coastguard Worker * However, we are not sure that all error messages are printed
13050*6777b538SAndroid Build Coastguard Worker * out in other places. It's not critical so we leave it as-is for now
13051*6777b538SAndroid Build Coastguard Worker */
13052*6777b538SAndroid Build Coastguard Worker xmlXPatherror(pctxt, __FILE__, __LINE__, XPATH_EXPR_ERROR);
13053*6777b538SAndroid Build Coastguard Worker comp = NULL;
13054*6777b538SAndroid Build Coastguard Worker } else {
13055*6777b538SAndroid Build Coastguard Worker comp = pctxt->comp;
13056*6777b538SAndroid Build Coastguard Worker if ((comp->nbStep > 1) && (comp->last >= 0)) {
13057*6777b538SAndroid Build Coastguard Worker if (ctxt != NULL)
13058*6777b538SAndroid Build Coastguard Worker oldDepth = ctxt->depth;
13059*6777b538SAndroid Build Coastguard Worker xmlXPathOptimizeExpression(pctxt, &comp->steps[comp->last]);
13060*6777b538SAndroid Build Coastguard Worker if (ctxt != NULL)
13061*6777b538SAndroid Build Coastguard Worker ctxt->depth = oldDepth;
13062*6777b538SAndroid Build Coastguard Worker }
13063*6777b538SAndroid Build Coastguard Worker pctxt->comp = NULL;
13064*6777b538SAndroid Build Coastguard Worker }
13065*6777b538SAndroid Build Coastguard Worker xmlXPathFreeParserContext(pctxt);
13066*6777b538SAndroid Build Coastguard Worker
13067*6777b538SAndroid Build Coastguard Worker if (comp != NULL) {
13068*6777b538SAndroid Build Coastguard Worker comp->expr = xmlStrdup(str);
13069*6777b538SAndroid Build Coastguard Worker }
13070*6777b538SAndroid Build Coastguard Worker return(comp);
13071*6777b538SAndroid Build Coastguard Worker }
13072*6777b538SAndroid Build Coastguard Worker
13073*6777b538SAndroid Build Coastguard Worker /**
13074*6777b538SAndroid Build Coastguard Worker * xmlXPathCompile:
13075*6777b538SAndroid Build Coastguard Worker * @str: the XPath expression
13076*6777b538SAndroid Build Coastguard Worker *
13077*6777b538SAndroid Build Coastguard Worker * Compile an XPath expression
13078*6777b538SAndroid Build Coastguard Worker *
13079*6777b538SAndroid Build Coastguard Worker * Returns the xmlXPathCompExprPtr resulting from the compilation or NULL.
13080*6777b538SAndroid Build Coastguard Worker * the caller has to free the object.
13081*6777b538SAndroid Build Coastguard Worker */
13082*6777b538SAndroid Build Coastguard Worker xmlXPathCompExprPtr
xmlXPathCompile(const xmlChar * str)13083*6777b538SAndroid Build Coastguard Worker xmlXPathCompile(const xmlChar *str) {
13084*6777b538SAndroid Build Coastguard Worker return(xmlXPathCtxtCompile(NULL, str));
13085*6777b538SAndroid Build Coastguard Worker }
13086*6777b538SAndroid Build Coastguard Worker
13087*6777b538SAndroid Build Coastguard Worker /**
13088*6777b538SAndroid Build Coastguard Worker * xmlXPathCompiledEvalInternal:
13089*6777b538SAndroid Build Coastguard Worker * @comp: the compiled XPath expression
13090*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath context
13091*6777b538SAndroid Build Coastguard Worker * @resObj: the resulting XPath object or NULL
13092*6777b538SAndroid Build Coastguard Worker * @toBool: 1 if only a boolean result is requested
13093*6777b538SAndroid Build Coastguard Worker *
13094*6777b538SAndroid Build Coastguard Worker * Evaluate the Precompiled XPath expression in the given context.
13095*6777b538SAndroid Build Coastguard Worker * The caller has to free @resObj.
13096*6777b538SAndroid Build Coastguard Worker *
13097*6777b538SAndroid Build Coastguard Worker * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
13098*6777b538SAndroid Build Coastguard Worker * the caller has to free the object.
13099*6777b538SAndroid Build Coastguard Worker */
13100*6777b538SAndroid Build Coastguard Worker static int
xmlXPathCompiledEvalInternal(xmlXPathCompExprPtr comp,xmlXPathContextPtr ctxt,xmlXPathObjectPtr * resObjPtr,int toBool)13101*6777b538SAndroid Build Coastguard Worker xmlXPathCompiledEvalInternal(xmlXPathCompExprPtr comp,
13102*6777b538SAndroid Build Coastguard Worker xmlXPathContextPtr ctxt,
13103*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr *resObjPtr,
13104*6777b538SAndroid Build Coastguard Worker int toBool)
13105*6777b538SAndroid Build Coastguard Worker {
13106*6777b538SAndroid Build Coastguard Worker xmlXPathParserContextPtr pctxt;
13107*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr resObj = NULL;
13108*6777b538SAndroid Build Coastguard Worker #ifndef LIBXML_THREAD_ENABLED
13109*6777b538SAndroid Build Coastguard Worker static int reentance = 0;
13110*6777b538SAndroid Build Coastguard Worker #endif
13111*6777b538SAndroid Build Coastguard Worker int res;
13112*6777b538SAndroid Build Coastguard Worker
13113*6777b538SAndroid Build Coastguard Worker if (comp == NULL)
13114*6777b538SAndroid Build Coastguard Worker return(-1);
13115*6777b538SAndroid Build Coastguard Worker xmlInitParser();
13116*6777b538SAndroid Build Coastguard Worker
13117*6777b538SAndroid Build Coastguard Worker xmlResetError(&ctxt->lastError);
13118*6777b538SAndroid Build Coastguard Worker
13119*6777b538SAndroid Build Coastguard Worker #ifndef LIBXML_THREAD_ENABLED
13120*6777b538SAndroid Build Coastguard Worker reentance++;
13121*6777b538SAndroid Build Coastguard Worker if (reentance > 1)
13122*6777b538SAndroid Build Coastguard Worker xmlXPathDisableOptimizer = 1;
13123*6777b538SAndroid Build Coastguard Worker #endif
13124*6777b538SAndroid Build Coastguard Worker
13125*6777b538SAndroid Build Coastguard Worker pctxt = xmlXPathCompParserContext(comp, ctxt);
13126*6777b538SAndroid Build Coastguard Worker if (pctxt == NULL)
13127*6777b538SAndroid Build Coastguard Worker return(-1);
13128*6777b538SAndroid Build Coastguard Worker res = xmlXPathRunEval(pctxt, toBool);
13129*6777b538SAndroid Build Coastguard Worker
13130*6777b538SAndroid Build Coastguard Worker if (pctxt->error == XPATH_EXPRESSION_OK) {
13131*6777b538SAndroid Build Coastguard Worker if (pctxt->valueNr != ((toBool) ? 0 : 1))
13132*6777b538SAndroid Build Coastguard Worker xmlXPathErr(pctxt, XPATH_STACK_ERROR);
13133*6777b538SAndroid Build Coastguard Worker else if (!toBool)
13134*6777b538SAndroid Build Coastguard Worker resObj = valuePop(pctxt);
13135*6777b538SAndroid Build Coastguard Worker }
13136*6777b538SAndroid Build Coastguard Worker
13137*6777b538SAndroid Build Coastguard Worker if (resObjPtr)
13138*6777b538SAndroid Build Coastguard Worker *resObjPtr = resObj;
13139*6777b538SAndroid Build Coastguard Worker else
13140*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt, resObj);
13141*6777b538SAndroid Build Coastguard Worker
13142*6777b538SAndroid Build Coastguard Worker pctxt->comp = NULL;
13143*6777b538SAndroid Build Coastguard Worker xmlXPathFreeParserContext(pctxt);
13144*6777b538SAndroid Build Coastguard Worker #ifndef LIBXML_THREAD_ENABLED
13145*6777b538SAndroid Build Coastguard Worker reentance--;
13146*6777b538SAndroid Build Coastguard Worker #endif
13147*6777b538SAndroid Build Coastguard Worker
13148*6777b538SAndroid Build Coastguard Worker return(res);
13149*6777b538SAndroid Build Coastguard Worker }
13150*6777b538SAndroid Build Coastguard Worker
13151*6777b538SAndroid Build Coastguard Worker /**
13152*6777b538SAndroid Build Coastguard Worker * xmlXPathCompiledEval:
13153*6777b538SAndroid Build Coastguard Worker * @comp: the compiled XPath expression
13154*6777b538SAndroid Build Coastguard Worker * @ctx: the XPath context
13155*6777b538SAndroid Build Coastguard Worker *
13156*6777b538SAndroid Build Coastguard Worker * Evaluate the Precompiled XPath expression in the given context.
13157*6777b538SAndroid Build Coastguard Worker *
13158*6777b538SAndroid Build Coastguard Worker * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
13159*6777b538SAndroid Build Coastguard Worker * the caller has to free the object.
13160*6777b538SAndroid Build Coastguard Worker */
13161*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathCompiledEval(xmlXPathCompExprPtr comp,xmlXPathContextPtr ctx)13162*6777b538SAndroid Build Coastguard Worker xmlXPathCompiledEval(xmlXPathCompExprPtr comp, xmlXPathContextPtr ctx)
13163*6777b538SAndroid Build Coastguard Worker {
13164*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr res = NULL;
13165*6777b538SAndroid Build Coastguard Worker
13166*6777b538SAndroid Build Coastguard Worker xmlXPathCompiledEvalInternal(comp, ctx, &res, 0);
13167*6777b538SAndroid Build Coastguard Worker return(res);
13168*6777b538SAndroid Build Coastguard Worker }
13169*6777b538SAndroid Build Coastguard Worker
13170*6777b538SAndroid Build Coastguard Worker /**
13171*6777b538SAndroid Build Coastguard Worker * xmlXPathCompiledEvalToBoolean:
13172*6777b538SAndroid Build Coastguard Worker * @comp: the compiled XPath expression
13173*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath context
13174*6777b538SAndroid Build Coastguard Worker *
13175*6777b538SAndroid Build Coastguard Worker * Applies the XPath boolean() function on the result of the given
13176*6777b538SAndroid Build Coastguard Worker * compiled expression.
13177*6777b538SAndroid Build Coastguard Worker *
13178*6777b538SAndroid Build Coastguard Worker * Returns 1 if the expression evaluated to true, 0 if to false and
13179*6777b538SAndroid Build Coastguard Worker * -1 in API and internal errors.
13180*6777b538SAndroid Build Coastguard Worker */
13181*6777b538SAndroid Build Coastguard Worker int
xmlXPathCompiledEvalToBoolean(xmlXPathCompExprPtr comp,xmlXPathContextPtr ctxt)13182*6777b538SAndroid Build Coastguard Worker xmlXPathCompiledEvalToBoolean(xmlXPathCompExprPtr comp,
13183*6777b538SAndroid Build Coastguard Worker xmlXPathContextPtr ctxt)
13184*6777b538SAndroid Build Coastguard Worker {
13185*6777b538SAndroid Build Coastguard Worker return(xmlXPathCompiledEvalInternal(comp, ctxt, NULL, 1));
13186*6777b538SAndroid Build Coastguard Worker }
13187*6777b538SAndroid Build Coastguard Worker
13188*6777b538SAndroid Build Coastguard Worker /**
13189*6777b538SAndroid Build Coastguard Worker * xmlXPathEvalExpr:
13190*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
13191*6777b538SAndroid Build Coastguard Worker *
13192*6777b538SAndroid Build Coastguard Worker * Parse and evaluate an XPath expression in the given context,
13193*6777b538SAndroid Build Coastguard Worker * then push the result on the context stack
13194*6777b538SAndroid Build Coastguard Worker */
13195*6777b538SAndroid Build Coastguard Worker void
xmlXPathEvalExpr(xmlXPathParserContextPtr ctxt)13196*6777b538SAndroid Build Coastguard Worker xmlXPathEvalExpr(xmlXPathParserContextPtr ctxt) {
13197*6777b538SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
13198*6777b538SAndroid Build Coastguard Worker xmlXPathCompExprPtr comp;
13199*6777b538SAndroid Build Coastguard Worker #endif
13200*6777b538SAndroid Build Coastguard Worker int oldDepth = 0;
13201*6777b538SAndroid Build Coastguard Worker
13202*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
13203*6777b538SAndroid Build Coastguard Worker return;
13204*6777b538SAndroid Build Coastguard Worker if (ctxt->context->lastError.code != 0)
13205*6777b538SAndroid Build Coastguard Worker return;
13206*6777b538SAndroid Build Coastguard Worker
13207*6777b538SAndroid Build Coastguard Worker #ifdef XPATH_STREAMING
13208*6777b538SAndroid Build Coastguard Worker comp = xmlXPathTryStreamCompile(ctxt->context, ctxt->base);
13209*6777b538SAndroid Build Coastguard Worker if ((comp == NULL) &&
13210*6777b538SAndroid Build Coastguard Worker (ctxt->context->lastError.code == XML_ERR_NO_MEMORY)) {
13211*6777b538SAndroid Build Coastguard Worker xmlXPathPErrMemory(ctxt);
13212*6777b538SAndroid Build Coastguard Worker return;
13213*6777b538SAndroid Build Coastguard Worker }
13214*6777b538SAndroid Build Coastguard Worker if (comp != NULL) {
13215*6777b538SAndroid Build Coastguard Worker if (ctxt->comp != NULL)
13216*6777b538SAndroid Build Coastguard Worker xmlXPathFreeCompExpr(ctxt->comp);
13217*6777b538SAndroid Build Coastguard Worker ctxt->comp = comp;
13218*6777b538SAndroid Build Coastguard Worker } else
13219*6777b538SAndroid Build Coastguard Worker #endif
13220*6777b538SAndroid Build Coastguard Worker {
13221*6777b538SAndroid Build Coastguard Worker if (ctxt->context != NULL)
13222*6777b538SAndroid Build Coastguard Worker oldDepth = ctxt->context->depth;
13223*6777b538SAndroid Build Coastguard Worker xmlXPathCompileExpr(ctxt, 1);
13224*6777b538SAndroid Build Coastguard Worker if (ctxt->context != NULL)
13225*6777b538SAndroid Build Coastguard Worker ctxt->context->depth = oldDepth;
13226*6777b538SAndroid Build Coastguard Worker CHECK_ERROR;
13227*6777b538SAndroid Build Coastguard Worker
13228*6777b538SAndroid Build Coastguard Worker /* Check for trailing characters. */
13229*6777b538SAndroid Build Coastguard Worker if (*ctxt->cur != 0)
13230*6777b538SAndroid Build Coastguard Worker XP_ERROR(XPATH_EXPR_ERROR);
13231*6777b538SAndroid Build Coastguard Worker
13232*6777b538SAndroid Build Coastguard Worker if ((ctxt->comp->nbStep > 1) && (ctxt->comp->last >= 0)) {
13233*6777b538SAndroid Build Coastguard Worker if (ctxt->context != NULL)
13234*6777b538SAndroid Build Coastguard Worker oldDepth = ctxt->context->depth;
13235*6777b538SAndroid Build Coastguard Worker xmlXPathOptimizeExpression(ctxt,
13236*6777b538SAndroid Build Coastguard Worker &ctxt->comp->steps[ctxt->comp->last]);
13237*6777b538SAndroid Build Coastguard Worker if (ctxt->context != NULL)
13238*6777b538SAndroid Build Coastguard Worker ctxt->context->depth = oldDepth;
13239*6777b538SAndroid Build Coastguard Worker }
13240*6777b538SAndroid Build Coastguard Worker }
13241*6777b538SAndroid Build Coastguard Worker
13242*6777b538SAndroid Build Coastguard Worker xmlXPathRunEval(ctxt, 0);
13243*6777b538SAndroid Build Coastguard Worker }
13244*6777b538SAndroid Build Coastguard Worker
13245*6777b538SAndroid Build Coastguard Worker /**
13246*6777b538SAndroid Build Coastguard Worker * xmlXPathEval:
13247*6777b538SAndroid Build Coastguard Worker * @str: the XPath expression
13248*6777b538SAndroid Build Coastguard Worker * @ctx: the XPath context
13249*6777b538SAndroid Build Coastguard Worker *
13250*6777b538SAndroid Build Coastguard Worker * Evaluate the XPath Location Path in the given context.
13251*6777b538SAndroid Build Coastguard Worker *
13252*6777b538SAndroid Build Coastguard Worker * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
13253*6777b538SAndroid Build Coastguard Worker * the caller has to free the object.
13254*6777b538SAndroid Build Coastguard Worker */
13255*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathEval(const xmlChar * str,xmlXPathContextPtr ctx)13256*6777b538SAndroid Build Coastguard Worker xmlXPathEval(const xmlChar *str, xmlXPathContextPtr ctx) {
13257*6777b538SAndroid Build Coastguard Worker xmlXPathParserContextPtr ctxt;
13258*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr res;
13259*6777b538SAndroid Build Coastguard Worker
13260*6777b538SAndroid Build Coastguard Worker if (ctx == NULL)
13261*6777b538SAndroid Build Coastguard Worker return(NULL);
13262*6777b538SAndroid Build Coastguard Worker
13263*6777b538SAndroid Build Coastguard Worker xmlInitParser();
13264*6777b538SAndroid Build Coastguard Worker
13265*6777b538SAndroid Build Coastguard Worker xmlResetError(&ctx->lastError);
13266*6777b538SAndroid Build Coastguard Worker
13267*6777b538SAndroid Build Coastguard Worker ctxt = xmlXPathNewParserContext(str, ctx);
13268*6777b538SAndroid Build Coastguard Worker if (ctxt == NULL)
13269*6777b538SAndroid Build Coastguard Worker return NULL;
13270*6777b538SAndroid Build Coastguard Worker xmlXPathEvalExpr(ctxt);
13271*6777b538SAndroid Build Coastguard Worker
13272*6777b538SAndroid Build Coastguard Worker if (ctxt->error != XPATH_EXPRESSION_OK) {
13273*6777b538SAndroid Build Coastguard Worker res = NULL;
13274*6777b538SAndroid Build Coastguard Worker } else if (ctxt->valueNr != 1) {
13275*6777b538SAndroid Build Coastguard Worker xmlXPathErr(ctxt, XPATH_STACK_ERROR);
13276*6777b538SAndroid Build Coastguard Worker res = NULL;
13277*6777b538SAndroid Build Coastguard Worker } else {
13278*6777b538SAndroid Build Coastguard Worker res = valuePop(ctxt);
13279*6777b538SAndroid Build Coastguard Worker }
13280*6777b538SAndroid Build Coastguard Worker
13281*6777b538SAndroid Build Coastguard Worker xmlXPathFreeParserContext(ctxt);
13282*6777b538SAndroid Build Coastguard Worker return(res);
13283*6777b538SAndroid Build Coastguard Worker }
13284*6777b538SAndroid Build Coastguard Worker
13285*6777b538SAndroid Build Coastguard Worker /**
13286*6777b538SAndroid Build Coastguard Worker * xmlXPathSetContextNode:
13287*6777b538SAndroid Build Coastguard Worker * @node: the node to to use as the context node
13288*6777b538SAndroid Build Coastguard Worker * @ctx: the XPath context
13289*6777b538SAndroid Build Coastguard Worker *
13290*6777b538SAndroid Build Coastguard Worker * Sets 'node' as the context node. The node must be in the same
13291*6777b538SAndroid Build Coastguard Worker * document as that associated with the context.
13292*6777b538SAndroid Build Coastguard Worker *
13293*6777b538SAndroid Build Coastguard Worker * Returns -1 in case of error or 0 if successful
13294*6777b538SAndroid Build Coastguard Worker */
13295*6777b538SAndroid Build Coastguard Worker int
xmlXPathSetContextNode(xmlNodePtr node,xmlXPathContextPtr ctx)13296*6777b538SAndroid Build Coastguard Worker xmlXPathSetContextNode(xmlNodePtr node, xmlXPathContextPtr ctx) {
13297*6777b538SAndroid Build Coastguard Worker if ((node == NULL) || (ctx == NULL))
13298*6777b538SAndroid Build Coastguard Worker return(-1);
13299*6777b538SAndroid Build Coastguard Worker
13300*6777b538SAndroid Build Coastguard Worker if (node->doc == ctx->doc) {
13301*6777b538SAndroid Build Coastguard Worker ctx->node = node;
13302*6777b538SAndroid Build Coastguard Worker return(0);
13303*6777b538SAndroid Build Coastguard Worker }
13304*6777b538SAndroid Build Coastguard Worker return(-1);
13305*6777b538SAndroid Build Coastguard Worker }
13306*6777b538SAndroid Build Coastguard Worker
13307*6777b538SAndroid Build Coastguard Worker /**
13308*6777b538SAndroid Build Coastguard Worker * xmlXPathNodeEval:
13309*6777b538SAndroid Build Coastguard Worker * @node: the node to to use as the context node
13310*6777b538SAndroid Build Coastguard Worker * @str: the XPath expression
13311*6777b538SAndroid Build Coastguard Worker * @ctx: the XPath context
13312*6777b538SAndroid Build Coastguard Worker *
13313*6777b538SAndroid Build Coastguard Worker * Evaluate the XPath Location Path in the given context. The node 'node'
13314*6777b538SAndroid Build Coastguard Worker * is set as the context node. The context node is not restored.
13315*6777b538SAndroid Build Coastguard Worker *
13316*6777b538SAndroid Build Coastguard Worker * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
13317*6777b538SAndroid Build Coastguard Worker * the caller has to free the object.
13318*6777b538SAndroid Build Coastguard Worker */
13319*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathNodeEval(xmlNodePtr node,const xmlChar * str,xmlXPathContextPtr ctx)13320*6777b538SAndroid Build Coastguard Worker xmlXPathNodeEval(xmlNodePtr node, const xmlChar *str, xmlXPathContextPtr ctx) {
13321*6777b538SAndroid Build Coastguard Worker if (str == NULL)
13322*6777b538SAndroid Build Coastguard Worker return(NULL);
13323*6777b538SAndroid Build Coastguard Worker if (xmlXPathSetContextNode(node, ctx) < 0)
13324*6777b538SAndroid Build Coastguard Worker return(NULL);
13325*6777b538SAndroid Build Coastguard Worker return(xmlXPathEval(str, ctx));
13326*6777b538SAndroid Build Coastguard Worker }
13327*6777b538SAndroid Build Coastguard Worker
13328*6777b538SAndroid Build Coastguard Worker /**
13329*6777b538SAndroid Build Coastguard Worker * xmlXPathEvalExpression:
13330*6777b538SAndroid Build Coastguard Worker * @str: the XPath expression
13331*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath context
13332*6777b538SAndroid Build Coastguard Worker *
13333*6777b538SAndroid Build Coastguard Worker * Alias for xmlXPathEval().
13334*6777b538SAndroid Build Coastguard Worker *
13335*6777b538SAndroid Build Coastguard Worker * Returns the xmlXPathObjectPtr resulting from the evaluation or NULL.
13336*6777b538SAndroid Build Coastguard Worker * the caller has to free the object.
13337*6777b538SAndroid Build Coastguard Worker */
13338*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr
xmlXPathEvalExpression(const xmlChar * str,xmlXPathContextPtr ctxt)13339*6777b538SAndroid Build Coastguard Worker xmlXPathEvalExpression(const xmlChar *str, xmlXPathContextPtr ctxt) {
13340*6777b538SAndroid Build Coastguard Worker return(xmlXPathEval(str, ctxt));
13341*6777b538SAndroid Build Coastguard Worker }
13342*6777b538SAndroid Build Coastguard Worker
13343*6777b538SAndroid Build Coastguard Worker /************************************************************************
13344*6777b538SAndroid Build Coastguard Worker * *
13345*6777b538SAndroid Build Coastguard Worker * Extra functions not pertaining to the XPath spec *
13346*6777b538SAndroid Build Coastguard Worker * *
13347*6777b538SAndroid Build Coastguard Worker ************************************************************************/
13348*6777b538SAndroid Build Coastguard Worker /**
13349*6777b538SAndroid Build Coastguard Worker * xmlXPathEscapeUriFunction:
13350*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath Parser context
13351*6777b538SAndroid Build Coastguard Worker * @nargs: the number of arguments
13352*6777b538SAndroid Build Coastguard Worker *
13353*6777b538SAndroid Build Coastguard Worker * Implement the escape-uri() XPath function
13354*6777b538SAndroid Build Coastguard Worker * string escape-uri(string $str, bool $escape-reserved)
13355*6777b538SAndroid Build Coastguard Worker *
13356*6777b538SAndroid Build Coastguard Worker * This function applies the URI escaping rules defined in section 2 of [RFC
13357*6777b538SAndroid Build Coastguard Worker * 2396] to the string supplied as $uri-part, which typically represents all
13358*6777b538SAndroid Build Coastguard Worker * or part of a URI. The effect of the function is to replace any special
13359*6777b538SAndroid Build Coastguard Worker * character in the string by an escape sequence of the form %xx%yy...,
13360*6777b538SAndroid Build Coastguard Worker * where xxyy... is the hexadecimal representation of the octets used to
13361*6777b538SAndroid Build Coastguard Worker * represent the character in UTF-8.
13362*6777b538SAndroid Build Coastguard Worker *
13363*6777b538SAndroid Build Coastguard Worker * The set of characters that are escaped depends on the setting of the
13364*6777b538SAndroid Build Coastguard Worker * boolean argument $escape-reserved.
13365*6777b538SAndroid Build Coastguard Worker *
13366*6777b538SAndroid Build Coastguard Worker * If $escape-reserved is true, all characters are escaped other than lower
13367*6777b538SAndroid Build Coastguard Worker * case letters a-z, upper case letters A-Z, digits 0-9, and the characters
13368*6777b538SAndroid Build Coastguard Worker * referred to in [RFC 2396] as "marks": specifically, "-" | "_" | "." | "!"
13369*6777b538SAndroid Build Coastguard Worker * | "~" | "*" | "'" | "(" | ")". The "%" character itself is escaped only
13370*6777b538SAndroid Build Coastguard Worker * if it is not followed by two hexadecimal digits (that is, 0-9, a-f, and
13371*6777b538SAndroid Build Coastguard Worker * A-F).
13372*6777b538SAndroid Build Coastguard Worker *
13373*6777b538SAndroid Build Coastguard Worker * If $escape-reserved is false, the behavior differs in that characters
13374*6777b538SAndroid Build Coastguard Worker * referred to in [RFC 2396] as reserved characters are not escaped. These
13375*6777b538SAndroid Build Coastguard Worker * characters are ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ",".
13376*6777b538SAndroid Build Coastguard Worker *
13377*6777b538SAndroid Build Coastguard Worker * [RFC 2396] does not define whether escaped URIs should use lower case or
13378*6777b538SAndroid Build Coastguard Worker * upper case for hexadecimal digits. To ensure that escaped URIs can be
13379*6777b538SAndroid Build Coastguard Worker * compared using string comparison functions, this function must always use
13380*6777b538SAndroid Build Coastguard Worker * the upper-case letters A-F.
13381*6777b538SAndroid Build Coastguard Worker *
13382*6777b538SAndroid Build Coastguard Worker * Generally, $escape-reserved should be set to true when escaping a string
13383*6777b538SAndroid Build Coastguard Worker * that is to form a single part of a URI, and to false when escaping an
13384*6777b538SAndroid Build Coastguard Worker * entire URI or URI reference.
13385*6777b538SAndroid Build Coastguard Worker *
13386*6777b538SAndroid Build Coastguard Worker * In the case of non-ascii characters, the string is encoded according to
13387*6777b538SAndroid Build Coastguard Worker * utf-8 and then converted according to RFC 2396.
13388*6777b538SAndroid Build Coastguard Worker *
13389*6777b538SAndroid Build Coastguard Worker * Examples
13390*6777b538SAndroid Build Coastguard Worker * xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles#ocean"), true())
13391*6777b538SAndroid Build Coastguard Worker * returns "gopher%3A%2F%2Fspinaltap.micro.umn.edu%2F00%2FWeather%2FCalifornia%2FLos%20Angeles%23ocean"
13392*6777b538SAndroid Build Coastguard Worker * xf:escape-uri ("gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles#ocean"), false())
13393*6777b538SAndroid Build Coastguard Worker * returns "gopher://spinaltap.micro.umn.edu/00/Weather/California/Los%20Angeles%23ocean"
13394*6777b538SAndroid Build Coastguard Worker *
13395*6777b538SAndroid Build Coastguard Worker */
13396*6777b538SAndroid Build Coastguard Worker static void
xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt,int nargs)13397*6777b538SAndroid Build Coastguard Worker xmlXPathEscapeUriFunction(xmlXPathParserContextPtr ctxt, int nargs) {
13398*6777b538SAndroid Build Coastguard Worker xmlXPathObjectPtr str;
13399*6777b538SAndroid Build Coastguard Worker int escape_reserved;
13400*6777b538SAndroid Build Coastguard Worker xmlBufPtr target;
13401*6777b538SAndroid Build Coastguard Worker xmlChar *cptr;
13402*6777b538SAndroid Build Coastguard Worker xmlChar escape[4];
13403*6777b538SAndroid Build Coastguard Worker
13404*6777b538SAndroid Build Coastguard Worker CHECK_ARITY(2);
13405*6777b538SAndroid Build Coastguard Worker
13406*6777b538SAndroid Build Coastguard Worker escape_reserved = xmlXPathPopBoolean(ctxt);
13407*6777b538SAndroid Build Coastguard Worker
13408*6777b538SAndroid Build Coastguard Worker CAST_TO_STRING;
13409*6777b538SAndroid Build Coastguard Worker str = valuePop(ctxt);
13410*6777b538SAndroid Build Coastguard Worker
13411*6777b538SAndroid Build Coastguard Worker target = xmlBufCreate();
13412*6777b538SAndroid Build Coastguard Worker
13413*6777b538SAndroid Build Coastguard Worker escape[0] = '%';
13414*6777b538SAndroid Build Coastguard Worker escape[3] = 0;
13415*6777b538SAndroid Build Coastguard Worker
13416*6777b538SAndroid Build Coastguard Worker if (target) {
13417*6777b538SAndroid Build Coastguard Worker for (cptr = str->stringval; *cptr; cptr++) {
13418*6777b538SAndroid Build Coastguard Worker if ((*cptr >= 'A' && *cptr <= 'Z') ||
13419*6777b538SAndroid Build Coastguard Worker (*cptr >= 'a' && *cptr <= 'z') ||
13420*6777b538SAndroid Build Coastguard Worker (*cptr >= '0' && *cptr <= '9') ||
13421*6777b538SAndroid Build Coastguard Worker *cptr == '-' || *cptr == '_' || *cptr == '.' ||
13422*6777b538SAndroid Build Coastguard Worker *cptr == '!' || *cptr == '~' || *cptr == '*' ||
13423*6777b538SAndroid Build Coastguard Worker *cptr == '\''|| *cptr == '(' || *cptr == ')' ||
13424*6777b538SAndroid Build Coastguard Worker (*cptr == '%' &&
13425*6777b538SAndroid Build Coastguard Worker ((cptr[1] >= 'A' && cptr[1] <= 'F') ||
13426*6777b538SAndroid Build Coastguard Worker (cptr[1] >= 'a' && cptr[1] <= 'f') ||
13427*6777b538SAndroid Build Coastguard Worker (cptr[1] >= '0' && cptr[1] <= '9')) &&
13428*6777b538SAndroid Build Coastguard Worker ((cptr[2] >= 'A' && cptr[2] <= 'F') ||
13429*6777b538SAndroid Build Coastguard Worker (cptr[2] >= 'a' && cptr[2] <= 'f') ||
13430*6777b538SAndroid Build Coastguard Worker (cptr[2] >= '0' && cptr[2] <= '9'))) ||
13431*6777b538SAndroid Build Coastguard Worker (!escape_reserved &&
13432*6777b538SAndroid Build Coastguard Worker (*cptr == ';' || *cptr == '/' || *cptr == '?' ||
13433*6777b538SAndroid Build Coastguard Worker *cptr == ':' || *cptr == '@' || *cptr == '&' ||
13434*6777b538SAndroid Build Coastguard Worker *cptr == '=' || *cptr == '+' || *cptr == '$' ||
13435*6777b538SAndroid Build Coastguard Worker *cptr == ','))) {
13436*6777b538SAndroid Build Coastguard Worker xmlBufAdd(target, cptr, 1);
13437*6777b538SAndroid Build Coastguard Worker } else {
13438*6777b538SAndroid Build Coastguard Worker if ((*cptr >> 4) < 10)
13439*6777b538SAndroid Build Coastguard Worker escape[1] = '0' + (*cptr >> 4);
13440*6777b538SAndroid Build Coastguard Worker else
13441*6777b538SAndroid Build Coastguard Worker escape[1] = 'A' - 10 + (*cptr >> 4);
13442*6777b538SAndroid Build Coastguard Worker if ((*cptr & 0xF) < 10)
13443*6777b538SAndroid Build Coastguard Worker escape[2] = '0' + (*cptr & 0xF);
13444*6777b538SAndroid Build Coastguard Worker else
13445*6777b538SAndroid Build Coastguard Worker escape[2] = 'A' - 10 + (*cptr & 0xF);
13446*6777b538SAndroid Build Coastguard Worker
13447*6777b538SAndroid Build Coastguard Worker xmlBufAdd(target, &escape[0], 3);
13448*6777b538SAndroid Build Coastguard Worker }
13449*6777b538SAndroid Build Coastguard Worker }
13450*6777b538SAndroid Build Coastguard Worker }
13451*6777b538SAndroid Build Coastguard Worker valuePush(ctxt, xmlXPathCacheNewString(ctxt, xmlBufContent(target)));
13452*6777b538SAndroid Build Coastguard Worker xmlBufFree(target);
13453*6777b538SAndroid Build Coastguard Worker xmlXPathReleaseObject(ctxt->context, str);
13454*6777b538SAndroid Build Coastguard Worker }
13455*6777b538SAndroid Build Coastguard Worker
13456*6777b538SAndroid Build Coastguard Worker /**
13457*6777b538SAndroid Build Coastguard Worker * xmlXPathRegisterAllFunctions:
13458*6777b538SAndroid Build Coastguard Worker * @ctxt: the XPath context
13459*6777b538SAndroid Build Coastguard Worker *
13460*6777b538SAndroid Build Coastguard Worker * Registers all default XPath functions in this context
13461*6777b538SAndroid Build Coastguard Worker */
13462*6777b538SAndroid Build Coastguard Worker void
xmlXPathRegisterAllFunctions(xmlXPathContextPtr ctxt)13463*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterAllFunctions(xmlXPathContextPtr ctxt)
13464*6777b538SAndroid Build Coastguard Worker {
13465*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"boolean",
13466*6777b538SAndroid Build Coastguard Worker xmlXPathBooleanFunction);
13467*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"ceiling",
13468*6777b538SAndroid Build Coastguard Worker xmlXPathCeilingFunction);
13469*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"count",
13470*6777b538SAndroid Build Coastguard Worker xmlXPathCountFunction);
13471*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"concat",
13472*6777b538SAndroid Build Coastguard Worker xmlXPathConcatFunction);
13473*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"contains",
13474*6777b538SAndroid Build Coastguard Worker xmlXPathContainsFunction);
13475*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"id",
13476*6777b538SAndroid Build Coastguard Worker xmlXPathIdFunction);
13477*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"false",
13478*6777b538SAndroid Build Coastguard Worker xmlXPathFalseFunction);
13479*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"floor",
13480*6777b538SAndroid Build Coastguard Worker xmlXPathFloorFunction);
13481*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"last",
13482*6777b538SAndroid Build Coastguard Worker xmlXPathLastFunction);
13483*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"lang",
13484*6777b538SAndroid Build Coastguard Worker xmlXPathLangFunction);
13485*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"local-name",
13486*6777b538SAndroid Build Coastguard Worker xmlXPathLocalNameFunction);
13487*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"not",
13488*6777b538SAndroid Build Coastguard Worker xmlXPathNotFunction);
13489*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"name",
13490*6777b538SAndroid Build Coastguard Worker xmlXPathNameFunction);
13491*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"namespace-uri",
13492*6777b538SAndroid Build Coastguard Worker xmlXPathNamespaceURIFunction);
13493*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"normalize-space",
13494*6777b538SAndroid Build Coastguard Worker xmlXPathNormalizeFunction);
13495*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"number",
13496*6777b538SAndroid Build Coastguard Worker xmlXPathNumberFunction);
13497*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"position",
13498*6777b538SAndroid Build Coastguard Worker xmlXPathPositionFunction);
13499*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"round",
13500*6777b538SAndroid Build Coastguard Worker xmlXPathRoundFunction);
13501*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"string",
13502*6777b538SAndroid Build Coastguard Worker xmlXPathStringFunction);
13503*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"string-length",
13504*6777b538SAndroid Build Coastguard Worker xmlXPathStringLengthFunction);
13505*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"starts-with",
13506*6777b538SAndroid Build Coastguard Worker xmlXPathStartsWithFunction);
13507*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring",
13508*6777b538SAndroid Build Coastguard Worker xmlXPathSubstringFunction);
13509*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring-before",
13510*6777b538SAndroid Build Coastguard Worker xmlXPathSubstringBeforeFunction);
13511*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"substring-after",
13512*6777b538SAndroid Build Coastguard Worker xmlXPathSubstringAfterFunction);
13513*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"sum",
13514*6777b538SAndroid Build Coastguard Worker xmlXPathSumFunction);
13515*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"true",
13516*6777b538SAndroid Build Coastguard Worker xmlXPathTrueFunction);
13517*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFunc(ctxt, (const xmlChar *)"translate",
13518*6777b538SAndroid Build Coastguard Worker xmlXPathTranslateFunction);
13519*6777b538SAndroid Build Coastguard Worker
13520*6777b538SAndroid Build Coastguard Worker xmlXPathRegisterFuncNS(ctxt, (const xmlChar *)"escape-uri",
13521*6777b538SAndroid Build Coastguard Worker (const xmlChar *)"http://www.w3.org/2002/08/xquery-functions",
13522*6777b538SAndroid Build Coastguard Worker xmlXPathEscapeUriFunction);
13523*6777b538SAndroid Build Coastguard Worker }
13524*6777b538SAndroid Build Coastguard Worker
13525*6777b538SAndroid Build Coastguard Worker #endif /* LIBXML_XPATH_ENABLED */
13526