Coverage Report

Created: 2026-01-09 07:04

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