1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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/. */
6 #include "txResultRecycler.h"
7 #include "txExprResult.h"
10 txResultRecycler::txResultRecycler()
11 : mEmptyStringResult(new StringResult(nullptr)),
12 mTrueResult(new BooleanResult(true)),
13 mFalseResult(new BooleanResult(false)) {}
15 txResultRecycler::~txResultRecycler() {
16 txStackIterator
stringIter(&mStringResults
);
17 while (stringIter
.hasNext()) {
18 delete static_cast<StringResult
*>(stringIter
.next());
20 txStackIterator
nodesetIter(&mNodeSetResults
);
21 while (nodesetIter
.hasNext()) {
22 delete static_cast<txNodeSet
*>(nodesetIter
.next());
24 txStackIterator
numberIter(&mNumberResults
);
25 while (numberIter
.hasNext()) {
26 delete static_cast<NumberResult
*>(numberIter
.next());
30 void txResultRecycler::recycle(txAExprResult
* aResult
) {
31 NS_ASSERTION(aResult
->mRefCnt
== 0, "In-use txAExprResult recycled");
32 RefPtr
<txResultRecycler
> kungFuDeathGrip
;
33 aResult
->mRecycler
.swap(kungFuDeathGrip
);
35 switch (aResult
->getResultType()) {
36 case txAExprResult::STRING
: {
37 mStringResults
.push(static_cast<StringResult
*>(aResult
));
40 case txAExprResult::NODESET
: {
41 static_cast<txNodeSet
*>(aResult
)->clear();
42 mNodeSetResults
.push(static_cast<txNodeSet
*>(aResult
));
45 case txAExprResult::NUMBER
: {
46 mNumberResults
.push(static_cast<NumberResult
*>(aResult
));
55 nsresult
txResultRecycler::getStringResult(StringResult
** aResult
) {
56 if (mStringResults
.isEmpty()) {
57 *aResult
= new StringResult(this);
59 *aResult
= static_cast<StringResult
*>(mStringResults
.pop());
60 (*aResult
)->mValue
.Truncate();
61 (*aResult
)->mRecycler
= this;
68 nsresult
txResultRecycler::getStringResult(const nsAString
& aValue
,
69 txAExprResult
** aResult
) {
70 if (mStringResults
.isEmpty()) {
71 *aResult
= new StringResult(aValue
, this);
73 StringResult
* strRes
= static_cast<StringResult
*>(mStringResults
.pop());
74 strRes
->mValue
= aValue
;
75 strRes
->mRecycler
= this;
83 void txResultRecycler::getEmptyStringResult(txAExprResult
** aResult
) {
84 *aResult
= mEmptyStringResult
;
88 nsresult
txResultRecycler::getNodeSet(txNodeSet
** aResult
) {
89 if (mNodeSetResults
.isEmpty()) {
90 *aResult
= new txNodeSet(this);
92 *aResult
= static_cast<txNodeSet
*>(mNodeSetResults
.pop());
93 (*aResult
)->mRecycler
= this;
100 nsresult
txResultRecycler::getNodeSet(txNodeSet
* aNodeSet
,
101 txNodeSet
** aResult
) {
102 if (mNodeSetResults
.isEmpty()) {
103 *aResult
= new txNodeSet(*aNodeSet
, this);
105 *aResult
= static_cast<txNodeSet
*>(mNodeSetResults
.pop());
106 (*aResult
)->append(*aNodeSet
);
107 (*aResult
)->mRecycler
= this;
114 nsresult
txResultRecycler::getNodeSet(const txXPathNode
& aNode
,
115 txAExprResult
** aResult
) {
116 if (mNodeSetResults
.isEmpty()) {
117 *aResult
= new txNodeSet(aNode
, this);
119 txNodeSet
* nodes
= static_cast<txNodeSet
*>(mNodeSetResults
.pop());
120 nodes
->append(aNode
);
121 nodes
->mRecycler
= this;
129 nsresult
txResultRecycler::getNumberResult(double aValue
,
130 txAExprResult
** aResult
) {
131 if (mNumberResults
.isEmpty()) {
132 *aResult
= new NumberResult(aValue
, this);
134 NumberResult
* numRes
= static_cast<NumberResult
*>(mNumberResults
.pop());
135 numRes
->value
= aValue
;
136 numRes
->mRecycler
= this;
144 void txResultRecycler::getBoolResult(bool aValue
, txAExprResult
** aResult
) {
145 *aResult
= aValue
? mTrueResult
: mFalseResult
;
149 nsresult
txResultRecycler::getNonSharedNodeSet(txNodeSet
* aNodeSet
,
150 txNodeSet
** aResult
) {
151 if (aNodeSet
->mRefCnt
> 1) {
152 return getNodeSet(aNodeSet
, aResult
);
161 void txAExprResult::Release() {
163 NS_LOG_RELEASE(this, mRefCnt
, "txAExprResult");
166 mRecycler
->recycle(this);