Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "mozilla/Attributes.h"
8 #include "nsEnumeratorUtils.h"
10 #include "nsISimpleEnumerator.h"
11 #include "nsIStringEnumerator.h"
13 #include "nsCOMPtr.h"
15 class EmptyEnumeratorImpl : public nsISimpleEnumerator,
16 public nsIUTF8StringEnumerator,
17 public nsIStringEnumerator
18 {
19 public:
20 EmptyEnumeratorImpl() {}
21 // nsISupports interface
22 NS_DECL_ISUPPORTS_INHERITED // not really inherited, but no mRefCnt
24 // nsISimpleEnumerator
25 NS_DECL_NSISIMPLEENUMERATOR
26 NS_DECL_NSIUTF8STRINGENUMERATOR
27 // can't use NS_DECL_NSISTRINGENUMERATOR because they share the
28 // HasMore() signature
29 NS_IMETHOD GetNext(nsAString& aResult);
31 static EmptyEnumeratorImpl* GetInstance() {
32 static const EmptyEnumeratorImpl kInstance;
33 return const_cast<EmptyEnumeratorImpl*>(&kInstance);
34 }
35 };
37 // nsISupports interface
38 NS_IMETHODIMP_(MozExternalRefCountType) EmptyEnumeratorImpl::AddRef(void)
39 {
40 return 2;
41 }
43 NS_IMETHODIMP_(MozExternalRefCountType) EmptyEnumeratorImpl::Release(void)
44 {
45 return 1;
46 }
48 NS_IMPL_QUERY_INTERFACE(EmptyEnumeratorImpl, nsISimpleEnumerator,
49 nsIUTF8StringEnumerator, nsIStringEnumerator)
51 // nsISimpleEnumerator interface
52 NS_IMETHODIMP EmptyEnumeratorImpl::HasMoreElements(bool* aResult)
53 {
54 *aResult = false;
55 return NS_OK;
56 }
58 NS_IMETHODIMP EmptyEnumeratorImpl::HasMore(bool* aResult)
59 {
60 *aResult = false;
61 return NS_OK;
62 }
64 NS_IMETHODIMP EmptyEnumeratorImpl::GetNext(nsISupports** aResult)
65 {
66 return NS_ERROR_UNEXPECTED;
67 }
69 NS_IMETHODIMP EmptyEnumeratorImpl::GetNext(nsACString& aResult)
70 {
71 return NS_ERROR_UNEXPECTED;
72 }
74 NS_IMETHODIMP EmptyEnumeratorImpl::GetNext(nsAString& aResult)
75 {
76 return NS_ERROR_UNEXPECTED;
77 }
79 nsresult
80 NS_NewEmptyEnumerator(nsISimpleEnumerator** aResult)
81 {
82 *aResult = EmptyEnumeratorImpl::GetInstance();
83 return NS_OK;
84 }
86 ////////////////////////////////////////////////////////////////////////////////
88 class nsSingletonEnumerator MOZ_FINAL : public nsISimpleEnumerator
89 {
90 public:
91 NS_DECL_ISUPPORTS
93 // nsISimpleEnumerator methods
94 NS_IMETHOD HasMoreElements(bool* aResult);
95 NS_IMETHOD GetNext(nsISupports** aResult);
97 nsSingletonEnumerator(nsISupports* aValue);
99 private:
100 ~nsSingletonEnumerator();
102 protected:
103 nsISupports* mValue;
104 bool mConsumed;
105 };
107 nsSingletonEnumerator::nsSingletonEnumerator(nsISupports* aValue)
108 : mValue(aValue)
109 {
110 NS_IF_ADDREF(mValue);
111 mConsumed = (mValue ? false : true);
112 }
114 nsSingletonEnumerator::~nsSingletonEnumerator()
115 {
116 NS_IF_RELEASE(mValue);
117 }
119 NS_IMPL_ISUPPORTS(nsSingletonEnumerator, nsISimpleEnumerator)
121 NS_IMETHODIMP
122 nsSingletonEnumerator::HasMoreElements(bool* aResult)
123 {
124 NS_PRECONDITION(aResult != 0, "null ptr");
125 if (! aResult)
126 return NS_ERROR_NULL_POINTER;
128 *aResult = !mConsumed;
129 return NS_OK;
130 }
133 NS_IMETHODIMP
134 nsSingletonEnumerator::GetNext(nsISupports** aResult)
135 {
136 NS_PRECONDITION(aResult != 0, "null ptr");
137 if (! aResult)
138 return NS_ERROR_NULL_POINTER;
140 if (mConsumed)
141 return NS_ERROR_UNEXPECTED;
143 mConsumed = true;
145 *aResult = mValue;
146 NS_ADDREF(*aResult);
147 return NS_OK;
148 }
150 nsresult
151 NS_NewSingletonEnumerator(nsISimpleEnumerator* *result,
152 nsISupports* singleton)
153 {
154 nsSingletonEnumerator* enumer = new nsSingletonEnumerator(singleton);
155 if (enumer == nullptr)
156 return NS_ERROR_OUT_OF_MEMORY;
157 *result = enumer;
158 NS_ADDREF(*result);
159 return NS_OK;
160 }
162 ////////////////////////////////////////////////////////////////////////////////
164 class nsUnionEnumerator MOZ_FINAL : public nsISimpleEnumerator
165 {
166 public:
167 NS_DECL_ISUPPORTS
169 // nsISimpleEnumerator methods
170 NS_IMETHOD HasMoreElements(bool* aResult);
171 NS_IMETHOD GetNext(nsISupports** aResult);
173 nsUnionEnumerator(nsISimpleEnumerator* firstEnumerator,
174 nsISimpleEnumerator* secondEnumerator);
176 private:
177 ~nsUnionEnumerator();
179 protected:
180 nsCOMPtr<nsISimpleEnumerator> mFirstEnumerator, mSecondEnumerator;
181 bool mConsumed;
182 bool mAtSecond;
183 };
185 nsUnionEnumerator::nsUnionEnumerator(nsISimpleEnumerator* firstEnumerator,
186 nsISimpleEnumerator* secondEnumerator)
187 : mFirstEnumerator(firstEnumerator),
188 mSecondEnumerator(secondEnumerator),
189 mConsumed(false), mAtSecond(false)
190 {
191 }
193 nsUnionEnumerator::~nsUnionEnumerator()
194 {
195 }
197 NS_IMPL_ISUPPORTS(nsUnionEnumerator, nsISimpleEnumerator)
199 NS_IMETHODIMP
200 nsUnionEnumerator::HasMoreElements(bool* aResult)
201 {
202 NS_PRECONDITION(aResult != 0, "null ptr");
203 if (! aResult)
204 return NS_ERROR_NULL_POINTER;
206 nsresult rv;
208 if (mConsumed) {
209 *aResult = false;
210 return NS_OK;
211 }
213 if (! mAtSecond) {
214 rv = mFirstEnumerator->HasMoreElements(aResult);
215 if (NS_FAILED(rv)) return rv;
217 if (*aResult)
218 return NS_OK;
220 mAtSecond = true;
221 }
223 rv = mSecondEnumerator->HasMoreElements(aResult);
224 if (NS_FAILED(rv)) return rv;
226 if (*aResult)
227 return NS_OK;
229 *aResult = false;
230 mConsumed = true;
231 return NS_OK;
232 }
234 NS_IMETHODIMP
235 nsUnionEnumerator::GetNext(nsISupports** aResult)
236 {
237 NS_PRECONDITION(aResult != 0, "null ptr");
238 if (! aResult)
239 return NS_ERROR_NULL_POINTER;
241 if (mConsumed)
242 return NS_ERROR_UNEXPECTED;
244 if (! mAtSecond)
245 return mFirstEnumerator->GetNext(aResult);
247 return mSecondEnumerator->GetNext(aResult);
248 }
250 nsresult
251 NS_NewUnionEnumerator(nsISimpleEnumerator* *result,
252 nsISimpleEnumerator* firstEnumerator,
253 nsISimpleEnumerator* secondEnumerator)
254 {
255 *result = nullptr;
256 if (! firstEnumerator) {
257 *result = secondEnumerator;
258 } else if (! secondEnumerator) {
259 *result = firstEnumerator;
260 } else {
261 nsUnionEnumerator* enumer = new nsUnionEnumerator(firstEnumerator, secondEnumerator);
262 if (enumer == nullptr)
263 return NS_ERROR_OUT_OF_MEMORY;
264 *result = enumer;
265 }
266 NS_ADDREF(*result);
267 return NS_OK;
268 }