Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "mozilla/Attributes.h"
8 :
9 : #include "nsEnumeratorUtils.h"
10 :
11 : #include "nsISimpleEnumerator.h"
12 : #include "nsIStringEnumerator.h"
13 :
14 : #include "nsCOMPtr.h"
15 : #include "mozilla/RefPtr.h"
16 :
17 : class EmptyEnumeratorImpl
18 : : public nsISimpleEnumerator
19 : , public nsIUTF8StringEnumerator
20 : , public nsIStringEnumerator
21 : {
22 : public:
23 3 : EmptyEnumeratorImpl() {}
24 :
25 : // nsISupports interface
26 : NS_DECL_ISUPPORTS_INHERITED // not really inherited, but no mRefCnt
27 :
28 : // nsISimpleEnumerator
29 : NS_DECL_NSISIMPLEENUMERATOR
30 : NS_DECL_NSIUTF8STRINGENUMERATOR
31 : // can't use NS_DECL_NSISTRINGENUMERATOR because they share the
32 : // HasMore() signature
33 : NS_IMETHOD GetNext(nsAString& aResult) override;
34 :
35 26 : static EmptyEnumeratorImpl* GetInstance()
36 : {
37 26 : static const EmptyEnumeratorImpl kInstance;
38 26 : return const_cast<EmptyEnumeratorImpl*>(&kInstance);
39 : }
40 : };
41 :
42 : // nsISupports interface
43 : NS_IMETHODIMP_(MozExternalRefCountType)
44 37 : EmptyEnumeratorImpl::AddRef(void)
45 : {
46 37 : return 2;
47 : }
48 :
49 : NS_IMETHODIMP_(MozExternalRefCountType)
50 63 : EmptyEnumeratorImpl::Release(void)
51 : {
52 63 : return 1;
53 : }
54 :
55 37 : NS_IMPL_QUERY_INTERFACE(EmptyEnumeratorImpl, nsISimpleEnumerator,
56 : nsIUTF8StringEnumerator, nsIStringEnumerator)
57 :
58 : // nsISimpleEnumerator interface
59 : NS_IMETHODIMP
60 9 : EmptyEnumeratorImpl::HasMoreElements(bool* aResult)
61 : {
62 9 : *aResult = false;
63 9 : return NS_OK;
64 : }
65 :
66 : NS_IMETHODIMP
67 11 : EmptyEnumeratorImpl::HasMore(bool* aResult)
68 : {
69 11 : *aResult = false;
70 11 : return NS_OK;
71 : }
72 :
73 : NS_IMETHODIMP
74 6 : EmptyEnumeratorImpl::GetNext(nsISupports** aResult)
75 : {
76 6 : return NS_ERROR_UNEXPECTED;
77 : }
78 :
79 : NS_IMETHODIMP
80 0 : EmptyEnumeratorImpl::GetNext(nsACString& aResult)
81 : {
82 0 : return NS_ERROR_UNEXPECTED;
83 : }
84 :
85 : NS_IMETHODIMP
86 0 : EmptyEnumeratorImpl::GetNext(nsAString& aResult)
87 : {
88 0 : return NS_ERROR_UNEXPECTED;
89 : }
90 :
91 : nsresult
92 26 : NS_NewEmptyEnumerator(nsISimpleEnumerator** aResult)
93 : {
94 26 : *aResult = EmptyEnumeratorImpl::GetInstance();
95 26 : return NS_OK;
96 : }
97 :
98 : ////////////////////////////////////////////////////////////////////////////////
99 :
100 0 : class nsSingletonEnumerator final : public nsISimpleEnumerator
101 : {
102 : public:
103 : NS_DECL_ISUPPORTS
104 :
105 : // nsISimpleEnumerator methods
106 : NS_IMETHOD HasMoreElements(bool* aResult) override;
107 : NS_IMETHOD GetNext(nsISupports** aResult) override;
108 :
109 : explicit nsSingletonEnumerator(nsISupports* aValue);
110 :
111 : private:
112 : ~nsSingletonEnumerator();
113 :
114 : protected:
115 : nsCOMPtr<nsISupports> mValue;
116 : bool mConsumed;
117 : };
118 :
119 0 : nsSingletonEnumerator::nsSingletonEnumerator(nsISupports* aValue)
120 0 : : mValue(aValue)
121 : {
122 0 : mConsumed = (mValue ? false : true);
123 0 : }
124 :
125 : nsSingletonEnumerator::~nsSingletonEnumerator() = default;
126 :
127 0 : NS_IMPL_ISUPPORTS(nsSingletonEnumerator, nsISimpleEnumerator)
128 :
129 : NS_IMETHODIMP
130 0 : nsSingletonEnumerator::HasMoreElements(bool* aResult)
131 : {
132 0 : NS_PRECONDITION(aResult != 0, "null ptr");
133 0 : if (!aResult) {
134 0 : return NS_ERROR_NULL_POINTER;
135 : }
136 :
137 0 : *aResult = !mConsumed;
138 0 : return NS_OK;
139 : }
140 :
141 :
142 : NS_IMETHODIMP
143 0 : nsSingletonEnumerator::GetNext(nsISupports** aResult)
144 : {
145 0 : NS_PRECONDITION(aResult != 0, "null ptr");
146 0 : if (!aResult) {
147 0 : return NS_ERROR_NULL_POINTER;
148 : }
149 :
150 0 : if (mConsumed) {
151 0 : return NS_ERROR_UNEXPECTED;
152 : }
153 :
154 0 : mConsumed = true;
155 :
156 0 : *aResult = mValue;
157 0 : NS_ADDREF(*aResult);
158 0 : return NS_OK;
159 : }
160 :
161 : nsresult
162 0 : NS_NewSingletonEnumerator(nsISimpleEnumerator** aResult,
163 : nsISupports* aSingleton)
164 : {
165 0 : RefPtr<nsSingletonEnumerator> enumer = new nsSingletonEnumerator(aSingleton);
166 0 : enumer.forget(aResult);
167 0 : return NS_OK;
168 : }
169 :
170 : ////////////////////////////////////////////////////////////////////////////////
171 :
172 1 : class nsUnionEnumerator final : public nsISimpleEnumerator
173 : {
174 : public:
175 : NS_DECL_ISUPPORTS
176 :
177 : // nsISimpleEnumerator methods
178 : NS_IMETHOD HasMoreElements(bool* aResult) override;
179 : NS_IMETHOD GetNext(nsISupports** aResult) override;
180 :
181 : nsUnionEnumerator(nsISimpleEnumerator* aFirstEnumerator,
182 : nsISimpleEnumerator* aSecondEnumerator);
183 :
184 : private:
185 : ~nsUnionEnumerator();
186 :
187 : protected:
188 : nsCOMPtr<nsISimpleEnumerator> mFirstEnumerator, mSecondEnumerator;
189 : bool mConsumed;
190 : bool mAtSecond;
191 : };
192 :
193 1 : nsUnionEnumerator::nsUnionEnumerator(nsISimpleEnumerator* aFirstEnumerator,
194 1 : nsISimpleEnumerator* aSecondEnumerator)
195 : : mFirstEnumerator(aFirstEnumerator)
196 : , mSecondEnumerator(aSecondEnumerator)
197 : , mConsumed(false)
198 1 : , mAtSecond(false)
199 : {
200 1 : }
201 :
202 : nsUnionEnumerator::~nsUnionEnumerator() = default;
203 :
204 12 : NS_IMPL_ISUPPORTS(nsUnionEnumerator, nsISimpleEnumerator)
205 :
206 : NS_IMETHODIMP
207 1 : nsUnionEnumerator::HasMoreElements(bool* aResult)
208 : {
209 1 : NS_PRECONDITION(aResult != 0, "null ptr");
210 1 : if (!aResult) {
211 0 : return NS_ERROR_NULL_POINTER;
212 : }
213 :
214 : nsresult rv;
215 :
216 1 : if (mConsumed) {
217 0 : *aResult = false;
218 0 : return NS_OK;
219 : }
220 :
221 1 : if (!mAtSecond) {
222 1 : rv = mFirstEnumerator->HasMoreElements(aResult);
223 1 : if (NS_FAILED(rv)) {
224 0 : return rv;
225 : }
226 :
227 1 : if (*aResult) {
228 0 : return NS_OK;
229 : }
230 :
231 1 : mAtSecond = true;
232 : }
233 :
234 1 : rv = mSecondEnumerator->HasMoreElements(aResult);
235 1 : if (NS_FAILED(rv)) {
236 0 : return rv;
237 : }
238 :
239 1 : if (*aResult) {
240 0 : return NS_OK;
241 : }
242 :
243 1 : *aResult = false;
244 1 : mConsumed = true;
245 1 : return NS_OK;
246 : }
247 :
248 : NS_IMETHODIMP
249 0 : nsUnionEnumerator::GetNext(nsISupports** aResult)
250 : {
251 0 : NS_PRECONDITION(aResult != 0, "null ptr");
252 0 : if (!aResult) {
253 0 : return NS_ERROR_NULL_POINTER;
254 : }
255 :
256 0 : if (mConsumed) {
257 0 : return NS_ERROR_UNEXPECTED;
258 : }
259 :
260 0 : if (!mAtSecond) {
261 0 : return mFirstEnumerator->GetNext(aResult);
262 : }
263 :
264 0 : return mSecondEnumerator->GetNext(aResult);
265 : }
266 :
267 : nsresult
268 20 : NS_NewUnionEnumerator(nsISimpleEnumerator** aResult,
269 : nsISimpleEnumerator* aFirstEnumerator,
270 : nsISimpleEnumerator* aSecondEnumerator)
271 : {
272 20 : *aResult = nullptr;
273 20 : if (!aFirstEnumerator) {
274 19 : *aResult = aSecondEnumerator;
275 1 : } else if (!aSecondEnumerator) {
276 0 : *aResult = aFirstEnumerator;
277 : } else {
278 : auto* enumer = new nsUnionEnumerator(aFirstEnumerator,
279 1 : aSecondEnumerator);
280 1 : if (!enumer) {
281 0 : return NS_ERROR_OUT_OF_MEMORY;
282 : }
283 1 : *aResult = enumer;
284 : }
285 20 : NS_ADDREF(*aResult);
286 20 : return NS_OK;
287 : }
|