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