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