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 "mozilla/Attributes.h" michael@0: michael@0: #include "nsEnumeratorUtils.h" michael@0: michael@0: #include "nsISimpleEnumerator.h" michael@0: #include "nsIStringEnumerator.h" michael@0: michael@0: #include "nsCOMPtr.h" michael@0: michael@0: class EmptyEnumeratorImpl : public nsISimpleEnumerator, michael@0: public nsIUTF8StringEnumerator, michael@0: public nsIStringEnumerator michael@0: { michael@0: public: michael@0: EmptyEnumeratorImpl() {} michael@0: // nsISupports interface michael@0: NS_DECL_ISUPPORTS_INHERITED // not really inherited, but no mRefCnt michael@0: michael@0: // nsISimpleEnumerator michael@0: NS_DECL_NSISIMPLEENUMERATOR michael@0: NS_DECL_NSIUTF8STRINGENUMERATOR michael@0: // can't use NS_DECL_NSISTRINGENUMERATOR because they share the michael@0: // HasMore() signature michael@0: NS_IMETHOD GetNext(nsAString& aResult); michael@0: michael@0: static EmptyEnumeratorImpl* GetInstance() { michael@0: static const EmptyEnumeratorImpl kInstance; michael@0: return const_cast(&kInstance); michael@0: } michael@0: }; michael@0: michael@0: // nsISupports interface michael@0: NS_IMETHODIMP_(MozExternalRefCountType) EmptyEnumeratorImpl::AddRef(void) michael@0: { michael@0: return 2; michael@0: } michael@0: michael@0: NS_IMETHODIMP_(MozExternalRefCountType) EmptyEnumeratorImpl::Release(void) michael@0: { michael@0: return 1; michael@0: } michael@0: michael@0: NS_IMPL_QUERY_INTERFACE(EmptyEnumeratorImpl, nsISimpleEnumerator, michael@0: nsIUTF8StringEnumerator, nsIStringEnumerator) michael@0: michael@0: // nsISimpleEnumerator interface michael@0: NS_IMETHODIMP EmptyEnumeratorImpl::HasMoreElements(bool* aResult) michael@0: { michael@0: *aResult = false; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP EmptyEnumeratorImpl::HasMore(bool* aResult) michael@0: { michael@0: *aResult = false; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP EmptyEnumeratorImpl::GetNext(nsISupports** aResult) michael@0: { michael@0: return NS_ERROR_UNEXPECTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP EmptyEnumeratorImpl::GetNext(nsACString& aResult) michael@0: { michael@0: return NS_ERROR_UNEXPECTED; michael@0: } michael@0: michael@0: NS_IMETHODIMP EmptyEnumeratorImpl::GetNext(nsAString& aResult) michael@0: { michael@0: return NS_ERROR_UNEXPECTED; michael@0: } michael@0: michael@0: nsresult michael@0: NS_NewEmptyEnumerator(nsISimpleEnumerator** aResult) michael@0: { michael@0: *aResult = EmptyEnumeratorImpl::GetInstance(); michael@0: return NS_OK; michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: class nsSingletonEnumerator MOZ_FINAL : public nsISimpleEnumerator michael@0: { michael@0: public: michael@0: NS_DECL_ISUPPORTS michael@0: michael@0: // nsISimpleEnumerator methods michael@0: NS_IMETHOD HasMoreElements(bool* aResult); michael@0: NS_IMETHOD GetNext(nsISupports** aResult); michael@0: michael@0: nsSingletonEnumerator(nsISupports* aValue); michael@0: michael@0: private: michael@0: ~nsSingletonEnumerator(); michael@0: michael@0: protected: michael@0: nsISupports* mValue; michael@0: bool mConsumed; michael@0: }; michael@0: michael@0: nsSingletonEnumerator::nsSingletonEnumerator(nsISupports* aValue) michael@0: : mValue(aValue) michael@0: { michael@0: NS_IF_ADDREF(mValue); michael@0: mConsumed = (mValue ? false : true); michael@0: } michael@0: michael@0: nsSingletonEnumerator::~nsSingletonEnumerator() michael@0: { michael@0: NS_IF_RELEASE(mValue); michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS(nsSingletonEnumerator, nsISimpleEnumerator) michael@0: michael@0: NS_IMETHODIMP michael@0: nsSingletonEnumerator::HasMoreElements(bool* aResult) michael@0: { michael@0: NS_PRECONDITION(aResult != 0, "null ptr"); michael@0: if (! aResult) michael@0: return NS_ERROR_NULL_POINTER; michael@0: michael@0: *aResult = !mConsumed; michael@0: return NS_OK; michael@0: } michael@0: michael@0: michael@0: NS_IMETHODIMP michael@0: nsSingletonEnumerator::GetNext(nsISupports** aResult) michael@0: { michael@0: NS_PRECONDITION(aResult != 0, "null ptr"); michael@0: if (! aResult) michael@0: return NS_ERROR_NULL_POINTER; michael@0: michael@0: if (mConsumed) michael@0: return NS_ERROR_UNEXPECTED; michael@0: michael@0: mConsumed = true; michael@0: michael@0: *aResult = mValue; michael@0: NS_ADDREF(*aResult); michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: NS_NewSingletonEnumerator(nsISimpleEnumerator* *result, michael@0: nsISupports* singleton) michael@0: { michael@0: nsSingletonEnumerator* enumer = new nsSingletonEnumerator(singleton); michael@0: if (enumer == nullptr) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: *result = enumer; michael@0: NS_ADDREF(*result); michael@0: return NS_OK; michael@0: } michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: class nsUnionEnumerator MOZ_FINAL : public nsISimpleEnumerator michael@0: { michael@0: public: michael@0: NS_DECL_ISUPPORTS michael@0: michael@0: // nsISimpleEnumerator methods michael@0: NS_IMETHOD HasMoreElements(bool* aResult); michael@0: NS_IMETHOD GetNext(nsISupports** aResult); michael@0: michael@0: nsUnionEnumerator(nsISimpleEnumerator* firstEnumerator, michael@0: nsISimpleEnumerator* secondEnumerator); michael@0: michael@0: private: michael@0: ~nsUnionEnumerator(); michael@0: michael@0: protected: michael@0: nsCOMPtr mFirstEnumerator, mSecondEnumerator; michael@0: bool mConsumed; michael@0: bool mAtSecond; michael@0: }; michael@0: michael@0: nsUnionEnumerator::nsUnionEnumerator(nsISimpleEnumerator* firstEnumerator, michael@0: nsISimpleEnumerator* secondEnumerator) michael@0: : mFirstEnumerator(firstEnumerator), michael@0: mSecondEnumerator(secondEnumerator), michael@0: mConsumed(false), mAtSecond(false) michael@0: { michael@0: } michael@0: michael@0: nsUnionEnumerator::~nsUnionEnumerator() michael@0: { michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS(nsUnionEnumerator, nsISimpleEnumerator) michael@0: michael@0: NS_IMETHODIMP michael@0: nsUnionEnumerator::HasMoreElements(bool* aResult) michael@0: { michael@0: NS_PRECONDITION(aResult != 0, "null ptr"); michael@0: if (! aResult) michael@0: return NS_ERROR_NULL_POINTER; michael@0: michael@0: nsresult rv; michael@0: michael@0: if (mConsumed) { michael@0: *aResult = false; michael@0: return NS_OK; michael@0: } michael@0: michael@0: if (! mAtSecond) { michael@0: rv = mFirstEnumerator->HasMoreElements(aResult); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: if (*aResult) michael@0: return NS_OK; michael@0: michael@0: mAtSecond = true; michael@0: } michael@0: michael@0: rv = mSecondEnumerator->HasMoreElements(aResult); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: if (*aResult) michael@0: return NS_OK; michael@0: michael@0: *aResult = false; michael@0: mConsumed = true; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsUnionEnumerator::GetNext(nsISupports** aResult) michael@0: { michael@0: NS_PRECONDITION(aResult != 0, "null ptr"); michael@0: if (! aResult) michael@0: return NS_ERROR_NULL_POINTER; michael@0: michael@0: if (mConsumed) michael@0: return NS_ERROR_UNEXPECTED; michael@0: michael@0: if (! mAtSecond) michael@0: return mFirstEnumerator->GetNext(aResult); michael@0: michael@0: return mSecondEnumerator->GetNext(aResult); michael@0: } michael@0: michael@0: nsresult michael@0: NS_NewUnionEnumerator(nsISimpleEnumerator* *result, michael@0: nsISimpleEnumerator* firstEnumerator, michael@0: nsISimpleEnumerator* secondEnumerator) michael@0: { michael@0: *result = nullptr; michael@0: if (! firstEnumerator) { michael@0: *result = secondEnumerator; michael@0: } else if (! secondEnumerator) { michael@0: *result = firstEnumerator; michael@0: } else { michael@0: nsUnionEnumerator* enumer = new nsUnionEnumerator(firstEnumerator, secondEnumerator); michael@0: if (enumer == nullptr) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: *result = enumer; michael@0: } michael@0: NS_ADDREF(*result); michael@0: return NS_OK; michael@0: }