1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/glue/nsCOMArray.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,307 @@ 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 "nsCOMArray.h" 1.10 + 1.11 +#include "mozilla/MemoryReporting.h" 1.12 + 1.13 +#include "nsCOMPtr.h" 1.14 + 1.15 +// This specialization is private to nsCOMArray. 1.16 +// It exists solely to automatically zero-out newly created array elements. 1.17 +template<> 1.18 +class nsTArrayElementTraits<nsISupports*> 1.19 +{ 1.20 + typedef nsISupports* E; 1.21 +public: 1.22 + // Zero out the value 1.23 + static inline void Construct(E *e) { 1.24 + new (static_cast<void *>(e)) E(); 1.25 + } 1.26 + // Invoke the copy-constructor in place. 1.27 + template<class A> 1.28 + static inline void Construct(E *e, const A &arg) { 1.29 + new (static_cast<void *>(e)) E(arg); 1.30 + } 1.31 + // Invoke the destructor in place. 1.32 + static inline void Destruct(E *e) { 1.33 + e->~E(); 1.34 + } 1.35 +}; 1.36 + 1.37 +static void ReleaseObjects(nsTArray<nsISupports*> &aArray); 1.38 + 1.39 +// implementations of non-trivial methods in nsCOMArray_base 1.40 + 1.41 +nsCOMArray_base::nsCOMArray_base(const nsCOMArray_base& aOther) 1.42 +{ 1.43 + // make sure we do only one allocation 1.44 + mArray.SetCapacity(aOther.Count()); 1.45 + AppendObjects(aOther); 1.46 +} 1.47 + 1.48 +nsCOMArray_base::~nsCOMArray_base() 1.49 +{ 1.50 + Clear(); 1.51 +} 1.52 + 1.53 +int32_t 1.54 +nsCOMArray_base::IndexOf(nsISupports* aObject, uint32_t aStartIndex) const 1.55 +{ 1.56 + return mArray.IndexOf(aObject, aStartIndex); 1.57 +} 1.58 + 1.59 +int32_t 1.60 +nsCOMArray_base::IndexOfObject(nsISupports* aObject) const 1.61 +{ 1.62 + nsCOMPtr<nsISupports> supports = do_QueryInterface(aObject); 1.63 + if (NS_WARN_IF(!supports)) 1.64 + return -1; 1.65 + 1.66 + uint32_t i, count; 1.67 + int32_t retval = -1; 1.68 + count = mArray.Length(); 1.69 + for (i = 0; i < count; ++i) { 1.70 + nsCOMPtr<nsISupports> arrayItem = do_QueryInterface(mArray[i]); 1.71 + if (arrayItem == supports) { 1.72 + retval = i; 1.73 + break; 1.74 + } 1.75 + } 1.76 + return retval; 1.77 +} 1.78 + 1.79 +bool 1.80 +nsCOMArray_base::EnumerateForwards(nsBaseArrayEnumFunc aFunc, void* aData) const 1.81 +{ 1.82 + for (uint32_t index = 0; index < mArray.Length(); index++) 1.83 + if (!(*aFunc)(mArray[index], aData)) 1.84 + return false; 1.85 + 1.86 + return true; 1.87 +} 1.88 + 1.89 +bool 1.90 +nsCOMArray_base::EnumerateBackwards(nsBaseArrayEnumFunc aFunc, void* aData) const 1.91 +{ 1.92 + for (uint32_t index = mArray.Length(); index--; ) 1.93 + if (!(*aFunc)(mArray[index], aData)) 1.94 + return false; 1.95 + 1.96 + return true; 1.97 +} 1.98 + 1.99 +int 1.100 +nsCOMArray_base::nsCOMArrayComparator(const void* aElement1, const void* aElement2, void* aData) 1.101 +{ 1.102 + nsCOMArrayComparatorContext* ctx = static_cast<nsCOMArrayComparatorContext*>(aData); 1.103 + return (*ctx->mComparatorFunc)(*static_cast<nsISupports* const*>(aElement1), 1.104 + *static_cast<nsISupports* const*>(aElement2), 1.105 + ctx->mData); 1.106 +} 1.107 + 1.108 +void 1.109 +nsCOMArray_base::Sort(nsBaseArrayComparatorFunc aFunc, void* aData) 1.110 +{ 1.111 + if (mArray.Length() > 1) { 1.112 + nsCOMArrayComparatorContext ctx = {aFunc, aData}; 1.113 + NS_QuickSort(mArray.Elements(), mArray.Length(), sizeof(nsISupports*), 1.114 + nsCOMArrayComparator, &ctx); 1.115 + } 1.116 +} 1.117 + 1.118 +bool 1.119 +nsCOMArray_base::InsertObjectAt(nsISupports* aObject, int32_t aIndex) 1.120 +{ 1.121 + if ((uint32_t)aIndex > mArray.Length()) 1.122 + return false; 1.123 + 1.124 + if (!mArray.InsertElementAt(aIndex, aObject)) 1.125 + return false; 1.126 + 1.127 + NS_IF_ADDREF(aObject); 1.128 + return true; 1.129 +} 1.130 + 1.131 +void 1.132 +nsCOMArray_base::InsertElementAt(uint32_t aIndex, nsISupports* aElement) 1.133 +{ 1.134 + mArray.InsertElementAt(aIndex, aElement); 1.135 + NS_IF_ADDREF(aElement); 1.136 +} 1.137 + 1.138 +bool 1.139 +nsCOMArray_base::InsertObjectsAt(const nsCOMArray_base& aObjects, int32_t aIndex) 1.140 +{ 1.141 + if ((uint32_t)aIndex > mArray.Length()) 1.142 + return false; 1.143 + 1.144 + if (!mArray.InsertElementsAt(aIndex, aObjects.mArray)) 1.145 + return false; 1.146 + 1.147 + // need to addref all these 1.148 + uint32_t count = aObjects.Length(); 1.149 + for (uint32_t i = 0; i < count; ++i) 1.150 + NS_IF_ADDREF(aObjects[i]); 1.151 + 1.152 + return true; 1.153 +} 1.154 + 1.155 +void 1.156 +nsCOMArray_base::InsertElementsAt(uint32_t aIndex, const nsCOMArray_base& aElements) 1.157 +{ 1.158 + mArray.InsertElementsAt(aIndex, aElements.mArray); 1.159 + 1.160 + // need to addref all these 1.161 + uint32_t count = aElements.Length(); 1.162 + for (uint32_t i = 0; i < count; ++i) 1.163 + NS_IF_ADDREF(aElements[i]); 1.164 +} 1.165 + 1.166 +void 1.167 +nsCOMArray_base::InsertElementsAt(uint32_t aIndex, nsISupports* const* aElements, uint32_t aCount) 1.168 +{ 1.169 + mArray.InsertElementsAt(aIndex, aElements, aCount); 1.170 + 1.171 + // need to addref all these 1.172 + for (uint32_t i = 0; i < aCount; ++i) 1.173 + NS_IF_ADDREF(aElements[i]); 1.174 +} 1.175 + 1.176 +bool 1.177 +nsCOMArray_base::ReplaceObjectAt(nsISupports* aObject, int32_t aIndex) 1.178 +{ 1.179 + mArray.EnsureLengthAtLeast(aIndex + 1); 1.180 + nsISupports *oldObject = mArray[aIndex]; 1.181 + // Make sure to addref first, in case aObject == oldObject 1.182 + NS_IF_ADDREF(mArray[aIndex] = aObject); 1.183 + NS_IF_RELEASE(oldObject); 1.184 + // XXX make this return void 1.185 + return true; 1.186 +} 1.187 + 1.188 +bool 1.189 +nsCOMArray_base::RemoveObject(nsISupports *aObject) 1.190 +{ 1.191 + bool result = mArray.RemoveElement(aObject); 1.192 + if (result) 1.193 + NS_IF_RELEASE(aObject); 1.194 + return result; 1.195 +} 1.196 + 1.197 +bool 1.198 +nsCOMArray_base::RemoveObjectAt(int32_t aIndex) 1.199 +{ 1.200 + if (uint32_t(aIndex) < mArray.Length()) { 1.201 + nsISupports* element = mArray[aIndex]; 1.202 + 1.203 + mArray.RemoveElementAt(aIndex); 1.204 + NS_IF_RELEASE(element); 1.205 + return true; 1.206 + } 1.207 + 1.208 + return false; 1.209 +} 1.210 + 1.211 +void 1.212 +nsCOMArray_base::RemoveElementAt(uint32_t aIndex) 1.213 +{ 1.214 + nsISupports* element = mArray[aIndex]; 1.215 + mArray.RemoveElementAt(aIndex); 1.216 + NS_IF_RELEASE(element); 1.217 +} 1.218 + 1.219 +bool 1.220 +nsCOMArray_base::RemoveObjectsAt(int32_t aIndex, int32_t aCount) 1.221 +{ 1.222 + if (uint32_t(aIndex) + uint32_t(aCount) <= mArray.Length()) { 1.223 + nsTArray<nsISupports*> elementsToDestroy(aCount); 1.224 + elementsToDestroy.AppendElements(mArray.Elements() + aIndex, aCount); 1.225 + mArray.RemoveElementsAt(aIndex, aCount); 1.226 + ReleaseObjects(elementsToDestroy); 1.227 + return true; 1.228 + } 1.229 + 1.230 + return false; 1.231 +} 1.232 + 1.233 +void 1.234 +nsCOMArray_base::RemoveElementsAt(uint32_t aIndex, uint32_t aCount) 1.235 +{ 1.236 + nsTArray<nsISupports*> elementsToDestroy(aCount); 1.237 + elementsToDestroy.AppendElements(mArray.Elements() + aIndex, aCount); 1.238 + mArray.RemoveElementsAt(aIndex, aCount); 1.239 + ReleaseObjects(elementsToDestroy); 1.240 +} 1.241 + 1.242 +// useful for destructors 1.243 +void 1.244 +ReleaseObjects(nsTArray<nsISupports*> &aArray) 1.245 +{ 1.246 + for (uint32_t i = 0; i < aArray.Length(); i++) 1.247 + NS_IF_RELEASE(aArray[i]); 1.248 +} 1.249 + 1.250 +void 1.251 +nsCOMArray_base::Clear() 1.252 +{ 1.253 + nsTArray<nsISupports*> objects; 1.254 + objects.SwapElements(mArray); 1.255 + ReleaseObjects(objects); 1.256 +} 1.257 + 1.258 +bool 1.259 +nsCOMArray_base::SetCount(int32_t aNewCount) 1.260 +{ 1.261 + NS_ASSERTION(aNewCount >= 0,"SetCount(negative index)"); 1.262 + if (aNewCount < 0) 1.263 + return false; 1.264 + 1.265 + int32_t count = mArray.Length(); 1.266 + if (count > aNewCount) 1.267 + RemoveObjectsAt(aNewCount, mArray.Length() - aNewCount); 1.268 + mArray.SetLength(aNewCount); 1.269 + return true; 1.270 +} 1.271 + 1.272 +size_t 1.273 +nsCOMArray_base::SizeOfExcludingThis( 1.274 + nsBaseArraySizeOfElementIncludingThisFunc aSizeOfElementIncludingThis, 1.275 + mozilla::MallocSizeOf aMallocSizeOf, void* aData) const 1.276 +{ 1.277 + size_t n = mArray.SizeOfExcludingThis(aMallocSizeOf); 1.278 + 1.279 + if (aSizeOfElementIncludingThis) 1.280 + for (uint32_t index = 0; index < mArray.Length(); index++) 1.281 + n += aSizeOfElementIncludingThis(mArray[index], aMallocSizeOf, aData); 1.282 + 1.283 + return n; 1.284 +} 1.285 + 1.286 + 1.287 +void 1.288 +nsCOMArray_base::Adopt(nsISupports** aElements, uint32_t aSize) 1.289 +{ 1.290 + Clear(); 1.291 + mArray.AppendElements(aElements, aSize); 1.292 + 1.293 + // Free the allocated array as well. 1.294 + NS_Free(aElements); 1.295 +} 1.296 + 1.297 +uint32_t 1.298 +nsCOMArray_base::Forget(nsISupports*** elements) 1.299 +{ 1.300 + uint32_t length = Length(); 1.301 + size_t array_size = sizeof(nsISupports*) * length; 1.302 + nsISupports** array = static_cast<nsISupports**>(NS_Alloc(array_size)); 1.303 + memmove(array, Elements(), array_size); 1.304 + *elements = array; 1.305 + // Don't Release the contained pointers; the caller of the method will 1.306 + // do this eventually. 1.307 + mArray.Clear(); 1.308 + 1.309 + return length; 1.310 +}