michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "txResultRecycler.h" michael@0: #include "txExprResult.h" michael@0: #include "txNodeSet.h" michael@0: michael@0: txResultRecycler::txResultRecycler() michael@0: : mEmptyStringResult(nullptr), michael@0: mTrueResult(nullptr), michael@0: mFalseResult(nullptr) michael@0: { michael@0: } michael@0: michael@0: txResultRecycler::~txResultRecycler() michael@0: { michael@0: txStackIterator stringIter(&mStringResults); michael@0: while (stringIter.hasNext()) { michael@0: delete static_cast(stringIter.next()); michael@0: } michael@0: txStackIterator nodesetIter(&mNodeSetResults); michael@0: while (nodesetIter.hasNext()) { michael@0: delete static_cast(nodesetIter.next()); michael@0: } michael@0: txStackIterator numberIter(&mNumberResults); michael@0: while (numberIter.hasNext()) { michael@0: delete static_cast(numberIter.next()); michael@0: } michael@0: michael@0: NS_IF_RELEASE(mEmptyStringResult); michael@0: NS_IF_RELEASE(mTrueResult); michael@0: NS_IF_RELEASE(mFalseResult); michael@0: } michael@0: michael@0: michael@0: nsresult michael@0: txResultRecycler::init() michael@0: { michael@0: NS_ASSERTION(!mEmptyStringResult && !mTrueResult && !mFalseResult, michael@0: "Already inited"); michael@0: mEmptyStringResult = new StringResult(nullptr); michael@0: NS_ENSURE_TRUE(mEmptyStringResult, NS_ERROR_OUT_OF_MEMORY); michael@0: michael@0: NS_ADDREF(mEmptyStringResult); michael@0: michael@0: mTrueResult = new BooleanResult(true); michael@0: NS_ENSURE_TRUE(mTrueResult, NS_ERROR_OUT_OF_MEMORY); michael@0: michael@0: NS_ADDREF(mTrueResult); michael@0: michael@0: mFalseResult = new BooleanResult(false); michael@0: NS_ENSURE_TRUE(mFalseResult, NS_ERROR_OUT_OF_MEMORY); michael@0: michael@0: NS_ADDREF(mFalseResult); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: michael@0: void michael@0: txResultRecycler::recycle(txAExprResult* aResult) michael@0: { michael@0: NS_ASSERTION(aResult->mRefCnt == 0, "In-use txAExprResult recycled"); michael@0: nsRefPtr kungFuDeathGrip; michael@0: aResult->mRecycler.swap(kungFuDeathGrip); michael@0: michael@0: nsresult rv = NS_OK; michael@0: switch (aResult->getResultType()) { michael@0: case txAExprResult::STRING: michael@0: { michael@0: rv = mStringResults.push(static_cast(aResult)); michael@0: if (NS_FAILED(rv)) { michael@0: delete aResult; michael@0: } michael@0: return; michael@0: } michael@0: case txAExprResult::NODESET: michael@0: { michael@0: static_cast(aResult)->clear(); michael@0: rv = mNodeSetResults.push(static_cast(aResult)); michael@0: if (NS_FAILED(rv)) { michael@0: delete aResult; michael@0: } michael@0: return; michael@0: } michael@0: case txAExprResult::NUMBER: michael@0: { michael@0: rv = mNumberResults.push(static_cast(aResult)); michael@0: if (NS_FAILED(rv)) { michael@0: delete aResult; michael@0: } michael@0: return; michael@0: } michael@0: default: michael@0: { michael@0: delete aResult; michael@0: } michael@0: } michael@0: } michael@0: michael@0: nsresult michael@0: txResultRecycler::getStringResult(StringResult** aResult) michael@0: { michael@0: if (mStringResults.isEmpty()) { michael@0: *aResult = new StringResult(this); michael@0: NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY); michael@0: } michael@0: else { michael@0: *aResult = static_cast(mStringResults.pop()); michael@0: (*aResult)->mValue.Truncate(); michael@0: (*aResult)->mRecycler = this; michael@0: } michael@0: NS_ADDREF(*aResult); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: txResultRecycler::getStringResult(const nsAString& aValue, michael@0: txAExprResult** aResult) michael@0: { michael@0: if (mStringResults.isEmpty()) { michael@0: *aResult = new StringResult(aValue, this); michael@0: NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY); michael@0: } michael@0: else { michael@0: StringResult* strRes = michael@0: static_cast(mStringResults.pop()); michael@0: strRes->mValue = aValue; michael@0: strRes->mRecycler = this; michael@0: *aResult = strRes; michael@0: } michael@0: NS_ADDREF(*aResult); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: void michael@0: txResultRecycler::getEmptyStringResult(txAExprResult** aResult) michael@0: { michael@0: *aResult = mEmptyStringResult; michael@0: NS_ADDREF(*aResult); michael@0: } michael@0: michael@0: nsresult michael@0: txResultRecycler::getNodeSet(txNodeSet** aResult) michael@0: { michael@0: if (mNodeSetResults.isEmpty()) { michael@0: *aResult = new txNodeSet(this); michael@0: NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY); michael@0: } michael@0: else { michael@0: *aResult = static_cast(mNodeSetResults.pop()); michael@0: (*aResult)->mRecycler = this; michael@0: } michael@0: NS_ADDREF(*aResult); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: txResultRecycler::getNodeSet(txNodeSet* aNodeSet, txNodeSet** aResult) michael@0: { michael@0: if (mNodeSetResults.isEmpty()) { michael@0: *aResult = new txNodeSet(*aNodeSet, this); michael@0: NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY); michael@0: } michael@0: else { michael@0: *aResult = static_cast(mNodeSetResults.pop()); michael@0: (*aResult)->append(*aNodeSet); michael@0: (*aResult)->mRecycler = this; michael@0: } michael@0: NS_ADDREF(*aResult); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: txResultRecycler::getNodeSet(const txXPathNode& aNode, txAExprResult** aResult) michael@0: { michael@0: if (mNodeSetResults.isEmpty()) { michael@0: *aResult = new txNodeSet(aNode, this); michael@0: NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY); michael@0: } michael@0: else { michael@0: txNodeSet* nodes = static_cast(mNodeSetResults.pop()); michael@0: nodes->append(aNode); michael@0: nodes->mRecycler = this; michael@0: *aResult = nodes; michael@0: } michael@0: NS_ADDREF(*aResult); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: txResultRecycler::getNumberResult(double aValue, txAExprResult** aResult) michael@0: { michael@0: if (mNumberResults.isEmpty()) { michael@0: *aResult = new NumberResult(aValue, this); michael@0: NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY); michael@0: } michael@0: else { michael@0: NumberResult* numRes = michael@0: static_cast(mNumberResults.pop()); michael@0: numRes->value = aValue; michael@0: numRes->mRecycler = this; michael@0: *aResult = numRes; michael@0: } michael@0: NS_ADDREF(*aResult); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: void michael@0: txResultRecycler::getBoolResult(bool aValue, txAExprResult** aResult) michael@0: { michael@0: *aResult = aValue ? mTrueResult : mFalseResult; michael@0: NS_ADDREF(*aResult); michael@0: } michael@0: michael@0: nsresult michael@0: txResultRecycler::getNonSharedNodeSet(txNodeSet* aNodeSet, txNodeSet** aResult) michael@0: { michael@0: if (aNodeSet->mRefCnt > 1) { michael@0: return getNodeSet(aNodeSet, aResult); michael@0: } michael@0: michael@0: *aResult = aNodeSet; michael@0: NS_ADDREF(*aResult); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: void michael@0: txAExprResult::Release() michael@0: { michael@0: --mRefCnt; michael@0: NS_LOG_RELEASE(this, mRefCnt, "txAExprResult"); michael@0: if (mRefCnt == 0) { michael@0: if (mRecycler) { michael@0: mRecycler->recycle(this); michael@0: } michael@0: else { michael@0: delete this; michael@0: } michael@0: } michael@0: }