1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is TransforMiiX XSLT processor code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * IBM Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 2002
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * IBM Corporation
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #include "txResultRecycler.h"
40 : #include "txExprResult.h"
41 : #include "txNodeSet.h"
42 :
43 2 : txResultRecycler::txResultRecycler()
44 : : mEmptyStringResult(nsnull),
45 : mTrueResult(nsnull),
46 2 : mFalseResult(nsnull)
47 : {
48 2 : }
49 :
50 4 : txResultRecycler::~txResultRecycler()
51 : {
52 2 : txStackIterator stringIter(&mStringResults);
53 4 : while (stringIter.hasNext()) {
54 0 : delete static_cast<StringResult*>(stringIter.next());
55 : }
56 2 : txStackIterator nodesetIter(&mNodeSetResults);
57 6 : while (nodesetIter.hasNext()) {
58 2 : delete static_cast<txNodeSet*>(nodesetIter.next());
59 : }
60 2 : txStackIterator numberIter(&mNumberResults);
61 4 : while (numberIter.hasNext()) {
62 0 : delete static_cast<NumberResult*>(numberIter.next());
63 : }
64 :
65 2 : NS_IF_RELEASE(mEmptyStringResult);
66 2 : NS_IF_RELEASE(mTrueResult);
67 2 : NS_IF_RELEASE(mFalseResult);
68 2 : }
69 :
70 :
71 : nsresult
72 2 : txResultRecycler::init()
73 : {
74 2 : NS_ASSERTION(!mEmptyStringResult && !mTrueResult && !mFalseResult,
75 : "Already inited");
76 2 : mEmptyStringResult = new StringResult(nsnull);
77 2 : NS_ENSURE_TRUE(mEmptyStringResult, NS_ERROR_OUT_OF_MEMORY);
78 :
79 2 : NS_ADDREF(mEmptyStringResult);
80 :
81 2 : mTrueResult = new BooleanResult(true);
82 2 : NS_ENSURE_TRUE(mTrueResult, NS_ERROR_OUT_OF_MEMORY);
83 :
84 2 : NS_ADDREF(mTrueResult);
85 :
86 2 : mFalseResult = new BooleanResult(false);
87 2 : NS_ENSURE_TRUE(mFalseResult, NS_ERROR_OUT_OF_MEMORY);
88 :
89 2 : NS_ADDREF(mFalseResult);
90 :
91 2 : return NS_OK;
92 : }
93 :
94 :
95 : void
96 42 : txResultRecycler::recycle(txAExprResult* aResult)
97 : {
98 42 : NS_ASSERTION(aResult->mRefCnt == 0, "In-use txAExprResult recycled");
99 84 : nsRefPtr<txResultRecycler> kungFuDeathGrip;
100 42 : aResult->mRecycler.swap(kungFuDeathGrip);
101 :
102 42 : nsresult rv = NS_OK;
103 42 : switch (aResult->getResultType()) {
104 : case txAExprResult::STRING:
105 : {
106 0 : rv = mStringResults.push(static_cast<StringResult*>(aResult));
107 0 : if (NS_FAILED(rv)) {
108 0 : delete aResult;
109 : }
110 : return;
111 : }
112 : case txAExprResult::NODESET:
113 : {
114 42 : static_cast<txNodeSet*>(aResult)->clear();
115 42 : rv = mNodeSetResults.push(static_cast<txNodeSet*>(aResult));
116 42 : if (NS_FAILED(rv)) {
117 0 : delete aResult;
118 : }
119 : return;
120 : }
121 : case txAExprResult::NUMBER:
122 : {
123 0 : rv = mNumberResults.push(static_cast<NumberResult*>(aResult));
124 0 : if (NS_FAILED(rv)) {
125 0 : delete aResult;
126 : }
127 : return;
128 : }
129 : default:
130 : {
131 0 : delete aResult;
132 : }
133 : }
134 : }
135 :
136 : nsresult
137 0 : txResultRecycler::getStringResult(StringResult** aResult)
138 : {
139 0 : if (mStringResults.isEmpty()) {
140 0 : *aResult = new StringResult(this);
141 0 : NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
142 : }
143 : else {
144 0 : *aResult = static_cast<StringResult*>(mStringResults.pop());
145 0 : (*aResult)->mValue.Truncate();
146 0 : (*aResult)->mRecycler = this;
147 : }
148 0 : NS_ADDREF(*aResult);
149 :
150 0 : return NS_OK;
151 : }
152 :
153 : nsresult
154 0 : txResultRecycler::getStringResult(const nsAString& aValue,
155 : txAExprResult** aResult)
156 : {
157 0 : if (mStringResults.isEmpty()) {
158 0 : *aResult = new StringResult(aValue, this);
159 0 : NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
160 : }
161 : else {
162 : StringResult* strRes =
163 0 : static_cast<StringResult*>(mStringResults.pop());
164 0 : strRes->mValue = aValue;
165 0 : strRes->mRecycler = this;
166 0 : *aResult = strRes;
167 : }
168 0 : NS_ADDREF(*aResult);
169 :
170 0 : return NS_OK;
171 : }
172 :
173 : void
174 0 : txResultRecycler::getEmptyStringResult(txAExprResult** aResult)
175 : {
176 0 : *aResult = mEmptyStringResult;
177 0 : NS_ADDREF(*aResult);
178 0 : }
179 :
180 : nsresult
181 42 : txResultRecycler::getNodeSet(txNodeSet** aResult)
182 : {
183 42 : if (mNodeSetResults.isEmpty()) {
184 2 : *aResult = new txNodeSet(this);
185 2 : NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
186 : }
187 : else {
188 40 : *aResult = static_cast<txNodeSet*>(mNodeSetResults.pop());
189 40 : (*aResult)->mRecycler = this;
190 : }
191 42 : NS_ADDREF(*aResult);
192 :
193 42 : return NS_OK;
194 : }
195 :
196 : nsresult
197 0 : txResultRecycler::getNodeSet(txNodeSet* aNodeSet, txNodeSet** aResult)
198 : {
199 0 : if (mNodeSetResults.isEmpty()) {
200 0 : *aResult = new txNodeSet(*aNodeSet, this);
201 0 : NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
202 : }
203 : else {
204 0 : *aResult = static_cast<txNodeSet*>(mNodeSetResults.pop());
205 0 : (*aResult)->append(*aNodeSet);
206 0 : (*aResult)->mRecycler = this;
207 : }
208 0 : NS_ADDREF(*aResult);
209 :
210 0 : return NS_OK;
211 : }
212 :
213 : nsresult
214 0 : txResultRecycler::getNodeSet(const txXPathNode& aNode, txAExprResult** aResult)
215 : {
216 0 : if (mNodeSetResults.isEmpty()) {
217 0 : *aResult = new txNodeSet(aNode, this);
218 0 : NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
219 : }
220 : else {
221 0 : txNodeSet* nodes = static_cast<txNodeSet*>(mNodeSetResults.pop());
222 0 : nodes->append(aNode);
223 0 : nodes->mRecycler = this;
224 0 : *aResult = nodes;
225 : }
226 0 : NS_ADDREF(*aResult);
227 :
228 0 : return NS_OK;
229 : }
230 :
231 : nsresult
232 0 : txResultRecycler::getNumberResult(double aValue, txAExprResult** aResult)
233 : {
234 0 : if (mNumberResults.isEmpty()) {
235 0 : *aResult = new NumberResult(aValue, this);
236 0 : NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
237 : }
238 : else {
239 : NumberResult* numRes =
240 0 : static_cast<NumberResult*>(mNumberResults.pop());
241 0 : numRes->value = aValue;
242 0 : numRes->mRecycler = this;
243 0 : *aResult = numRes;
244 : }
245 0 : NS_ADDREF(*aResult);
246 :
247 0 : return NS_OK;
248 : }
249 :
250 : void
251 0 : txResultRecycler::getBoolResult(bool aValue, txAExprResult** aResult)
252 : {
253 0 : *aResult = aValue ? mTrueResult : mFalseResult;
254 0 : NS_ADDREF(*aResult);
255 0 : }
256 :
257 : nsresult
258 0 : txResultRecycler::getNonSharedNodeSet(txNodeSet* aNodeSet, txNodeSet** aResult)
259 : {
260 0 : if (aNodeSet->mRefCnt > 1) {
261 0 : return getNodeSet(aNodeSet, aResult);
262 : }
263 :
264 0 : *aResult = aNodeSet;
265 0 : NS_ADDREF(*aResult);
266 :
267 0 : return NS_OK;
268 : }
269 :
270 : void
271 132 : txAExprResult::Release()
272 : {
273 132 : --mRefCnt;
274 132 : NS_LOG_RELEASE(this, mRefCnt, "txAExprResult");
275 132 : if (mRefCnt == 0) {
276 48 : if (mRecycler) {
277 42 : mRecycler->recycle(this);
278 : }
279 : else {
280 6 : delete this;
281 : }
282 : }
283 132 : }
|