diff options
Diffstat (limited to 'xpcom/glue/nsEnumeratorUtils.cpp')
-rw-r--r-- | xpcom/glue/nsEnumeratorUtils.cpp | 291 |
1 files changed, 291 insertions, 0 deletions
diff --git a/xpcom/glue/nsEnumeratorUtils.cpp b/xpcom/glue/nsEnumeratorUtils.cpp new file mode 100644 index 0000000000..d1843a78ad --- /dev/null +++ b/xpcom/glue/nsEnumeratorUtils.cpp @@ -0,0 +1,291 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/Attributes.h" + +#include "nsEnumeratorUtils.h" + +#include "nsISimpleEnumerator.h" +#include "nsIStringEnumerator.h" + +#include "nsCOMPtr.h" +#include "mozilla/RefPtr.h" + +class EmptyEnumeratorImpl + : public nsISimpleEnumerator + , public nsIUTF8StringEnumerator + , public nsIStringEnumerator +{ +public: + EmptyEnumeratorImpl() {} + + // nsISupports interface + NS_DECL_ISUPPORTS_INHERITED // not really inherited, but no mRefCnt + + // nsISimpleEnumerator + NS_DECL_NSISIMPLEENUMERATOR + NS_DECL_NSIUTF8STRINGENUMERATOR + // can't use NS_DECL_NSISTRINGENUMERATOR because they share the + // HasMore() signature + NS_IMETHOD GetNext(nsAString& aResult) override; + + static EmptyEnumeratorImpl* GetInstance() + { + static const EmptyEnumeratorImpl kInstance; + return const_cast<EmptyEnumeratorImpl*>(&kInstance); + } +}; + +// nsISupports interface +NS_IMETHODIMP_(MozExternalRefCountType) +EmptyEnumeratorImpl::AddRef(void) +{ + return 2; +} + +NS_IMETHODIMP_(MozExternalRefCountType) +EmptyEnumeratorImpl::Release(void) +{ + return 1; +} + +NS_IMPL_QUERY_INTERFACE(EmptyEnumeratorImpl, nsISimpleEnumerator, + nsIUTF8StringEnumerator, nsIStringEnumerator) + +// nsISimpleEnumerator interface +NS_IMETHODIMP +EmptyEnumeratorImpl::HasMoreElements(bool* aResult) +{ + *aResult = false; + return NS_OK; +} + +NS_IMETHODIMP +EmptyEnumeratorImpl::HasMore(bool* aResult) +{ + *aResult = false; + return NS_OK; +} + +NS_IMETHODIMP +EmptyEnumeratorImpl::GetNext(nsISupports** aResult) +{ + return NS_ERROR_UNEXPECTED; +} + +NS_IMETHODIMP +EmptyEnumeratorImpl::GetNext(nsACString& aResult) +{ + return NS_ERROR_UNEXPECTED; +} + +NS_IMETHODIMP +EmptyEnumeratorImpl::GetNext(nsAString& aResult) +{ + return NS_ERROR_UNEXPECTED; +} + +nsresult +NS_NewEmptyEnumerator(nsISimpleEnumerator** aResult) +{ + *aResult = EmptyEnumeratorImpl::GetInstance(); + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////////////// + +class nsSingletonEnumerator final : public nsISimpleEnumerator +{ +public: + NS_DECL_ISUPPORTS + + // nsISimpleEnumerator methods + NS_IMETHOD HasMoreElements(bool* aResult) override; + NS_IMETHOD GetNext(nsISupports** aResult) override; + + explicit nsSingletonEnumerator(nsISupports* aValue); + +private: + ~nsSingletonEnumerator(); + +protected: + nsCOMPtr<nsISupports> mValue; + bool mConsumed; +}; + +nsSingletonEnumerator::nsSingletonEnumerator(nsISupports* aValue) + : mValue(aValue) +{ + mConsumed = (mValue ? false : true); +} + +nsSingletonEnumerator::~nsSingletonEnumerator() +{ +} + +NS_IMPL_ISUPPORTS(nsSingletonEnumerator, nsISimpleEnumerator) + +NS_IMETHODIMP +nsSingletonEnumerator::HasMoreElements(bool* aResult) +{ + NS_PRECONDITION(aResult != 0, "null ptr"); + if (!aResult) { + return NS_ERROR_NULL_POINTER; + } + + *aResult = !mConsumed; + return NS_OK; +} + + +NS_IMETHODIMP +nsSingletonEnumerator::GetNext(nsISupports** aResult) +{ + NS_PRECONDITION(aResult != 0, "null ptr"); + if (!aResult) { + return NS_ERROR_NULL_POINTER; + } + + if (mConsumed) { + return NS_ERROR_UNEXPECTED; + } + + mConsumed = true; + + *aResult = mValue; + NS_ADDREF(*aResult); + return NS_OK; +} + +nsresult +NS_NewSingletonEnumerator(nsISimpleEnumerator** aResult, + nsISupports* aSingleton) +{ + RefPtr<nsSingletonEnumerator> enumer = new nsSingletonEnumerator(aSingleton); + enumer.forget(aResult); + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////////////// + +class nsUnionEnumerator final : public nsISimpleEnumerator +{ +public: + NS_DECL_ISUPPORTS + + // nsISimpleEnumerator methods + NS_IMETHOD HasMoreElements(bool* aResult) override; + NS_IMETHOD GetNext(nsISupports** aResult) override; + + nsUnionEnumerator(nsISimpleEnumerator* aFirstEnumerator, + nsISimpleEnumerator* aSecondEnumerator); + +private: + ~nsUnionEnumerator(); + +protected: + nsCOMPtr<nsISimpleEnumerator> mFirstEnumerator, mSecondEnumerator; + bool mConsumed; + bool mAtSecond; +}; + +nsUnionEnumerator::nsUnionEnumerator(nsISimpleEnumerator* aFirstEnumerator, + nsISimpleEnumerator* aSecondEnumerator) + : mFirstEnumerator(aFirstEnumerator) + , mSecondEnumerator(aSecondEnumerator) + , mConsumed(false) + , mAtSecond(false) +{ +} + +nsUnionEnumerator::~nsUnionEnumerator() +{ +} + +NS_IMPL_ISUPPORTS(nsUnionEnumerator, nsISimpleEnumerator) + +NS_IMETHODIMP +nsUnionEnumerator::HasMoreElements(bool* aResult) +{ + NS_PRECONDITION(aResult != 0, "null ptr"); + if (!aResult) { + return NS_ERROR_NULL_POINTER; + } + + nsresult rv; + + if (mConsumed) { + *aResult = false; + return NS_OK; + } + + if (!mAtSecond) { + rv = mFirstEnumerator->HasMoreElements(aResult); + if (NS_FAILED(rv)) { + return rv; + } + + if (*aResult) { + return NS_OK; + } + + mAtSecond = true; + } + + rv = mSecondEnumerator->HasMoreElements(aResult); + if (NS_FAILED(rv)) { + return rv; + } + + if (*aResult) { + return NS_OK; + } + + *aResult = false; + mConsumed = true; + return NS_OK; +} + +NS_IMETHODIMP +nsUnionEnumerator::GetNext(nsISupports** aResult) +{ + NS_PRECONDITION(aResult != 0, "null ptr"); + if (!aResult) { + return NS_ERROR_NULL_POINTER; + } + + if (mConsumed) { + return NS_ERROR_UNEXPECTED; + } + + if (!mAtSecond) { + return mFirstEnumerator->GetNext(aResult); + } + + return mSecondEnumerator->GetNext(aResult); +} + +nsresult +NS_NewUnionEnumerator(nsISimpleEnumerator** aResult, + nsISimpleEnumerator* aFirstEnumerator, + nsISimpleEnumerator* aSecondEnumerator) +{ + *aResult = nullptr; + if (!aFirstEnumerator) { + *aResult = aSecondEnumerator; + } else if (!aSecondEnumerator) { + *aResult = aFirstEnumerator; + } else { + nsUnionEnumerator* enumer = new nsUnionEnumerator(aFirstEnumerator, + aSecondEnumerator); + if (!enumer) { + return NS_ERROR_OUT_OF_MEMORY; + } + *aResult = enumer; + } + NS_ADDREF(*aResult); + return NS_OK; +} |