summaryrefslogtreecommitdiff
path: root/xpcom/glue/nsEnumeratorUtils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xpcom/glue/nsEnumeratorUtils.cpp')
-rw-r--r--xpcom/glue/nsEnumeratorUtils.cpp291
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;
+}