xpcom/glue/nsArrayEnumerator.cpp

changeset 0
6474c204b198
     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 +}

mercurial