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