1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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 Mozilla.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications.
19 : * Portions created by the Initial Developer are Copyright (C) 2001
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Scott Collins <scc@mozilla.org> (original author)
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either of the GNU General Public License Version 2 or later (the "GPL"),
27 : * or 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 : #ifndef nsStringIterator_h___
40 : #define nsStringIterator_h___
41 :
42 : #ifndef nsCharTraits_h___
43 : #include "nsCharTraits.h"
44 : #endif
45 :
46 : #ifndef nsAlgorithm_h___
47 : #include "nsAlgorithm.h"
48 : #endif
49 :
50 : #ifndef nsDebug_h___
51 : #include "nsDebug.h"
52 : #endif
53 :
54 : /**
55 : * @see nsTAString
56 : */
57 :
58 : template <class CharT>
59 : class nsReadingIterator
60 : {
61 : public:
62 : typedef nsReadingIterator<CharT> self_type;
63 : typedef ptrdiff_t difference_type;
64 : typedef CharT value_type;
65 : typedef const CharT* pointer;
66 : typedef const CharT& reference;
67 :
68 : private:
69 : friend class nsAString;
70 : friend class nsACString;
71 :
72 : // unfortunately, the API for nsReadingIterator requires that the
73 : // iterator know its start and end positions. this was needed when
74 : // we supported multi-fragment strings, but now it is really just
75 : // extra baggage. we should remove mStart and mEnd at some point.
76 :
77 : const CharT* mStart;
78 : const CharT* mEnd;
79 : const CharT* mPosition;
80 :
81 : public:
82 13874043 : nsReadingIterator() { }
83 : // nsReadingIterator( const nsReadingIterator<CharT>& ); // auto-generated copy-constructor OK
84 : // nsReadingIterator<CharT>& operator=( const nsReadingIterator<CharT>& ); // auto-generated copy-assignment operator OK
85 :
86 : inline void normalize_forward() {}
87 : inline void normalize_backward() {}
88 :
89 : pointer
90 0 : start() const
91 : {
92 0 : return mStart;
93 : }
94 :
95 : pointer
96 : end() const
97 : {
98 : return mEnd;
99 : }
100 :
101 : pointer
102 58846671 : get() const
103 : {
104 58846671 : return mPosition;
105 : }
106 :
107 : CharT
108 2743038 : operator*() const
109 : {
110 2743038 : return *get();
111 : }
112 :
113 : #if 0
114 : // An iterator really deserves this, but some compilers (notably IBM VisualAge for OS/2)
115 : // don't like this when |CharT| is a type without members.
116 : pointer
117 : operator->() const
118 : {
119 : return get();
120 : }
121 : #endif
122 :
123 : self_type&
124 8184872 : operator++()
125 : {
126 8184872 : ++mPosition;
127 8184872 : return *this;
128 : }
129 :
130 : self_type
131 116092 : operator++( int )
132 : {
133 116092 : self_type result(*this);
134 116092 : ++mPosition;
135 : return result;
136 : }
137 :
138 : self_type&
139 1403028 : operator--()
140 : {
141 1403028 : --mPosition;
142 1403028 : return *this;
143 : }
144 :
145 : self_type
146 : operator--( int )
147 : {
148 : self_type result(*this);
149 : --mPosition;
150 : return result;
151 : }
152 :
153 : difference_type
154 1691529 : size_forward() const
155 : {
156 1691529 : return mEnd - mPosition;
157 : }
158 :
159 : difference_type
160 0 : size_backward() const
161 : {
162 0 : return mPosition - mStart;
163 : }
164 :
165 : self_type&
166 2778501 : advance( difference_type n )
167 : {
168 2778501 : if (n > 0)
169 : {
170 1499564 : difference_type step = NS_MIN(n, size_forward());
171 :
172 1499564 : NS_ASSERTION(step>0, "can't advance a reading iterator beyond the end of a string");
173 :
174 1499564 : mPosition += step;
175 : }
176 1278937 : else if (n < 0)
177 : {
178 0 : difference_type step = NS_MAX(n, -size_backward());
179 :
180 0 : NS_ASSERTION(step<0, "can't advance (backward) a reading iterator beyond the end of a string");
181 :
182 0 : mPosition += step;
183 : }
184 2778501 : return *this;
185 : }
186 : };
187 :
188 : /**
189 : * @see nsTAString
190 : */
191 :
192 : template <class CharT>
193 : class nsWritingIterator
194 : {
195 : public:
196 : typedef nsWritingIterator<CharT> self_type;
197 : typedef ptrdiff_t difference_type;
198 : typedef CharT value_type;
199 : typedef CharT* pointer;
200 : typedef CharT& reference;
201 :
202 : private:
203 : friend class nsAString;
204 : friend class nsACString;
205 :
206 : // unfortunately, the API for nsWritingIterator requires that the
207 : // iterator know its start and end positions. this was needed when
208 : // we supported multi-fragment strings, but now it is really just
209 : // extra baggage. we should remove mStart and mEnd at some point.
210 :
211 : CharT* mStart;
212 : CharT* mEnd;
213 : CharT* mPosition;
214 :
215 : public:
216 827487 : nsWritingIterator() { }
217 : // nsWritingIterator( const nsWritingIterator<CharT>& ); // auto-generated copy-constructor OK
218 : // nsWritingIterator<CharT>& operator=( const nsWritingIterator<CharT>& ); // auto-generated copy-assignment operator OK
219 :
220 : inline void normalize_forward() {}
221 : inline void normalize_backward() {}
222 :
223 : pointer
224 : start() const
225 : {
226 : return mStart;
227 : }
228 :
229 : pointer
230 : end() const
231 : {
232 : return mEnd;
233 : }
234 :
235 : pointer
236 823599 : get() const
237 : {
238 823599 : return mPosition;
239 : }
240 :
241 : reference
242 2803 : operator*() const
243 : {
244 2803 : return *get();
245 : }
246 :
247 : #if 0
248 : // An iterator really deserves this, but some compilers (notably IBM VisualAge for OS/2)
249 : // don't like this when |CharT| is a type without members.
250 : pointer
251 : operator->() const
252 : {
253 : return get();
254 : }
255 : #endif
256 :
257 : self_type&
258 0 : operator++()
259 : {
260 0 : ++mPosition;
261 0 : return *this;
262 : }
263 :
264 : self_type
265 180 : operator++( int )
266 : {
267 180 : self_type result(*this);
268 180 : ++mPosition;
269 : return result;
270 : }
271 :
272 : self_type&
273 2443 : operator--()
274 : {
275 2443 : --mPosition;
276 2443 : return *this;
277 : }
278 :
279 : self_type
280 : operator--( int )
281 : {
282 : self_type result(*this);
283 : --mPosition;
284 : return result;
285 : }
286 :
287 : difference_type
288 12357 : size_forward() const
289 : {
290 12357 : return mEnd - mPosition;
291 : }
292 :
293 : difference_type
294 0 : size_backward() const
295 : {
296 0 : return mPosition - mStart;
297 : }
298 :
299 : self_type&
300 597911 : advance( difference_type n )
301 : {
302 597911 : if (n > 0)
303 : {
304 4129 : difference_type step = NS_MIN(n, size_forward());
305 :
306 4129 : NS_ASSERTION(step>0, "can't advance a writing iterator beyond the end of a string");
307 :
308 4129 : mPosition += step;
309 : }
310 593782 : else if (n < 0)
311 : {
312 0 : difference_type step = NS_MAX(n, -size_backward());
313 :
314 0 : NS_ASSERTION(step<0, "can't advance (backward) a writing iterator beyond the end of a string");
315 :
316 0 : mPosition += step;
317 : }
318 597911 : return *this;
319 : }
320 :
321 : void
322 4018 : write( const value_type* s, PRUint32 n )
323 : {
324 4018 : NS_ASSERTION(size_forward() > 0, "You can't |write| into an |nsWritingIterator| with no space!");
325 :
326 4018 : nsCharTraits<value_type>::move(mPosition, s, n);
327 4018 : advance( difference_type(n) );
328 4018 : }
329 : };
330 :
331 : template <class CharT>
332 : inline
333 : bool
334 1980850 : operator==( const nsReadingIterator<CharT>& lhs, const nsReadingIterator<CharT>& rhs )
335 : {
336 1980850 : return lhs.get() == rhs.get();
337 : }
338 :
339 : template <class CharT>
340 : inline
341 : bool
342 8291953 : operator!=( const nsReadingIterator<CharT>& lhs, const nsReadingIterator<CharT>& rhs )
343 : {
344 8291953 : return lhs.get() != rhs.get();
345 : }
346 :
347 :
348 : //
349 : // |nsWritingIterator|s
350 : //
351 :
352 : template <class CharT>
353 : inline
354 : bool
355 : operator==( const nsWritingIterator<CharT>& lhs, const nsWritingIterator<CharT>& rhs )
356 : {
357 : return lhs.get() == rhs.get();
358 : }
359 :
360 : template <class CharT>
361 : inline
362 : bool
363 187 : operator!=( const nsWritingIterator<CharT>& lhs, const nsWritingIterator<CharT>& rhs )
364 : {
365 187 : return lhs.get() != rhs.get();
366 : }
367 :
368 : #endif /* !defined(nsStringIterator_h___) */
|