root/third_party/libxslt/libexslt/sets.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. exsltSetsDifferenceFunction
  2. exsltSetsIntersectionFunction
  3. exsltSetsDistinctFunction
  4. exsltSetsHasSameNodesFunction
  5. exsltSetsLeadingFunction
  6. exsltSetsTrailingFunction
  7. exsltSetsRegister
  8. exsltSetsXpathCtxtRegister

#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;
}

/* [<][>][^][v][top][bottom][index][help] */