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