summaryrefslogtreecommitdiffstats
path: root/libxslt/libexslt/sets.c
diff options
context:
space:
mode:
Diffstat (limited to 'libxslt/libexslt/sets.c')
-rw-r--r--libxslt/libexslt/sets.c334
1 files changed, 334 insertions, 0 deletions
diff --git a/libxslt/libexslt/sets.c b/libxslt/libexslt/sets.c
new file mode 100644
index 0000000..a5a7913
--- /dev/null
+++ b/libxslt/libexslt/sets.c
@@ -0,0 +1,334 @@
+#define IN_LIBEXSLT
+#include "libexslt/libexslt.h"
+
+#if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
+#include <win32config.h>
+#else
+#include "config.h"
+#endif
+
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+#include <libxml/xpathInternals.h>
+
+#include <libxslt/xsltutils.h>
+#include <libxslt/xsltInternals.h>
+#include <libxslt/extensions.h>
+
+#include "exslt.h"
+
+/**
+ * exsltSetsDifferenceFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * Wraps #xmlXPathDifference for use by the XPath processor
+ */
+static void
+exsltSetsDifferenceFunction (xmlXPathParserContextPtr ctxt, int nargs) {
+ xmlNodeSetPtr arg1, arg2, ret;
+
+ if (nargs != 2) {
+ xmlXPathSetArityError(ctxt);
+ return;
+ }
+
+ arg2 = xmlXPathPopNodeSet(ctxt);
+ if (xmlXPathCheckError(ctxt)) {
+ xmlXPathSetTypeError(ctxt);
+ return;
+ }
+
+ arg1 = xmlXPathPopNodeSet(ctxt);
+ if (xmlXPathCheckError(ctxt)) {
+ xmlXPathSetTypeError(ctxt);
+ return;
+ }
+
+ ret = xmlXPathDifference(arg1, arg2);
+
+ if (ret != arg1)
+ xmlXPathFreeNodeSet(arg1);
+ xmlXPathFreeNodeSet(arg2);
+
+ xmlXPathReturnNodeSet(ctxt, ret);
+}
+
+/**
+ * exsltSetsIntersectionFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * Wraps #xmlXPathIntersection for use by the XPath processor
+ */
+static void
+exsltSetsIntersectionFunction (xmlXPathParserContextPtr ctxt, int nargs) {
+ xmlNodeSetPtr arg1, arg2, ret;
+
+ if (nargs != 2) {
+ xmlXPathSetArityError(ctxt);
+ return;
+ }
+
+ arg2 = xmlXPathPopNodeSet(ctxt);
+ if (xmlXPathCheckError(ctxt)) {
+ xmlXPathSetTypeError(ctxt);
+ return;
+ }
+
+ arg1 = xmlXPathPopNodeSet(ctxt);
+ if (xmlXPathCheckError(ctxt)) {
+ xmlXPathSetTypeError(ctxt);
+ return;
+ }
+
+ ret = xmlXPathIntersection(arg1, arg2);
+
+ xmlXPathFreeNodeSet(arg1);
+ xmlXPathFreeNodeSet(arg2);
+
+ xmlXPathReturnNodeSet(ctxt, ret);
+}
+
+/**
+ * exsltSetsDistinctFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * Wraps #xmlXPathDistinct for use by the XPath processor
+ */
+static void
+exsltSetsDistinctFunction (xmlXPathParserContextPtr ctxt, int nargs) {
+ xmlXPathObjectPtr obj;
+ xmlNodeSetPtr ns, ret;
+ int boolval = 0;
+ void *user = NULL;
+
+ if (nargs != 1) {
+ xmlXPathSetArityError(ctxt);
+ return;
+ }
+
+ if (ctxt->value != NULL) {
+ boolval = ctxt->value->boolval;
+ user = ctxt->value->user;
+ ctxt->value->boolval = 0;
+ ctxt->value->user = NULL;
+ }
+ ns = xmlXPathPopNodeSet(ctxt);
+ if (xmlXPathCheckError(ctxt))
+ return;
+
+ /* !!! must be sorted !!! */
+ ret = xmlXPathDistinctSorted(ns);
+
+ if (ret != ns)
+ xmlXPathFreeNodeSet(ns);
+
+ obj = xmlXPathWrapNodeSet(ret);
+ obj->user = user;
+ obj->boolval = boolval;
+ valuePush((ctxt), obj);
+}
+
+/**
+ * exsltSetsHasSameNodesFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * Wraps #xmlXPathHasSameNodes for use by the XPath processor
+ */
+static void
+exsltSetsHasSameNodesFunction (xmlXPathParserContextPtr ctxt,
+ int nargs) {
+ xmlNodeSetPtr arg1, arg2;
+ int ret;
+
+ if (nargs != 2) {
+ xmlXPathSetArityError(ctxt);
+ return;
+ }
+
+ arg2 = xmlXPathPopNodeSet(ctxt);
+ if (xmlXPathCheckError(ctxt)) {
+ xmlXPathSetTypeError(ctxt);
+ return;
+ }
+
+ arg1 = xmlXPathPopNodeSet(ctxt);
+ if (xmlXPathCheckError(ctxt)) {
+ xmlXPathSetTypeError(ctxt);
+ return;
+ }
+
+ ret = xmlXPathHasSameNodes(arg1, arg2);
+
+ xmlXPathFreeNodeSet(arg1);
+ xmlXPathFreeNodeSet(arg2);
+
+ xmlXPathReturnBoolean(ctxt, ret);
+}
+
+/**
+ * exsltSetsLeadingFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * Wraps #xmlXPathLeading for use by the XPath processor
+ */
+static void
+exsltSetsLeadingFunction (xmlXPathParserContextPtr ctxt, int nargs) {
+ xmlNodeSetPtr arg1, arg2, ret;
+
+ if (nargs != 2) {
+ xmlXPathSetArityError(ctxt);
+ return;
+ }
+
+ arg2 = xmlXPathPopNodeSet(ctxt);
+ if (xmlXPathCheckError(ctxt)) {
+ xmlXPathSetTypeError(ctxt);
+ return;
+ }
+
+ arg1 = xmlXPathPopNodeSet(ctxt);
+ if (xmlXPathCheckError(ctxt)) {
+ xmlXPathSetTypeError(ctxt);
+ return;
+ }
+
+ /* If the second node set is empty, then the first node set is
+ * returned.
+ */
+ if (xmlXPathNodeSetIsEmpty(arg2)) {
+ xmlXPathReturnNodeSet(ctxt, arg1);
+
+ xmlXPathFreeNodeSet(arg2);
+
+ return;
+ }
+ /* !!! must be sorted */
+ ret = xmlXPathNodeLeadingSorted(arg1, xmlXPathNodeSetItem(arg2, 0));
+
+ xmlXPathFreeNodeSet(arg1);
+ xmlXPathFreeNodeSet(arg2);
+
+ xmlXPathReturnNodeSet(ctxt, ret);
+}
+
+/**
+ * exsltSetsTrailingFunction:
+ * @ctxt: an XPath parser context
+ * @nargs: the number of arguments
+ *
+ * Wraps #xmlXPathTrailing for use by the XPath processor
+ */
+static void
+exsltSetsTrailingFunction (xmlXPathParserContextPtr ctxt, int nargs) {
+ xmlNodeSetPtr arg1, arg2, ret;
+
+ if (nargs != 2) {
+ xmlXPathSetArityError(ctxt);
+ return;
+ }
+
+ arg2 = xmlXPathPopNodeSet(ctxt);
+ if (xmlXPathCheckError(ctxt)) {
+ xmlXPathSetTypeError(ctxt);
+ return;
+ }
+
+ arg1 = xmlXPathPopNodeSet(ctxt);
+ if (xmlXPathCheckError(ctxt)) {
+ xmlXPathSetTypeError(ctxt);
+ return;
+ }
+
+ /* If the second node set is empty, then the first node set is
+ * returned.
+ */
+ if (xmlXPathNodeSetIsEmpty(arg2)) {
+ xmlXPathReturnNodeSet(ctxt, arg1);
+
+ xmlXPathFreeNodeSet(arg2);
+
+ return;
+ }
+ /* !!! mist be sorted */
+ ret = xmlXPathNodeTrailingSorted(arg1, xmlXPathNodeSetItem(arg2, 0));
+
+ xmlXPathFreeNodeSet(arg1);
+ xmlXPathFreeNodeSet(arg2);
+
+ xmlXPathReturnNodeSet(ctxt, ret);
+}
+
+/**
+ * exsltSetsRegister:
+ *
+ * Registers the EXSLT - Sets module
+ */
+
+void
+exsltSetsRegister (void) {
+ xsltRegisterExtModuleFunction ((const xmlChar *) "difference",
+ EXSLT_SETS_NAMESPACE,
+ exsltSetsDifferenceFunction);
+ xsltRegisterExtModuleFunction ((const xmlChar *) "intersection",
+ EXSLT_SETS_NAMESPACE,
+ exsltSetsIntersectionFunction);
+ xsltRegisterExtModuleFunction ((const xmlChar *) "distinct",
+ EXSLT_SETS_NAMESPACE,
+ exsltSetsDistinctFunction);
+ xsltRegisterExtModuleFunction ((const xmlChar *) "has-same-node",
+ EXSLT_SETS_NAMESPACE,
+ exsltSetsHasSameNodesFunction);
+ xsltRegisterExtModuleFunction ((const xmlChar *) "leading",
+ EXSLT_SETS_NAMESPACE,
+ exsltSetsLeadingFunction);
+ xsltRegisterExtModuleFunction ((const xmlChar *) "trailing",
+ EXSLT_SETS_NAMESPACE,
+ exsltSetsTrailingFunction);
+}
+
+/**
+ * exsltSetsXpathCtxtRegister:
+ *
+ * Registers the EXSLT - Sets module for use outside XSLT
+ */
+int
+exsltSetsXpathCtxtRegister (xmlXPathContextPtr ctxt, const xmlChar *prefix)
+{
+ if (ctxt
+ && prefix
+ && !xmlXPathRegisterNs(ctxt,
+ prefix,
+ (const xmlChar *) EXSLT_SETS_NAMESPACE)
+ && !xmlXPathRegisterFuncNS(ctxt,
+ (const xmlChar *) "difference",
+ (const xmlChar *) EXSLT_SETS_NAMESPACE,
+ exsltSetsDifferenceFunction)
+ && !xmlXPathRegisterFuncNS(ctxt,
+ (const xmlChar *) "intersection",
+ (const xmlChar *) EXSLT_SETS_NAMESPACE,
+ exsltSetsIntersectionFunction)
+ && !xmlXPathRegisterFuncNS(ctxt,
+ (const xmlChar *) "distinct",
+ (const xmlChar *) EXSLT_SETS_NAMESPACE,
+ exsltSetsDistinctFunction)
+ && !xmlXPathRegisterFuncNS(ctxt,
+ (const xmlChar *) "has-same-node",
+ (const xmlChar *) EXSLT_SETS_NAMESPACE,
+ exsltSetsHasSameNodesFunction)
+ && !xmlXPathRegisterFuncNS(ctxt,
+ (const xmlChar *) "leading",
+ (const xmlChar *) EXSLT_SETS_NAMESPACE,
+ exsltSetsLeadingFunction)
+ && !xmlXPathRegisterFuncNS(ctxt,
+ (const xmlChar *) "trailing",
+ (const xmlChar *) EXSLT_SETS_NAMESPACE,
+ exsltSetsTrailingFunction)) {
+ return 0;
+ }
+ return -1;
+}