Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/xslt/xpath/txRelationalExpr.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/* This Source Code Form is subject to the terms of the Mozilla Public
3
 * License, v. 2.0. If a copy of the MPL was not distributed with this
4
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6
#include "txExpr.h"
7
#include "txNodeSet.h"
8
#include "txIXPathContext.h"
9
#include "txXPathTreeWalker.h"
10
11
/**
12
 *  Compares the two ExprResults based on XPath 1.0 Recommendation (section 3.4)
13
 */
14
bool
15
RelationalExpr::compareResults(txIEvalContext* aContext, txAExprResult* aLeft,
16
                               txAExprResult* aRight)
17
0
{
18
0
    short ltype = aLeft->getResultType();
19
0
    short rtype = aRight->getResultType();
20
0
    nsresult rv = NS_OK;
21
0
22
0
    // Handle case for just Left NodeSet or Both NodeSets
23
0
    if (ltype == txAExprResult::NODESET) {
24
0
        if (rtype == txAExprResult::BOOLEAN) {
25
0
            BooleanResult leftBool(aLeft->booleanValue());
26
0
            return compareResults(aContext, &leftBool, aRight);
27
0
        }
28
0
29
0
        txNodeSet* nodeSet = static_cast<txNodeSet*>(aLeft);
30
0
        RefPtr<StringResult> strResult;
31
0
        rv = aContext->recycler()->getStringResult(getter_AddRefs(strResult));
32
0
        NS_ENSURE_SUCCESS(rv, false);
33
0
34
0
        int32_t i;
35
0
        for (i = 0; i < nodeSet->size(); ++i) {
36
0
            strResult->mValue.Truncate();
37
0
            txXPathNodeUtils::appendNodeValue(nodeSet->get(i),
38
0
                                              strResult->mValue);
39
0
            if (compareResults(aContext, strResult, aRight)) {
40
0
                return true;
41
0
            }
42
0
        }
43
0
44
0
        return false;
45
0
    }
46
0
47
0
    // Handle case for Just Right NodeSet
48
0
    if (rtype == txAExprResult::NODESET) {
49
0
        if (ltype == txAExprResult::BOOLEAN) {
50
0
            BooleanResult rightBool(aRight->booleanValue());
51
0
            return compareResults(aContext, aLeft, &rightBool);
52
0
        }
53
0
54
0
        txNodeSet* nodeSet = static_cast<txNodeSet*>(aRight);
55
0
        RefPtr<StringResult> strResult;
56
0
        rv = aContext->recycler()->getStringResult(getter_AddRefs(strResult));
57
0
        NS_ENSURE_SUCCESS(rv, false);
58
0
59
0
        int32_t i;
60
0
        for (i = 0; i < nodeSet->size(); ++i) {
61
0
            strResult->mValue.Truncate();
62
0
            txXPathNodeUtils::appendNodeValue(nodeSet->get(i),
63
0
                                              strResult->mValue);
64
0
            if (compareResults(aContext, aLeft, strResult)) {
65
0
                return true;
66
0
            }
67
0
        }
68
0
69
0
        return false;
70
0
    }
71
0
72
0
    // Neither is a NodeSet
73
0
    if (mOp == EQUAL || mOp == NOT_EQUAL) {
74
0
        bool result;
75
0
        const nsString *lString, *rString;
76
0
77
0
        // If either is a bool, compare as bools.
78
0
        if (ltype == txAExprResult::BOOLEAN ||
79
0
            rtype == txAExprResult::BOOLEAN) {
80
0
            result = aLeft->booleanValue() == aRight->booleanValue();
81
0
        }
82
0
83
0
        // If either is a number, compare as numbers.
84
0
        else if (ltype == txAExprResult::NUMBER ||
85
0
                 rtype == txAExprResult::NUMBER) {
86
0
            double lval = aLeft->numberValue();
87
0
            double rval = aRight->numberValue();
88
0
            result = (lval == rval);
89
0
        }
90
0
91
0
        // Otherwise compare as strings. Try to use the stringobject in
92
0
        // StringResult if possible since that is a common case.
93
0
        else if ((lString = aLeft->stringValuePointer())) {
94
0
            if ((rString = aRight->stringValuePointer())) {
95
0
                result = lString->Equals(*rString);
96
0
            }
97
0
            else {
98
0
                nsAutoString rStr;
99
0
                aRight->stringValue(rStr);
100
0
                result = lString->Equals(rStr);
101
0
            }
102
0
        }
103
0
        else if ((rString = aRight->stringValuePointer())) {
104
0
            nsAutoString lStr;
105
0
            aLeft->stringValue(lStr);
106
0
            result = rString->Equals(lStr);
107
0
        }
108
0
        else {
109
0
            nsAutoString lStr, rStr;
110
0
            aLeft->stringValue(lStr);
111
0
            aRight->stringValue(rStr);
112
0
            result = lStr.Equals(rStr);
113
0
        }
114
0
115
0
        return mOp == EQUAL ? result : !result;
116
0
    }
117
0
118
0
    double leftDbl = aLeft->numberValue();
119
0
    double rightDbl = aRight->numberValue();
120
0
    switch (mOp) {
121
0
        case LESS_THAN:
122
0
        {
123
0
            return (leftDbl < rightDbl);
124
0
        }
125
0
        case LESS_OR_EQUAL:
126
0
        {
127
0
            return (leftDbl <= rightDbl);
128
0
        }
129
0
        case GREATER_THAN:
130
0
        {
131
0
            return (leftDbl > rightDbl);
132
0
        }
133
0
        case GREATER_OR_EQUAL:
134
0
        {
135
0
            return (leftDbl >= rightDbl);
136
0
        }
137
0
        default:
138
0
        {
139
0
            MOZ_ASSERT_UNREACHABLE("We should have caught all cases");
140
0
        }
141
0
    }
142
0
143
0
    return false;
144
0
}
145
146
nsresult
147
RelationalExpr::evaluate(txIEvalContext* aContext, txAExprResult** aResult)
148
0
{
149
0
    *aResult = nullptr;
150
0
    RefPtr<txAExprResult> lResult;
151
0
    nsresult rv = mLeftExpr->evaluate(aContext, getter_AddRefs(lResult));
152
0
    NS_ENSURE_SUCCESS(rv, rv);
153
0
154
0
    RefPtr<txAExprResult> rResult;
155
0
    rv = mRightExpr->evaluate(aContext, getter_AddRefs(rResult));
156
0
    NS_ENSURE_SUCCESS(rv, rv);
157
0
158
0
    aContext->recycler()->
159
0
        getBoolResult(compareResults(aContext, lResult, rResult), aResult);
160
0
161
0
    return NS_OK;
162
0
}
163
164
TX_IMPL_EXPR_STUBS_2(RelationalExpr, BOOLEAN_RESULT, mLeftExpr, mRightExpr)
165
166
bool
167
RelationalExpr::isSensitiveTo(ContextSensitivity aContext)
168
0
{
169
0
    return mLeftExpr->isSensitiveTo(aContext) ||
170
0
           mRightExpr->isSensitiveTo(aContext);
171
0
}
172
173
#ifdef TX_TO_STRING
174
void
175
RelationalExpr::toString(nsAString& str)
176
{
177
    mLeftExpr->toString(str);
178
179
    switch (mOp) {
180
        case NOT_EQUAL:
181
            str.AppendLiteral("!=");
182
            break;
183
        case LESS_THAN:
184
            str.Append(char16_t('<'));
185
            break;
186
        case LESS_OR_EQUAL:
187
            str.AppendLiteral("<=");
188
            break;
189
        case GREATER_THAN :
190
            str.Append(char16_t('>'));
191
            break;
192
        case GREATER_OR_EQUAL:
193
            str.AppendLiteral(">=");
194
            break;
195
        default:
196
            str.Append(char16_t('='));
197
            break;
198
    }
199
200
    mRightExpr->toString(str);
201
}
202
#endif