b62a39d587d2f86dc0e199774365d3d3de3d8374
[platform/upstream/libxslt.git] / libexslt / sets.c
1 #include "libexslt/libexslt.h"
2
3 #if defined(WIN32) && !defined (__CYGWIN__)
4 #include <win32config.h>
5 #else
6 #include "config.h"
7 #endif
8
9 #include <libxml/tree.h>
10 #include <libxml/xpath.h>
11 #include <libxml/xpathInternals.h>
12
13 #include <libxslt/xsltutils.h>
14 #include <libxslt/xsltInternals.h>
15 #include <libxslt/extensions.h>
16
17 #include "exslt.h"
18
19 /**
20  * exsltSetsDifferenceFunction:
21  * @ctxt:  an XPath parser context
22  * @nargs:  the number of arguments
23  *
24  * Wraps #xmlXPathDifference for use by the XPath processor
25  */
26 static void
27 exsltSetsDifferenceFunction (xmlXPathParserContextPtr ctxt, int nargs) {
28     xmlNodeSetPtr arg1, arg2, ret;
29
30     if (nargs != 2) {
31         xmlXPathSetArityError(ctxt);
32         return;
33     }
34
35     arg2 = xmlXPathPopNodeSet(ctxt);
36     if (xmlXPathCheckError(ctxt)) {
37         xmlXPathSetTypeError(ctxt);
38         return;
39     }
40
41     arg1 = xmlXPathPopNodeSet(ctxt);
42     if (xmlXPathCheckError(ctxt)) {
43         xmlXPathSetTypeError(ctxt);
44         return;
45     }
46
47     ret = xmlXPathDifference(arg1, arg2);
48
49     if (ret != arg1)
50         xmlXPathFreeNodeSet(arg1);
51     xmlXPathFreeNodeSet(arg2);
52
53     xmlXPathReturnNodeSet(ctxt, ret);
54 }
55
56 /**
57  * exsltSetsIntersectionFunction:
58  * @ctxt:  an XPath parser context
59  * @nargs:  the number of arguments
60  *
61  * Wraps #xmlXPathIntersection for use by the XPath processor
62  */
63 static void
64 exsltSetsIntersectionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
65     xmlNodeSetPtr arg1, arg2, ret;
66
67     if (nargs != 2) {
68         xmlXPathSetArityError(ctxt);
69         return;
70     }
71
72     arg2 = xmlXPathPopNodeSet(ctxt);
73     if (xmlXPathCheckError(ctxt)) {
74         xmlXPathSetTypeError(ctxt);
75         return;
76     }
77
78     arg1 = xmlXPathPopNodeSet(ctxt);
79     if (xmlXPathCheckError(ctxt)) {
80         xmlXPathSetTypeError(ctxt);
81         return;
82     }
83
84     ret = xmlXPathIntersection(arg1, arg2);
85
86     xmlXPathFreeNodeSet(arg1);
87     xmlXPathFreeNodeSet(arg2);
88
89     xmlXPathReturnNodeSet(ctxt, ret);
90 }
91
92 /**
93  * exsltSetsDistinctFunction:
94  * @ctxt:  an XPath parser context
95  * @nargs:  the number of arguments
96  *
97  * Wraps #xmlXPathDistinct for use by the XPath processor
98  */
99 static void
100 exsltSetsDistinctFunction (xmlXPathParserContextPtr ctxt, int nargs) {
101     xmlNodeSetPtr ns, ret;
102
103     if (nargs != 1) {
104         xmlXPathSetArityError(ctxt);
105         return;
106     }
107
108     ns = xmlXPathPopNodeSet(ctxt);
109     if (xmlXPathCheckError(ctxt))
110         return;
111
112     /* !!! must be sorted !!! */
113     ret = xmlXPathDistinctSorted(ns);
114
115     xmlXPathFreeNodeSet(ns);
116
117     xmlXPathReturnNodeSet(ctxt, ret);
118 }
119
120 /**
121  * exsltSetsHasSameNodesFunction:
122  * @ctxt:  an XPath parser context
123  * @nargs:  the number of arguments
124  *
125  * Wraps #xmlXPathHasSameNodes for use by the XPath processor
126  */
127 static void
128 exsltSetsHasSameNodesFunction (xmlXPathParserContextPtr ctxt,
129                               int nargs) {
130     xmlNodeSetPtr arg1, arg2;
131     int ret;
132
133     if (nargs != 2) {
134         xmlXPathSetArityError(ctxt);
135         return;
136     }
137
138     arg2 = xmlXPathPopNodeSet(ctxt);
139     if (xmlXPathCheckError(ctxt)) {
140         xmlXPathSetTypeError(ctxt);
141         return;
142     }
143
144     arg1 = xmlXPathPopNodeSet(ctxt);
145     if (xmlXPathCheckError(ctxt)) {
146         xmlXPathSetTypeError(ctxt);
147         return;
148     }
149
150     ret = xmlXPathHasSameNodes(arg1, arg2);
151
152     xmlXPathFreeNodeSet(arg1);
153     xmlXPathFreeNodeSet(arg2);
154
155     xmlXPathReturnBoolean(ctxt, ret);
156 }
157
158 /**
159  * exsltSetsLeadingFunction:
160  * @ctxt:  an XPath parser context
161  * @nargs:  the number of arguments
162  *
163  * Wraps #xmlXPathLeading for use by the XPath processor
164  */
165 static void
166 exsltSetsLeadingFunction (xmlXPathParserContextPtr ctxt, int nargs) {
167     xmlNodeSetPtr arg1, arg2, ret;
168
169     if (nargs != 2) {
170         xmlXPathSetArityError(ctxt);
171         return;
172     }
173
174     arg2 = xmlXPathPopNodeSet(ctxt);
175     if (xmlXPathCheckError(ctxt)) {
176         xmlXPathSetTypeError(ctxt);
177         return;
178     }
179
180     arg1 = xmlXPathPopNodeSet(ctxt);
181     if (xmlXPathCheckError(ctxt)) {
182         xmlXPathSetTypeError(ctxt);
183         return;
184     }
185
186     /*  If the second node set is empty, then the first node set is
187      * returned.
188      */
189     if (xmlXPathNodeSetIsEmpty(arg2)) {
190         xmlXPathReturnNodeSet(ctxt, arg1);
191
192         xmlXPathFreeNodeSet(arg2);
193
194         return;
195     }
196     /* !!! must be sorted */
197     ret = xmlXPathNodeLeadingSorted(arg1, xmlXPathNodeSetItem(arg2, 0));
198
199     xmlXPathFreeNodeSet(arg1);
200     xmlXPathFreeNodeSet(arg2);
201
202     xmlXPathReturnNodeSet(ctxt, ret);
203 }
204
205 /**
206  * exsltSetsTrailingFunction:
207  * @ctxt:  an XPath parser context
208  * @nargs:  the number of arguments
209  *
210  * Wraps #xmlXPathTrailing for use by the XPath processor
211  */
212 static void
213 exsltSetsTrailingFunction (xmlXPathParserContextPtr ctxt, int nargs) {
214     xmlNodeSetPtr arg1, arg2, ret;
215
216     if (nargs != 2) {
217         xmlXPathSetArityError(ctxt);
218         return;
219     }
220
221     arg2 = xmlXPathPopNodeSet(ctxt);
222     if (xmlXPathCheckError(ctxt)) {
223         xmlXPathSetTypeError(ctxt);
224         return;
225     }
226
227     arg1 = xmlXPathPopNodeSet(ctxt);
228     if (xmlXPathCheckError(ctxt)) {
229         xmlXPathSetTypeError(ctxt);
230         return;
231     }
232
233     /*  If the second node set is empty, then the first node set is
234      * returned.
235      */
236     if (xmlXPathNodeSetIsEmpty(arg2)) {
237         xmlXPathReturnNodeSet(ctxt, arg1);
238
239         xmlXPathFreeNodeSet(arg2);
240
241         return;
242     }
243     /* !!! mist be sorted */
244     ret = xmlXPathNodeTrailingSorted(arg1, xmlXPathNodeSetItem(arg2, 0));
245
246     xmlXPathFreeNodeSet(arg1);
247     xmlXPathFreeNodeSet(arg2);
248
249     xmlXPathReturnNodeSet(ctxt, ret);
250 }
251
252 /**
253  * exsltSetsRegister:
254  *
255  * Registers the EXSLT - Sets module
256  */
257
258 void
259 exsltSetsRegister (void) {
260     xsltRegisterExtModuleFunction ((const xmlChar *) "difference",
261                                    EXSLT_SETS_NAMESPACE,
262                                    exsltSetsDifferenceFunction);
263     xsltRegisterExtModuleFunction ((const xmlChar *) "intersection",
264                                    EXSLT_SETS_NAMESPACE,
265                                    exsltSetsIntersectionFunction);
266     xsltRegisterExtModuleFunction ((const xmlChar *) "distinct",
267                                    EXSLT_SETS_NAMESPACE,
268                                    exsltSetsDistinctFunction);
269     xsltRegisterExtModuleFunction ((const xmlChar *) "has-same-node",
270                                    EXSLT_SETS_NAMESPACE,
271                                    exsltSetsHasSameNodesFunction);
272     xsltRegisterExtModuleFunction ((const xmlChar *) "leading",
273                                    EXSLT_SETS_NAMESPACE,
274                                    exsltSetsLeadingFunction);
275     xsltRegisterExtModuleFunction ((const xmlChar *) "trailing",
276                                    EXSLT_SETS_NAMESPACE,
277                                    exsltSetsTrailingFunction);
278 }