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 :
8 : #include "nsStringEnumerator.h"
9 : #include "nsISimpleEnumerator.h"
10 : #include "nsSupportsPrimitives.h"
11 : #include "mozilla/Attributes.h"
12 : #include "nsTArray.h"
13 :
14 : //
15 : // nsStringEnumerator
16 : //
17 :
18 : class nsStringEnumerator final
19 : : public nsIStringEnumerator
20 : , public nsIUTF8StringEnumerator
21 : , public nsISimpleEnumerator
22 : {
23 : public:
24 0 : nsStringEnumerator(const nsTArray<nsString>* aArray, bool aOwnsArray)
25 0 : : mArray(aArray)
26 : , mIndex(0)
27 : , mOwnsArray(aOwnsArray)
28 0 : , mIsUnicode(true)
29 0 : {}
30 :
31 5 : nsStringEnumerator(const nsTArray<nsCString>* aArray, bool aOwnsArray)
32 5 : : mCArray(aArray)
33 : , mIndex(0)
34 : , mOwnsArray(aOwnsArray)
35 5 : , mIsUnicode(false)
36 5 : {}
37 :
38 0 : nsStringEnumerator(const nsTArray<nsString>* aArray, nsISupports* aOwner)
39 0 : : mArray(aArray)
40 : , mIndex(0)
41 : , mOwner(aOwner)
42 : , mOwnsArray(false)
43 0 : , mIsUnicode(true)
44 0 : {}
45 :
46 0 : nsStringEnumerator(const nsTArray<nsCString>* aArray, nsISupports* aOwner)
47 0 : : mCArray(aArray)
48 : , mIndex(0)
49 : , mOwner(aOwner)
50 : , mOwnsArray(false)
51 0 : , mIsUnicode(false)
52 0 : {}
53 :
54 : NS_DECL_ISUPPORTS
55 : NS_DECL_NSIUTF8STRINGENUMERATOR
56 :
57 : // have to declare nsIStringEnumerator manually, because of
58 : // overlapping method names
59 : NS_IMETHOD GetNext(nsAString& aResult) override;
60 : NS_DECL_NSISIMPLEENUMERATOR
61 :
62 : private:
63 5 : ~nsStringEnumerator()
64 10 : {
65 5 : if (mOwnsArray) {
66 : // const-casting is safe here, because the NS_New*
67 : // constructors make sure mOwnsArray is consistent with
68 : // the constness of the objects
69 5 : if (mIsUnicode) {
70 0 : delete const_cast<nsTArray<nsString>*>(mArray);
71 : } else {
72 5 : delete const_cast<nsTArray<nsCString>*>(mCArray);
73 : }
74 : }
75 5 : }
76 :
77 : union
78 : {
79 : const nsTArray<nsString>* mArray;
80 : const nsTArray<nsCString>* mCArray;
81 : };
82 :
83 2317 : inline uint32_t Count()
84 : {
85 2317 : return mIsUnicode ? mArray->Length() : mCArray->Length();
86 : }
87 :
88 : uint32_t mIndex;
89 :
90 : // the owner allows us to hold a strong reference to the object
91 : // that owns the array. Having a non-null value in mOwner implies
92 : // that mOwnsArray is false, because we rely on the real owner
93 : // to release the array
94 : nsCOMPtr<nsISupports> mOwner;
95 : bool mOwnsArray;
96 : bool mIsUnicode;
97 : };
98 :
99 48 : NS_IMPL_ISUPPORTS(nsStringEnumerator,
100 : nsIStringEnumerator,
101 : nsIUTF8StringEnumerator,
102 : nsISimpleEnumerator)
103 :
104 : NS_IMETHODIMP
105 2316 : nsStringEnumerator::HasMore(bool* aResult)
106 : {
107 2316 : *aResult = mIndex < Count();
108 2316 : return NS_OK;
109 : }
110 :
111 : NS_IMETHODIMP
112 2313 : nsStringEnumerator::HasMoreElements(bool* aResult)
113 : {
114 2313 : return HasMore(aResult);
115 : }
116 :
117 : NS_IMETHODIMP
118 2310 : nsStringEnumerator::GetNext(nsISupports** aResult)
119 : {
120 2310 : if (mIsUnicode) {
121 0 : nsSupportsString* stringImpl = new nsSupportsString();
122 0 : if (!stringImpl) {
123 0 : return NS_ERROR_OUT_OF_MEMORY;
124 : }
125 :
126 0 : stringImpl->SetData(mArray->ElementAt(mIndex++));
127 0 : *aResult = stringImpl;
128 : } else {
129 2310 : nsSupportsCString* cstringImpl = new nsSupportsCString();
130 2310 : if (!cstringImpl) {
131 0 : return NS_ERROR_OUT_OF_MEMORY;
132 : }
133 :
134 2310 : cstringImpl->SetData(mCArray->ElementAt(mIndex++));
135 2310 : *aResult = cstringImpl;
136 : }
137 2310 : NS_ADDREF(*aResult);
138 2310 : return NS_OK;
139 : }
140 :
141 : NS_IMETHODIMP
142 0 : nsStringEnumerator::GetNext(nsAString& aResult)
143 : {
144 0 : if (NS_WARN_IF(mIndex >= Count())) {
145 0 : return NS_ERROR_UNEXPECTED;
146 : }
147 :
148 0 : if (mIsUnicode) {
149 0 : aResult = mArray->ElementAt(mIndex++);
150 : } else {
151 0 : CopyUTF8toUTF16(mCArray->ElementAt(mIndex++), aResult);
152 : }
153 :
154 0 : return NS_OK;
155 : }
156 :
157 : NS_IMETHODIMP
158 1 : nsStringEnumerator::GetNext(nsACString& aResult)
159 : {
160 1 : if (NS_WARN_IF(mIndex >= Count())) {
161 0 : return NS_ERROR_UNEXPECTED;
162 : }
163 :
164 1 : if (mIsUnicode) {
165 0 : CopyUTF16toUTF8(mArray->ElementAt(mIndex++), aResult);
166 : } else {
167 1 : aResult = mCArray->ElementAt(mIndex++);
168 : }
169 :
170 1 : return NS_OK;
171 : }
172 :
173 : template<class T>
174 : static inline nsresult
175 5 : StringEnumeratorTail(T** aResult)
176 : {
177 5 : if (!*aResult) {
178 0 : return NS_ERROR_OUT_OF_MEMORY;
179 : }
180 5 : NS_ADDREF(*aResult);
181 5 : return NS_OK;
182 : }
183 :
184 : //
185 : // constructors
186 : //
187 :
188 : nsresult
189 0 : NS_NewStringEnumerator(nsIStringEnumerator** aResult,
190 : const nsTArray<nsString>* aArray, nsISupports* aOwner)
191 : {
192 0 : if (NS_WARN_IF(!aResult) || NS_WARN_IF(!aArray)) {
193 0 : return NS_ERROR_INVALID_ARG;
194 : }
195 :
196 0 : *aResult = new nsStringEnumerator(aArray, aOwner);
197 0 : return StringEnumeratorTail(aResult);
198 : }
199 :
200 :
201 : nsresult
202 0 : NS_NewUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult,
203 : const nsTArray<nsCString>* aArray,
204 : nsISupports* aOwner)
205 : {
206 0 : if (NS_WARN_IF(!aResult) || NS_WARN_IF(!aArray)) {
207 0 : return NS_ERROR_INVALID_ARG;
208 : }
209 :
210 0 : *aResult = new nsStringEnumerator(aArray, aOwner);
211 0 : return StringEnumeratorTail(aResult);
212 : }
213 :
214 : nsresult
215 0 : NS_NewAdoptingStringEnumerator(nsIStringEnumerator** aResult,
216 : nsTArray<nsString>* aArray)
217 : {
218 0 : if (NS_WARN_IF(!aResult) || NS_WARN_IF(!aArray)) {
219 0 : return NS_ERROR_INVALID_ARG;
220 : }
221 :
222 0 : *aResult = new nsStringEnumerator(aArray, true);
223 0 : return StringEnumeratorTail(aResult);
224 : }
225 :
226 : nsresult
227 5 : NS_NewAdoptingUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult,
228 : nsTArray<nsCString>* aArray)
229 : {
230 5 : if (NS_WARN_IF(!aResult) || NS_WARN_IF(!aArray)) {
231 0 : return NS_ERROR_INVALID_ARG;
232 : }
233 :
234 5 : *aResult = new nsStringEnumerator(aArray, true);
235 5 : return StringEnumeratorTail(aResult);
236 : }
237 :
238 : // const ones internally just forward to the non-const equivalents
239 : nsresult
240 0 : NS_NewStringEnumerator(nsIStringEnumerator** aResult,
241 : const nsTArray<nsString>* aArray)
242 : {
243 0 : if (NS_WARN_IF(!aResult) || NS_WARN_IF(!aArray)) {
244 0 : return NS_ERROR_INVALID_ARG;
245 : }
246 :
247 0 : *aResult = new nsStringEnumerator(aArray, false);
248 0 : return StringEnumeratorTail(aResult);
249 : }
250 :
251 : nsresult
252 0 : NS_NewUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult,
253 : const nsTArray<nsCString>* aArray)
254 : {
255 0 : if (NS_WARN_IF(!aResult) || NS_WARN_IF(!aArray)) {
256 0 : return NS_ERROR_INVALID_ARG;
257 : }
258 :
259 0 : *aResult = new nsStringEnumerator(aArray, false);
260 0 : return StringEnumeratorTail(aResult);
261 : }
262 :
|