1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/glue/nsArrayEnumerator.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,207 @@ 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 "mozilla/Attributes.h" 1.10 + 1.11 +#include "nsArrayEnumerator.h" 1.12 + 1.13 +#include "nsIArray.h" 1.14 +#include "nsISimpleEnumerator.h" 1.15 + 1.16 +#include "nsCOMArray.h" 1.17 +#include "nsCOMPtr.h" 1.18 + 1.19 +class nsSimpleArrayEnumerator MOZ_FINAL : public nsISimpleEnumerator 1.20 +{ 1.21 +public: 1.22 + // nsISupports interface 1.23 + NS_DECL_ISUPPORTS 1.24 + 1.25 + // nsISimpleEnumerator interface 1.26 + NS_DECL_NSISIMPLEENUMERATOR 1.27 + 1.28 + // nsSimpleArrayEnumerator methods 1.29 + nsSimpleArrayEnumerator(nsIArray* aValueArray) : 1.30 + mValueArray(aValueArray), mIndex(0) { 1.31 + } 1.32 + 1.33 +private: 1.34 + ~nsSimpleArrayEnumerator() {} 1.35 + 1.36 +protected: 1.37 + nsCOMPtr<nsIArray> mValueArray; 1.38 + uint32_t mIndex; 1.39 +}; 1.40 + 1.41 +NS_IMPL_ISUPPORTS(nsSimpleArrayEnumerator, nsISimpleEnumerator) 1.42 + 1.43 +NS_IMETHODIMP 1.44 +nsSimpleArrayEnumerator::HasMoreElements(bool* aResult) 1.45 +{ 1.46 + NS_PRECONDITION(aResult != 0, "null ptr"); 1.47 + if (! aResult) 1.48 + return NS_ERROR_NULL_POINTER; 1.49 + 1.50 + if (!mValueArray) { 1.51 + *aResult = false; 1.52 + return NS_OK; 1.53 + } 1.54 + 1.55 + uint32_t cnt; 1.56 + nsresult rv = mValueArray->GetLength(&cnt); 1.57 + if (NS_FAILED(rv)) return rv; 1.58 + *aResult = (mIndex < cnt); 1.59 + return NS_OK; 1.60 +} 1.61 + 1.62 +NS_IMETHODIMP 1.63 +nsSimpleArrayEnumerator::GetNext(nsISupports** aResult) 1.64 +{ 1.65 + NS_PRECONDITION(aResult != 0, "null ptr"); 1.66 + if (! aResult) 1.67 + return NS_ERROR_NULL_POINTER; 1.68 + 1.69 + if (!mValueArray) { 1.70 + *aResult = nullptr; 1.71 + return NS_OK; 1.72 + } 1.73 + 1.74 + uint32_t cnt; 1.75 + nsresult rv = mValueArray->GetLength(&cnt); 1.76 + if (NS_FAILED(rv)) return rv; 1.77 + if (mIndex >= cnt) 1.78 + return NS_ERROR_UNEXPECTED; 1.79 + 1.80 + return mValueArray->QueryElementAt(mIndex++, NS_GET_IID(nsISupports), (void**)aResult); 1.81 +} 1.82 + 1.83 +nsresult 1.84 +NS_NewArrayEnumerator(nsISimpleEnumerator* *result, 1.85 + nsIArray* array) 1.86 +{ 1.87 + nsSimpleArrayEnumerator* enumer = new nsSimpleArrayEnumerator(array); 1.88 + if (enumer == nullptr) 1.89 + return NS_ERROR_OUT_OF_MEMORY; 1.90 + 1.91 + NS_ADDREF(*result = enumer); 1.92 + return NS_OK; 1.93 +} 1.94 + 1.95 +//////////////////////////////////////////////////////////////////////////////// 1.96 + 1.97 +// enumerator implementation for nsCOMArray 1.98 +// creates a snapshot of the array in question 1.99 +// you MUST use NS_NewArrayEnumerator to create this, so that 1.100 +// allocation is done correctly 1.101 +class nsCOMArrayEnumerator MOZ_FINAL : public nsISimpleEnumerator 1.102 +{ 1.103 +public: 1.104 + // nsISupports interface 1.105 + NS_DECL_ISUPPORTS 1.106 + 1.107 + // nsISimpleEnumerator interface 1.108 + NS_DECL_NSISIMPLEENUMERATOR 1.109 + 1.110 + // nsSimpleArrayEnumerator methods 1.111 + nsCOMArrayEnumerator() : mIndex(0) { 1.112 + } 1.113 + 1.114 + // specialized operator to make sure we make room for mValues 1.115 + void* operator new (size_t size, const nsCOMArray_base& aArray) CPP_THROW_NEW; 1.116 + void operator delete(void* ptr) { 1.117 + ::operator delete(ptr); 1.118 + } 1.119 + 1.120 +private: 1.121 + ~nsCOMArrayEnumerator(void); 1.122 + 1.123 +protected: 1.124 + uint32_t mIndex; // current position 1.125 + uint32_t mArraySize; // size of the array 1.126 + 1.127 + // this is actually bigger 1.128 + nsISupports* mValueArray[1]; 1.129 +}; 1.130 + 1.131 +NS_IMPL_ISUPPORTS(nsCOMArrayEnumerator, nsISimpleEnumerator) 1.132 + 1.133 +nsCOMArrayEnumerator::~nsCOMArrayEnumerator() 1.134 +{ 1.135 + // only release the entries that we haven't visited yet 1.136 + for (; mIndex < mArraySize; ++mIndex) { 1.137 + NS_IF_RELEASE(mValueArray[mIndex]); 1.138 + } 1.139 +} 1.140 + 1.141 +NS_IMETHODIMP 1.142 +nsCOMArrayEnumerator::HasMoreElements(bool* aResult) 1.143 +{ 1.144 + NS_PRECONDITION(aResult != 0, "null ptr"); 1.145 + if (! aResult) 1.146 + return NS_ERROR_NULL_POINTER; 1.147 + 1.148 + *aResult = (mIndex < mArraySize); 1.149 + return NS_OK; 1.150 +} 1.151 + 1.152 +NS_IMETHODIMP 1.153 +nsCOMArrayEnumerator::GetNext(nsISupports** aResult) 1.154 +{ 1.155 + NS_PRECONDITION(aResult != 0, "null ptr"); 1.156 + if (! aResult) 1.157 + return NS_ERROR_NULL_POINTER; 1.158 + 1.159 + if (mIndex >= mArraySize) 1.160 + return NS_ERROR_UNEXPECTED; 1.161 + 1.162 + // pass the ownership of the reference to the caller. Since 1.163 + // we AddRef'ed during creation of |this|, there is no need 1.164 + // to AddRef here 1.165 + *aResult = mValueArray[mIndex++]; 1.166 + 1.167 + // this really isn't necessary. just pretend this happens, since 1.168 + // we'll never visit this value again! 1.169 + // mValueArray[(mIndex-1)] = nullptr; 1.170 + 1.171 + return NS_OK; 1.172 +} 1.173 + 1.174 +void* 1.175 +nsCOMArrayEnumerator::operator new (size_t size, const nsCOMArray_base& aArray) 1.176 + CPP_THROW_NEW 1.177 +{ 1.178 + // create enough space such that mValueArray points to a large 1.179 + // enough value. Note that the initial value of size gives us 1.180 + // space for mValueArray[0], so we must subtract 1.181 + size += (aArray.Count() - 1) * sizeof(aArray[0]); 1.182 + 1.183 + // do the actual allocation 1.184 + nsCOMArrayEnumerator * result = 1.185 + static_cast<nsCOMArrayEnumerator*>(::operator new(size)); 1.186 + 1.187 + // now need to copy over the values, and addref each one 1.188 + // now this might seem like a lot of work, but we're actually just 1.189 + // doing all our AddRef's ahead of time since GetNext() doesn't 1.190 + // need to AddRef() on the way out 1.191 + uint32_t i; 1.192 + uint32_t max = result->mArraySize = aArray.Count(); 1.193 + for (i = 0; i<max; i++) { 1.194 + result->mValueArray[i] = aArray[i]; 1.195 + NS_IF_ADDREF(result->mValueArray[i]); 1.196 + } 1.197 + 1.198 + return result; 1.199 +} 1.200 + 1.201 +nsresult 1.202 +NS_NewArrayEnumerator(nsISimpleEnumerator* *aResult, 1.203 + const nsCOMArray_base& aArray) 1.204 +{ 1.205 + nsCOMArrayEnumerator *enumerator = new (aArray) nsCOMArrayEnumerator(); 1.206 + if (!enumerator) return NS_ERROR_OUT_OF_MEMORY; 1.207 + 1.208 + NS_ADDREF(*aResult = enumerator); 1.209 + return NS_OK; 1.210 +}