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