Coverage Report

Created: 2026-03-06 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libxslt/libexslt/sets.c
Line
Count
Source
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
679
exsltSetsDifferenceFunction (xmlXPathParserContextPtr ctxt, int nargs) {
23
679
    xmlNodeSetPtr arg1, arg2, ret;
24
25
679
    if (nargs != 2) {
26
1
  xmlXPathSetArityError(ctxt);
27
1
  return;
28
1
    }
29
30
678
    arg2 = xmlXPathPopNodeSet(ctxt);
31
678
    if (xmlXPathCheckError(ctxt))
32
1
  return;
33
34
677
    arg1 = xmlXPathPopNodeSet(ctxt);
35
677
    if (xmlXPathCheckError(ctxt)) {
36
1
        xmlXPathFreeNodeSet(arg2);
37
1
  return;
38
1
    }
39
40
676
    ret = xmlXPathDifference(arg1, arg2);
41
42
676
    if (ret != arg1)
43
586
  xmlXPathFreeNodeSet(arg1);
44
676
    xmlXPathFreeNodeSet(arg2);
45
46
676
    xmlXPathReturnNodeSet(ctxt, ret);
47
676
}
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
847
exsltSetsIntersectionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
58
847
    xmlNodeSetPtr arg1, arg2, ret;
59
60
847
    if (nargs != 2) {
61
1
  xmlXPathSetArityError(ctxt);
62
1
  return;
63
1
    }
64
65
846
    arg2 = xmlXPathPopNodeSet(ctxt);
66
846
    if (xmlXPathCheckError(ctxt))
67
1
  return;
68
69
845
    arg1 = xmlXPathPopNodeSet(ctxt);
70
845
    if (xmlXPathCheckError(ctxt)) {
71
1
        xmlXPathFreeNodeSet(arg2);
72
1
  return;
73
1
    }
74
75
844
    ret = xmlXPathIntersection(arg1, arg2);
76
77
844
    xmlXPathFreeNodeSet(arg1);
78
844
    xmlXPathFreeNodeSet(arg2);
79
80
844
    xmlXPathReturnNodeSet(ctxt, ret);
81
844
}
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
597
exsltSetsDistinctFunction (xmlXPathParserContextPtr ctxt, int nargs) {
92
597
    xmlXPathObjectPtr obj;
93
597
    xmlNodeSetPtr ns, ret;
94
597
    int boolval = 0;
95
597
    void *user = NULL;
96
97
597
    if (nargs != 1) {
98
1
  xmlXPathSetArityError(ctxt);
99
1
  return;
100
1
    }
101
102
596
    if (ctxt->value != NULL) {
103
596
        boolval = ctxt->value->boolval;
104
596
  user = ctxt->value->user;
105
596
  ctxt->value->boolval = 0;
106
596
  ctxt->value->user = NULL;
107
596
    }
108
596
    ns = xmlXPathPopNodeSet(ctxt);
109
596
    if (xmlXPathCheckError(ctxt))
110
1
  return;
111
112
    /* !!! must be sorted !!! */
113
595
    ret = xmlXPathDistinctSorted(ns);
114
115
595
    if (ret != ns)
116
276
  xmlXPathFreeNodeSet(ns);
117
118
595
    obj = xmlXPathWrapNodeSet(ret);
119
595
    if (obj != NULL) {
120
576
        obj->user = user;
121
576
        obj->boolval = boolval;
122
576
    }
123
595
    valuePush(ctxt, obj);
124
595
}
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
1.23k
            int nargs) {
136
1.23k
    xmlNodeSetPtr arg1, arg2;
137
1.23k
    int ret;
138
139
1.23k
    if (nargs != 2) {
140
1
  xmlXPathSetArityError(ctxt);
141
1
  return;
142
1
    }
143
144
1.23k
    arg2 = xmlXPathPopNodeSet(ctxt);
145
1.23k
    if (xmlXPathCheckError(ctxt))
146
1
  return;
147
148
1.23k
    arg1 = xmlXPathPopNodeSet(ctxt);
149
1.23k
    if (xmlXPathCheckError(ctxt)) {
150
1
        xmlXPathFreeNodeSet(arg2);
151
1
  return;
152
1
    }
153
154
1.22k
    ret = xmlXPathHasSameNodes(arg1, arg2);
155
156
1.22k
    xmlXPathFreeNodeSet(arg1);
157
1.22k
    xmlXPathFreeNodeSet(arg2);
158
159
1.22k
    xmlXPathReturnBoolean(ctxt, ret);
160
1.22k
}
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
1.18k
exsltSetsLeadingFunction (xmlXPathParserContextPtr ctxt, int nargs) {
171
1.18k
    xmlNodeSetPtr arg1, arg2, ret;
172
173
1.18k
    if (nargs != 2) {
174
1
  xmlXPathSetArityError(ctxt);
175
1
  return;
176
1
    }
177
178
1.18k
    arg2 = xmlXPathPopNodeSet(ctxt);
179
1.18k
    if (xmlXPathCheckError(ctxt))
180
1
  return;
181
182
1.18k
    arg1 = xmlXPathPopNodeSet(ctxt);
183
1.18k
    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
1.18k
    if (xmlXPathNodeSetIsEmpty(arg2)) {
192
160
  xmlXPathReturnNodeSet(ctxt, arg1);
193
194
160
  xmlXPathFreeNodeSet(arg2);
195
196
160
  return;
197
160
    }
198
    /* !!! must be sorted */
199
1.02k
    ret = xmlXPathNodeLeadingSorted(arg1, xmlXPathNodeSetItem(arg2, 0));
200
201
1.02k
    xmlXPathFreeNodeSet(arg1);
202
1.02k
    xmlXPathFreeNodeSet(arg2);
203
204
1.02k
    xmlXPathReturnNodeSet(ctxt, ret);
205
1.02k
}
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
13.9k
exsltSetsTrailingFunction (xmlXPathParserContextPtr ctxt, int nargs) {
216
13.9k
    xmlNodeSetPtr arg1, arg2, ret;
217
218
13.9k
    if (nargs != 2) {
219
474
  xmlXPathSetArityError(ctxt);
220
474
  return;
221
474
    }
222
223
13.5k
    arg2 = xmlXPathPopNodeSet(ctxt);
224
13.5k
    if (xmlXPathCheckError(ctxt))
225
850
  return;
226
227
12.6k
    arg1 = xmlXPathPopNodeSet(ctxt);
228
12.6k
    if (xmlXPathCheckError(ctxt)) {
229
2.03k
  xmlXPathFreeNodeSet(arg2);
230
2.03k
  return;
231
2.03k
    }
232
233
    /*  If the second node set is empty, then the first node set is
234
     * returned.
235
     */
236
10.6k
    if (xmlXPathNodeSetIsEmpty(arg2)) {
237
1.77k
  xmlXPathReturnNodeSet(ctxt, arg1);
238
239
1.77k
  xmlXPathFreeNodeSet(arg2);
240
241
1.77k
  return;
242
1.77k
    }
243
    /* !!! mist be sorted */
244
8.83k
    ret = xmlXPathNodeTrailingSorted(arg1, xmlXPathNodeSetItem(arg2, 0));
245
246
8.83k
    xmlXPathFreeNodeSet(arg1);
247
8.83k
    xmlXPathFreeNodeSet(arg2);
248
249
8.83k
    xmlXPathReturnNodeSet(ctxt, ret);
250
8.83k
}
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
}