1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is String Enumerator.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corp.
19 : * Portions created by the Initial Developer are Copyright (C) 2003
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Alec Flett <alecf@netscape.com>
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 :
40 : #include "nsStringEnumerator.h"
41 : #include "prtypes.h"
42 : #include "nsCRT.h"
43 : #include "nsString.h"
44 : #include "nsReadableUtils.h"
45 : #include "nsISimpleEnumerator.h"
46 : #include "nsSupportsPrimitives.h"
47 :
48 : //
49 : // nsStringEnumerator
50 : //
51 :
52 : class nsStringEnumerator : public nsIStringEnumerator,
53 : public nsIUTF8StringEnumerator,
54 : public nsISimpleEnumerator
55 : {
56 : public:
57 0 : nsStringEnumerator(const nsTArray<nsString>* aArray, bool aOwnsArray) :
58 0 : mArray(aArray), mIndex(0), mOwnsArray(aOwnsArray), mIsUnicode(true)
59 0 : {}
60 :
61 2422 : nsStringEnumerator(const nsTArray<nsCString>* aArray, bool aOwnsArray) :
62 2422 : mCArray(aArray), mIndex(0), mOwnsArray(aOwnsArray), mIsUnicode(false)
63 2422 : {}
64 :
65 0 : nsStringEnumerator(const nsTArray<nsString>* aArray, nsISupports* aOwner) :
66 0 : mArray(aArray), mIndex(0), mOwner(aOwner), mOwnsArray(false), mIsUnicode(true)
67 0 : {}
68 :
69 3 : nsStringEnumerator(const nsTArray<nsCString>* aArray, nsISupports* aOwner) :
70 3 : mCArray(aArray), mIndex(0), mOwner(aOwner), mOwnsArray(false), mIsUnicode(false)
71 3 : {}
72 :
73 : NS_DECL_ISUPPORTS
74 : NS_DECL_NSIUTF8STRINGENUMERATOR
75 :
76 : // have to declare nsIStringEnumerator manually, because of
77 : // overlapping method names
78 : NS_IMETHOD GetNext(nsAString& aResult);
79 : NS_DECL_NSISIMPLEENUMERATOR
80 :
81 : private:
82 4850 : ~nsStringEnumerator() {
83 2425 : if (mOwnsArray) {
84 : // const-casting is safe here, because the NS_New*
85 : // constructors make sure mOwnsArray is consistent with
86 : // the constness of the objects
87 2422 : if (mIsUnicode)
88 0 : delete const_cast<nsTArray<nsString>*>(mArray);
89 : else
90 2422 : delete const_cast<nsTArray<nsCString>*>(mCArray);
91 : }
92 2425 : }
93 :
94 : union {
95 : const nsTArray<nsString>* mArray;
96 : const nsTArray<nsCString>* mCArray;
97 : };
98 :
99 8993 : inline PRUint32 Count() {
100 8993 : return mIsUnicode ? mArray->Length() : mCArray->Length();
101 : }
102 :
103 : PRUint32 mIndex;
104 :
105 : // the owner allows us to hold a strong reference to the object
106 : // that owns the array. Having a non-null value in mOwner implies
107 : // that mOwnsArray is false, because we rely on the real owner
108 : // to release the array
109 : nsCOMPtr<nsISupports> mOwner;
110 : bool mOwnsArray;
111 : bool mIsUnicode;
112 : };
113 :
114 38087 : NS_IMPL_ISUPPORTS3(nsStringEnumerator,
115 : nsIStringEnumerator,
116 : nsIUTF8StringEnumerator,
117 : nsISimpleEnumerator)
118 :
119 : NS_IMETHODIMP
120 5709 : nsStringEnumerator::HasMore(bool* aResult)
121 : {
122 5709 : NS_ENSURE_ARG_POINTER(aResult);
123 5709 : *aResult = mIndex < Count();
124 5709 : return NS_OK;
125 : }
126 :
127 : NS_IMETHODIMP
128 0 : nsStringEnumerator::HasMoreElements(bool* aResult)
129 : {
130 0 : return HasMore(aResult);
131 : }
132 :
133 : NS_IMETHODIMP
134 0 : nsStringEnumerator::GetNext(nsISupports** aResult)
135 : {
136 0 : if (mIsUnicode) {
137 0 : nsSupportsStringImpl* stringImpl = new nsSupportsStringImpl();
138 0 : if (!stringImpl) return NS_ERROR_OUT_OF_MEMORY;
139 :
140 0 : stringImpl->SetData(mArray->ElementAt(mIndex++));
141 0 : *aResult = stringImpl;
142 : }
143 : else {
144 0 : nsSupportsCStringImpl* cstringImpl = new nsSupportsCStringImpl();
145 0 : if (!cstringImpl) return NS_ERROR_OUT_OF_MEMORY;
146 :
147 0 : cstringImpl->SetData(mCArray->ElementAt(mIndex++));
148 0 : *aResult = cstringImpl;
149 : }
150 0 : NS_ADDREF(*aResult);
151 0 : return NS_OK;
152 : }
153 :
154 : NS_IMETHODIMP
155 0 : nsStringEnumerator::GetNext(nsAString& aResult)
156 : {
157 0 : NS_ENSURE_TRUE(mIndex < Count(), NS_ERROR_UNEXPECTED);
158 :
159 0 : if (mIsUnicode)
160 0 : aResult = mArray->ElementAt(mIndex++);
161 : else
162 0 : CopyUTF8toUTF16(mCArray->ElementAt(mIndex++), aResult);
163 :
164 0 : return NS_OK;
165 : }
166 :
167 : NS_IMETHODIMP
168 3284 : nsStringEnumerator::GetNext(nsACString& aResult)
169 : {
170 3284 : NS_ENSURE_TRUE(mIndex < Count(), NS_ERROR_UNEXPECTED);
171 :
172 3284 : if (mIsUnicode)
173 0 : CopyUTF16toUTF8(mArray->ElementAt(mIndex++), aResult);
174 : else
175 3284 : aResult = mCArray->ElementAt(mIndex++);
176 :
177 3284 : return NS_OK;
178 : }
179 :
180 : template<class T>
181 : static inline nsresult
182 2425 : StringEnumeratorTail(T** aResult NS_INPARAM)
183 : {
184 2425 : if (!*aResult)
185 0 : return NS_ERROR_OUT_OF_MEMORY;
186 2425 : NS_ADDREF(*aResult);
187 2425 : return NS_OK;
188 : }
189 :
190 : //
191 : // constructors
192 : //
193 :
194 : nsresult
195 0 : NS_NewStringEnumerator(nsIStringEnumerator** aResult,
196 : const nsTArray<nsString>* aArray, nsISupports* aOwner)
197 : {
198 0 : NS_ENSURE_ARG_POINTER(aResult);
199 0 : NS_ENSURE_ARG_POINTER(aArray);
200 :
201 0 : *aResult = new nsStringEnumerator(aArray, aOwner);
202 0 : return StringEnumeratorTail(aResult);
203 : }
204 :
205 :
206 : nsresult
207 3 : NS_NewUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult,
208 : const nsTArray<nsCString>* aArray, nsISupports* aOwner)
209 : {
210 3 : NS_ENSURE_ARG_POINTER(aResult);
211 3 : NS_ENSURE_ARG_POINTER(aArray);
212 :
213 3 : *aResult = new nsStringEnumerator(aArray, aOwner);
214 3 : return StringEnumeratorTail(aResult);
215 : }
216 :
217 : nsresult
218 0 : NS_NewAdoptingStringEnumerator(nsIStringEnumerator** aResult,
219 : nsTArray<nsString>* aArray)
220 : {
221 0 : NS_ENSURE_ARG_POINTER(aResult);
222 0 : NS_ENSURE_ARG_POINTER(aArray);
223 :
224 0 : *aResult = new nsStringEnumerator(aArray, true);
225 0 : return StringEnumeratorTail(aResult);
226 : }
227 :
228 : nsresult
229 2422 : NS_NewAdoptingUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult,
230 : nsTArray<nsCString>* aArray)
231 : {
232 2422 : NS_ENSURE_ARG_POINTER(aResult);
233 2422 : NS_ENSURE_ARG_POINTER(aArray);
234 :
235 2422 : *aResult = new nsStringEnumerator(aArray, true);
236 2422 : return StringEnumeratorTail(aResult);
237 : }
238 :
239 : // const ones internally just forward to the non-const equivalents
240 : nsresult
241 0 : NS_NewStringEnumerator(nsIStringEnumerator** aResult,
242 : const nsTArray<nsString>* aArray)
243 : {
244 0 : NS_ENSURE_ARG_POINTER(aResult);
245 0 : NS_ENSURE_ARG_POINTER(aArray);
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 : NS_ENSURE_ARG_POINTER(aResult);
256 0 : NS_ENSURE_ARG_POINTER(aArray);
257 :
258 0 : *aResult = new nsStringEnumerator(aArray, false);
259 0 : return StringEnumeratorTail(aResult);
260 : }
261 :
|