Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/xslt/xpath/txResultRecycler.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 "txResultRecycler.h"
7
#include "txExprResult.h"
8
#include "txNodeSet.h"
9
10
txResultRecycler::txResultRecycler()
11
    : mEmptyStringResult(new StringResult(nullptr)),
12
      mTrueResult(new BooleanResult(true)),
13
      mFalseResult(new BooleanResult(false))
14
0
{
15
0
}
16
17
txResultRecycler::~txResultRecycler()
18
0
{
19
0
    txStackIterator stringIter(&mStringResults);
20
0
    while (stringIter.hasNext()) {
21
0
        delete static_cast<StringResult*>(stringIter.next());
22
0
    }
23
0
    txStackIterator nodesetIter(&mNodeSetResults);
24
0
    while (nodesetIter.hasNext()) {
25
0
        delete static_cast<txNodeSet*>(nodesetIter.next());
26
0
    }
27
0
    txStackIterator numberIter(&mNumberResults);
28
0
    while (numberIter.hasNext()) {
29
0
        delete static_cast<NumberResult*>(numberIter.next());
30
0
    }
31
0
}
32
33
34
void
35
txResultRecycler::recycle(txAExprResult* aResult)
36
0
{
37
0
    NS_ASSERTION(aResult->mRefCnt == 0, "In-use txAExprResult recycled");
38
0
    RefPtr<txResultRecycler> kungFuDeathGrip;
39
0
    aResult->mRecycler.swap(kungFuDeathGrip);
40
0
41
0
    nsresult rv = NS_OK;
42
0
    switch (aResult->getResultType()) {
43
0
        case txAExprResult::STRING:
44
0
        {
45
0
            rv = mStringResults.push(static_cast<StringResult*>(aResult));
46
0
            if (NS_FAILED(rv)) {
47
0
                delete aResult;
48
0
            }
49
0
            return;
50
0
        }
51
0
        case txAExprResult::NODESET:
52
0
        {
53
0
            static_cast<txNodeSet*>(aResult)->clear();
54
0
            rv = mNodeSetResults.push(static_cast<txNodeSet*>(aResult));
55
0
            if (NS_FAILED(rv)) {
56
0
                delete aResult;
57
0
            }
58
0
            return;
59
0
        }
60
0
        case txAExprResult::NUMBER:
61
0
        {
62
0
            rv = mNumberResults.push(static_cast<NumberResult*>(aResult));
63
0
            if (NS_FAILED(rv)) {
64
0
                delete aResult;
65
0
            }
66
0
            return;
67
0
        }
68
0
        default:
69
0
        {
70
0
            delete aResult;
71
0
        }
72
0
    }
73
0
}
74
75
nsresult
76
txResultRecycler::getStringResult(StringResult** aResult)
77
0
{
78
0
    if (mStringResults.isEmpty()) {
79
0
        *aResult = new StringResult(this);
80
0
    }
81
0
    else {
82
0
        *aResult = static_cast<StringResult*>(mStringResults.pop());
83
0
        (*aResult)->mValue.Truncate();
84
0
        (*aResult)->mRecycler = this;
85
0
    }
86
0
    NS_ADDREF(*aResult);
87
0
88
0
    return NS_OK;
89
0
}
90
91
nsresult
92
txResultRecycler::getStringResult(const nsAString& aValue,
93
                                  txAExprResult** aResult)
94
0
{
95
0
    if (mStringResults.isEmpty()) {
96
0
        *aResult = new StringResult(aValue, this);
97
0
    }
98
0
    else {
99
0
        StringResult* strRes =
100
0
            static_cast<StringResult*>(mStringResults.pop());
101
0
        strRes->mValue = aValue;
102
0
        strRes->mRecycler = this;
103
0
        *aResult = strRes;
104
0
    }
105
0
    NS_ADDREF(*aResult);
106
0
107
0
    return NS_OK;
108
0
}
109
110
void
111
txResultRecycler::getEmptyStringResult(txAExprResult** aResult)
112
0
{
113
0
    *aResult = mEmptyStringResult;
114
0
    NS_ADDREF(*aResult);
115
0
}
116
117
nsresult
118
txResultRecycler::getNodeSet(txNodeSet** aResult)
119
0
{
120
0
    if (mNodeSetResults.isEmpty()) {
121
0
        *aResult = new txNodeSet(this);
122
0
    }
123
0
    else {
124
0
        *aResult = static_cast<txNodeSet*>(mNodeSetResults.pop());
125
0
        (*aResult)->mRecycler = this;
126
0
    }
127
0
    NS_ADDREF(*aResult);
128
0
129
0
    return NS_OK;
130
0
}
131
132
nsresult
133
txResultRecycler::getNodeSet(txNodeSet* aNodeSet, txNodeSet** aResult)
134
0
{
135
0
    if (mNodeSetResults.isEmpty()) {
136
0
        *aResult = new txNodeSet(*aNodeSet, this);
137
0
    }
138
0
    else {
139
0
        *aResult = static_cast<txNodeSet*>(mNodeSetResults.pop());
140
0
        (*aResult)->append(*aNodeSet);
141
0
        (*aResult)->mRecycler = this;
142
0
    }
143
0
    NS_ADDREF(*aResult);
144
0
145
0
    return NS_OK;
146
0
}
147
148
nsresult
149
txResultRecycler::getNodeSet(const txXPathNode& aNode, txAExprResult** aResult)
150
0
{
151
0
    if (mNodeSetResults.isEmpty()) {
152
0
        *aResult = new txNodeSet(aNode, this);
153
0
    }
154
0
    else {
155
0
        txNodeSet* nodes = static_cast<txNodeSet*>(mNodeSetResults.pop());
156
0
        nodes->append(aNode);
157
0
        nodes->mRecycler = this;
158
0
        *aResult = nodes;
159
0
    }
160
0
    NS_ADDREF(*aResult);
161
0
162
0
    return NS_OK;
163
0
}
164
165
nsresult
166
txResultRecycler::getNumberResult(double aValue, txAExprResult** aResult)
167
0
{
168
0
    if (mNumberResults.isEmpty()) {
169
0
        *aResult = new NumberResult(aValue, this);
170
0
    }
171
0
    else {
172
0
        NumberResult* numRes =
173
0
            static_cast<NumberResult*>(mNumberResults.pop());
174
0
        numRes->value = aValue;
175
0
        numRes->mRecycler = this;
176
0
        *aResult = numRes;
177
0
    }
178
0
    NS_ADDREF(*aResult);
179
0
180
0
    return NS_OK;
181
0
}
182
183
void
184
txResultRecycler::getBoolResult(bool aValue, txAExprResult** aResult)
185
0
{
186
0
    *aResult = aValue ? mTrueResult : mFalseResult;
187
0
    NS_ADDREF(*aResult);
188
0
}
189
190
nsresult
191
txResultRecycler::getNonSharedNodeSet(txNodeSet* aNodeSet, txNodeSet** aResult)
192
0
{
193
0
    if (aNodeSet->mRefCnt > 1) {
194
0
        return getNodeSet(aNodeSet, aResult);
195
0
    }
196
0
197
0
    *aResult = aNodeSet;
198
0
    NS_ADDREF(*aResult);
199
0
200
0
    return NS_OK;
201
0
}
202
203
void
204
txAExprResult::Release()
205
0
{
206
0
    --mRefCnt;
207
0
    NS_LOG_RELEASE(this, mRefCnt, "txAExprResult");
208
0
    if (mRefCnt == 0) {
209
0
        if (mRecycler) {
210
0
            mRecycler->recycle(this);
211
0
        }
212
0
        else {
213
0
            delete this;
214
0
        }
215
0
    }
216
0
}