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