1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/xslt/xpath/txResultRecycler.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,250 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "txResultRecycler.h" 1.10 +#include "txExprResult.h" 1.11 +#include "txNodeSet.h" 1.12 + 1.13 +txResultRecycler::txResultRecycler() 1.14 + : mEmptyStringResult(nullptr), 1.15 + mTrueResult(nullptr), 1.16 + mFalseResult(nullptr) 1.17 +{ 1.18 +} 1.19 + 1.20 +txResultRecycler::~txResultRecycler() 1.21 +{ 1.22 + txStackIterator stringIter(&mStringResults); 1.23 + while (stringIter.hasNext()) { 1.24 + delete static_cast<StringResult*>(stringIter.next()); 1.25 + } 1.26 + txStackIterator nodesetIter(&mNodeSetResults); 1.27 + while (nodesetIter.hasNext()) { 1.28 + delete static_cast<txNodeSet*>(nodesetIter.next()); 1.29 + } 1.30 + txStackIterator numberIter(&mNumberResults); 1.31 + while (numberIter.hasNext()) { 1.32 + delete static_cast<NumberResult*>(numberIter.next()); 1.33 + } 1.34 + 1.35 + NS_IF_RELEASE(mEmptyStringResult); 1.36 + NS_IF_RELEASE(mTrueResult); 1.37 + NS_IF_RELEASE(mFalseResult); 1.38 +} 1.39 + 1.40 + 1.41 +nsresult 1.42 +txResultRecycler::init() 1.43 +{ 1.44 + NS_ASSERTION(!mEmptyStringResult && !mTrueResult && !mFalseResult, 1.45 + "Already inited"); 1.46 + mEmptyStringResult = new StringResult(nullptr); 1.47 + NS_ENSURE_TRUE(mEmptyStringResult, NS_ERROR_OUT_OF_MEMORY); 1.48 + 1.49 + NS_ADDREF(mEmptyStringResult); 1.50 + 1.51 + mTrueResult = new BooleanResult(true); 1.52 + NS_ENSURE_TRUE(mTrueResult, NS_ERROR_OUT_OF_MEMORY); 1.53 + 1.54 + NS_ADDREF(mTrueResult); 1.55 + 1.56 + mFalseResult = new BooleanResult(false); 1.57 + NS_ENSURE_TRUE(mFalseResult, NS_ERROR_OUT_OF_MEMORY); 1.58 + 1.59 + NS_ADDREF(mFalseResult); 1.60 + 1.61 + return NS_OK; 1.62 +} 1.63 + 1.64 + 1.65 +void 1.66 +txResultRecycler::recycle(txAExprResult* aResult) 1.67 +{ 1.68 + NS_ASSERTION(aResult->mRefCnt == 0, "In-use txAExprResult recycled"); 1.69 + nsRefPtr<txResultRecycler> kungFuDeathGrip; 1.70 + aResult->mRecycler.swap(kungFuDeathGrip); 1.71 + 1.72 + nsresult rv = NS_OK; 1.73 + switch (aResult->getResultType()) { 1.74 + case txAExprResult::STRING: 1.75 + { 1.76 + rv = mStringResults.push(static_cast<StringResult*>(aResult)); 1.77 + if (NS_FAILED(rv)) { 1.78 + delete aResult; 1.79 + } 1.80 + return; 1.81 + } 1.82 + case txAExprResult::NODESET: 1.83 + { 1.84 + static_cast<txNodeSet*>(aResult)->clear(); 1.85 + rv = mNodeSetResults.push(static_cast<txNodeSet*>(aResult)); 1.86 + if (NS_FAILED(rv)) { 1.87 + delete aResult; 1.88 + } 1.89 + return; 1.90 + } 1.91 + case txAExprResult::NUMBER: 1.92 + { 1.93 + rv = mNumberResults.push(static_cast<NumberResult*>(aResult)); 1.94 + if (NS_FAILED(rv)) { 1.95 + delete aResult; 1.96 + } 1.97 + return; 1.98 + } 1.99 + default: 1.100 + { 1.101 + delete aResult; 1.102 + } 1.103 + } 1.104 +} 1.105 + 1.106 +nsresult 1.107 +txResultRecycler::getStringResult(StringResult** aResult) 1.108 +{ 1.109 + if (mStringResults.isEmpty()) { 1.110 + *aResult = new StringResult(this); 1.111 + NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY); 1.112 + } 1.113 + else { 1.114 + *aResult = static_cast<StringResult*>(mStringResults.pop()); 1.115 + (*aResult)->mValue.Truncate(); 1.116 + (*aResult)->mRecycler = this; 1.117 + } 1.118 + NS_ADDREF(*aResult); 1.119 + 1.120 + return NS_OK; 1.121 +} 1.122 + 1.123 +nsresult 1.124 +txResultRecycler::getStringResult(const nsAString& aValue, 1.125 + txAExprResult** aResult) 1.126 +{ 1.127 + if (mStringResults.isEmpty()) { 1.128 + *aResult = new StringResult(aValue, this); 1.129 + NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY); 1.130 + } 1.131 + else { 1.132 + StringResult* strRes = 1.133 + static_cast<StringResult*>(mStringResults.pop()); 1.134 + strRes->mValue = aValue; 1.135 + strRes->mRecycler = this; 1.136 + *aResult = strRes; 1.137 + } 1.138 + NS_ADDREF(*aResult); 1.139 + 1.140 + return NS_OK; 1.141 +} 1.142 + 1.143 +void 1.144 +txResultRecycler::getEmptyStringResult(txAExprResult** aResult) 1.145 +{ 1.146 + *aResult = mEmptyStringResult; 1.147 + NS_ADDREF(*aResult); 1.148 +} 1.149 + 1.150 +nsresult 1.151 +txResultRecycler::getNodeSet(txNodeSet** aResult) 1.152 +{ 1.153 + if (mNodeSetResults.isEmpty()) { 1.154 + *aResult = new txNodeSet(this); 1.155 + NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY); 1.156 + } 1.157 + else { 1.158 + *aResult = static_cast<txNodeSet*>(mNodeSetResults.pop()); 1.159 + (*aResult)->mRecycler = this; 1.160 + } 1.161 + NS_ADDREF(*aResult); 1.162 + 1.163 + return NS_OK; 1.164 +} 1.165 + 1.166 +nsresult 1.167 +txResultRecycler::getNodeSet(txNodeSet* aNodeSet, txNodeSet** aResult) 1.168 +{ 1.169 + if (mNodeSetResults.isEmpty()) { 1.170 + *aResult = new txNodeSet(*aNodeSet, this); 1.171 + NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY); 1.172 + } 1.173 + else { 1.174 + *aResult = static_cast<txNodeSet*>(mNodeSetResults.pop()); 1.175 + (*aResult)->append(*aNodeSet); 1.176 + (*aResult)->mRecycler = this; 1.177 + } 1.178 + NS_ADDREF(*aResult); 1.179 + 1.180 + return NS_OK; 1.181 +} 1.182 + 1.183 +nsresult 1.184 +txResultRecycler::getNodeSet(const txXPathNode& aNode, txAExprResult** aResult) 1.185 +{ 1.186 + if (mNodeSetResults.isEmpty()) { 1.187 + *aResult = new txNodeSet(aNode, this); 1.188 + NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY); 1.189 + } 1.190 + else { 1.191 + txNodeSet* nodes = static_cast<txNodeSet*>(mNodeSetResults.pop()); 1.192 + nodes->append(aNode); 1.193 + nodes->mRecycler = this; 1.194 + *aResult = nodes; 1.195 + } 1.196 + NS_ADDREF(*aResult); 1.197 + 1.198 + return NS_OK; 1.199 +} 1.200 + 1.201 +nsresult 1.202 +txResultRecycler::getNumberResult(double aValue, txAExprResult** aResult) 1.203 +{ 1.204 + if (mNumberResults.isEmpty()) { 1.205 + *aResult = new NumberResult(aValue, this); 1.206 + NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY); 1.207 + } 1.208 + else { 1.209 + NumberResult* numRes = 1.210 + static_cast<NumberResult*>(mNumberResults.pop()); 1.211 + numRes->value = aValue; 1.212 + numRes->mRecycler = this; 1.213 + *aResult = numRes; 1.214 + } 1.215 + NS_ADDREF(*aResult); 1.216 + 1.217 + return NS_OK; 1.218 +} 1.219 + 1.220 +void 1.221 +txResultRecycler::getBoolResult(bool aValue, txAExprResult** aResult) 1.222 +{ 1.223 + *aResult = aValue ? mTrueResult : mFalseResult; 1.224 + NS_ADDREF(*aResult); 1.225 +} 1.226 + 1.227 +nsresult 1.228 +txResultRecycler::getNonSharedNodeSet(txNodeSet* aNodeSet, txNodeSet** aResult) 1.229 +{ 1.230 + if (aNodeSet->mRefCnt > 1) { 1.231 + return getNodeSet(aNodeSet, aResult); 1.232 + } 1.233 + 1.234 + *aResult = aNodeSet; 1.235 + NS_ADDREF(*aResult); 1.236 + 1.237 + return NS_OK; 1.238 +} 1.239 + 1.240 +void 1.241 +txAExprResult::Release() 1.242 +{ 1.243 + --mRefCnt; 1.244 + NS_LOG_RELEASE(this, mRefCnt, "txAExprResult"); 1.245 + if (mRefCnt == 0) { 1.246 + if (mRecycler) { 1.247 + mRecycler->recycle(this); 1.248 + } 1.249 + else { 1.250 + delete this; 1.251 + } 1.252 + } 1.253 +}