Back to index

lightning-sunbird  0.9+nobinonly
txResultRecycler.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is TransforMiiX XSLT processor code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * IBM Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 2002
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   IBM Corporation
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "txResultRecycler.h"
00040 #include "ExprResult.h"
00041 #include "txNodeSet.h"
00042 
00043 txResultRecycler::txResultRecycler()
00044     : mEmptyStringResult(nsnull),
00045       mTrueResult(nsnull),
00046       mFalseResult(nsnull)
00047 {
00048 }
00049 
00050 txResultRecycler::~txResultRecycler()
00051 {
00052     txStackIterator stringIter(&mStringResults);
00053     while (stringIter.hasNext()) {
00054         delete NS_STATIC_CAST(StringResult*, stringIter.next());
00055     }
00056     txStackIterator nodesetIter(&mNodeSetResults);
00057     while (nodesetIter.hasNext()) {
00058         delete NS_STATIC_CAST(txNodeSet*, nodesetIter.next());
00059     }
00060     txStackIterator numberIter(&mNumberResults);
00061     while (numberIter.hasNext()) {
00062         delete NS_STATIC_CAST(NumberResult*, numberIter.next());
00063     }
00064 
00065     NS_IF_RELEASE(mEmptyStringResult);
00066     NS_IF_RELEASE(mTrueResult);
00067     NS_IF_RELEASE(mFalseResult);
00068 }
00069 
00070 
00071 nsresult
00072 txResultRecycler::init()
00073 {
00074     NS_ASSERTION(!mEmptyStringResult && !mTrueResult && !mFalseResult,
00075                  "Already inited");
00076     mEmptyStringResult = new StringResult(nsnull);
00077     NS_ENSURE_TRUE(mEmptyStringResult, NS_ERROR_OUT_OF_MEMORY);
00078 
00079     NS_ADDREF(mEmptyStringResult);
00080 
00081     mTrueResult = new BooleanResult(PR_TRUE);
00082     NS_ENSURE_TRUE(mTrueResult, NS_ERROR_OUT_OF_MEMORY);
00083 
00084     NS_ADDREF(mTrueResult);
00085 
00086     mFalseResult = new BooleanResult(PR_FALSE);
00087     NS_ENSURE_TRUE(mFalseResult, NS_ERROR_OUT_OF_MEMORY);
00088 
00089     NS_ADDREF(mFalseResult);
00090 
00091     return NS_OK;
00092 }
00093 
00094 
00095 void
00096 txResultRecycler::recycle(txAExprResult* aResult)
00097 {
00098     NS_ASSERTION(aResult->mRefCnt == 0, "In-use txAExprResult recycled");
00099     nsRefPtr<txResultRecycler> kungFuDeathGrip;
00100     aResult->mRecycler.swap(kungFuDeathGrip);
00101 
00102     nsresult rv = NS_OK;
00103     switch (aResult->getResultType()) {
00104         case txAExprResult::STRING:
00105         {
00106             rv = mStringResults.push(NS_STATIC_CAST(StringResult*, aResult));
00107             if (NS_FAILED(rv)) {
00108                 delete aResult;
00109             }
00110             return;
00111         }
00112         case txAExprResult::NODESET:
00113         {
00114             rv = mNodeSetResults.push(NS_STATIC_CAST(txNodeSet*, aResult));
00115             if (NS_FAILED(rv)) {
00116                 delete aResult;
00117             }
00118             return;
00119         }
00120         case txAExprResult::NUMBER:
00121         {
00122             rv = mNumberResults.push(NS_STATIC_CAST(NumberResult*, aResult));
00123             if (NS_FAILED(rv)) {
00124                 delete aResult;
00125             }
00126             return;
00127         }
00128         default:
00129         {
00130             delete aResult;
00131         }
00132     }
00133 }
00134 
00135 nsresult
00136 txResultRecycler::getStringResult(StringResult** aResult)
00137 {
00138     if (mStringResults.isEmpty()) {
00139         *aResult = new StringResult(this);
00140         NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
00141     }
00142     else {
00143         *aResult = NS_STATIC_CAST(StringResult*, mStringResults.pop());
00144         (*aResult)->mValue.Truncate();
00145         (*aResult)->mRecycler = this;
00146     }
00147     NS_ADDREF(*aResult);
00148 
00149     return NS_OK;
00150 }
00151 
00152 nsresult
00153 txResultRecycler::getStringResult(const nsAString& aValue,
00154                                   txAExprResult** aResult)
00155 {
00156     if (mStringResults.isEmpty()) {
00157         *aResult = new StringResult(aValue, this);
00158         NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
00159     }
00160     else {
00161         StringResult* strRes =
00162             NS_STATIC_CAST(StringResult*, mStringResults.pop());
00163         strRes->mValue = aValue;
00164         strRes->mRecycler = this;
00165         *aResult = strRes;
00166     }
00167     NS_ADDREF(*aResult);
00168 
00169     return NS_OK;
00170 }
00171 
00172 void
00173 txResultRecycler::getEmptyStringResult(txAExprResult** aResult)
00174 {
00175     *aResult = mEmptyStringResult;
00176     NS_ADDREF(*aResult);
00177 }
00178 
00179 nsresult
00180 txResultRecycler::getNodeSet(txNodeSet** aResult)
00181 {
00182     if (mNodeSetResults.isEmpty()) {
00183         *aResult = new txNodeSet(this);
00184         NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
00185     }
00186     else {
00187         *aResult = NS_STATIC_CAST(txNodeSet*, mNodeSetResults.pop());
00188         (*aResult)->clear();
00189         (*aResult)->mRecycler = this;
00190     }
00191     NS_ADDREF(*aResult);
00192 
00193     return NS_OK;
00194 }
00195 
00196 nsresult
00197 txResultRecycler::getNodeSet(txNodeSet* aNodeSet, txNodeSet** aResult)
00198 {
00199     if (mNodeSetResults.isEmpty()) {
00200         *aResult = new txNodeSet(*aNodeSet, this);
00201         NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
00202     }
00203     else {
00204         *aResult = NS_STATIC_CAST(txNodeSet*, mNodeSetResults.pop());
00205         (*aResult)->clear();
00206         (*aResult)->append(*aNodeSet);
00207         (*aResult)->mRecycler = this;
00208     }
00209     NS_ADDREF(*aResult);
00210 
00211     return NS_OK;
00212 }
00213 
00214 nsresult
00215 txResultRecycler::getNodeSet(const txXPathNode& aNode, txAExprResult** aResult)
00216 {
00217     if (mNodeSetResults.isEmpty()) {
00218         *aResult = new txNodeSet(aNode, this);
00219         NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
00220     }
00221     else {
00222         txNodeSet* nodes = NS_STATIC_CAST(txNodeSet*, mNodeSetResults.pop());
00223         nodes->clear();
00224         nodes->append(aNode);
00225         nodes->mRecycler = this;
00226         *aResult = nodes;
00227     }
00228     NS_ADDREF(*aResult);
00229 
00230     return NS_OK;
00231 }
00232 
00233 nsresult
00234 txResultRecycler::getNodeSet(const txXPathNode& aNode, txNodeSet** aResult)
00235 {
00236     if (mNodeSetResults.isEmpty()) {
00237         *aResult = new txNodeSet(aNode, this);
00238         NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
00239     }
00240     else {
00241         *aResult = NS_STATIC_CAST(txNodeSet*, mNodeSetResults.pop());
00242         (*aResult)->clear();
00243         (*aResult)->append(aNode);
00244         (*aResult)->mRecycler = this;
00245     }
00246     NS_ADDREF(*aResult);
00247 
00248     return NS_OK;
00249 }
00250 
00251 nsresult
00252 txResultRecycler::getNumberResult(double aValue, txAExprResult** aResult)
00253 {
00254     if (mNumberResults.isEmpty()) {
00255         *aResult = new NumberResult(aValue, this);
00256         NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY);
00257     }
00258     else {
00259         NumberResult* numRes =
00260             NS_STATIC_CAST(NumberResult*, mNumberResults.pop());
00261         numRes->value = aValue;
00262         numRes->mRecycler = this;
00263         *aResult = numRes;
00264     }
00265     NS_ADDREF(*aResult);
00266 
00267     return NS_OK;
00268 }
00269 
00270 void
00271 txResultRecycler::getBoolResult(PRBool aValue, txAExprResult** aResult)
00272 {
00273     *aResult = aValue ? mTrueResult : mFalseResult;
00274     NS_ADDREF(*aResult);
00275 }
00276 
00277 nsresult
00278 txResultRecycler::getNonSharedNodeSet(txNodeSet* aNodeSet, txNodeSet** aResult)
00279 {
00280     if (aNodeSet->mRefCnt > 1) {
00281         return getNodeSet(aNodeSet, aResult);
00282     }
00283 
00284     *aResult = aNodeSet;
00285     NS_ADDREF(*aResult);
00286 
00287     return NS_OK;
00288 }
00289 
00290 void
00291 txAExprResult::Release()
00292 {
00293     if (--mRefCnt == 0) {
00294         if (mRecycler) {
00295             mRecycler->recycle(this);
00296         }
00297         else {
00298             delete this;
00299         }
00300     }
00301 }