Coverage Report

Created: 2023-03-26 06:13

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