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 : #ifndef nsStringIterator_h___
8 : #define nsStringIterator_h___
9 :
10 : #include "nsCharTraits.h"
11 : #include "nsAlgorithm.h"
12 : #include "nsDebug.h"
13 :
14 : /**
15 : * @see nsTAString
16 : */
17 :
18 : template <class CharT>
19 : class nsReadingIterator
20 : {
21 : public:
22 : typedef nsReadingIterator<CharT> self_type;
23 : typedef ptrdiff_t difference_type;
24 : typedef size_t size_type;
25 : typedef CharT value_type;
26 : typedef const CharT* pointer;
27 : typedef const CharT& reference;
28 :
29 : private:
30 : friend class mozilla::detail::nsStringRepr;
31 : friend class mozilla::detail::nsCStringRepr;
32 :
33 : // unfortunately, the API for nsReadingIterator requires that the
34 : // iterator know its start and end positions. this was needed when
35 : // we supported multi-fragment strings, but now it is really just
36 : // extra baggage. we should remove mStart and mEnd at some point.
37 :
38 : const CharT* mStart;
39 : const CharT* mEnd;
40 : const CharT* mPosition;
41 :
42 : public:
43 126155 : nsReadingIterator()
44 : {
45 126155 : }
46 : // nsReadingIterator( const nsReadingIterator<CharT>& ); // auto-generated copy-constructor OK
47 : // nsReadingIterator<CharT>& operator=( const nsReadingIterator<CharT>& ); // auto-generated copy-assignment operator OK
48 :
49 453375 : pointer get() const
50 : {
51 453375 : return mPosition;
52 : }
53 :
54 74348 : CharT operator*() const
55 : {
56 74348 : return *get();
57 : }
58 :
59 34560 : self_type& operator++()
60 : {
61 34560 : ++mPosition;
62 34560 : return *this;
63 : }
64 :
65 27044 : self_type operator++(int)
66 : {
67 27044 : self_type result(*this);
68 27044 : ++mPosition;
69 27044 : return result;
70 : }
71 :
72 12318 : self_type& operator--()
73 : {
74 12318 : --mPosition;
75 12318 : return *this;
76 : }
77 :
78 0 : self_type operator--(int)
79 : {
80 0 : self_type result(*this);
81 0 : --mPosition;
82 0 : return result;
83 : }
84 :
85 10530 : self_type& advance(difference_type aN)
86 : {
87 10530 : if (aN > 0) {
88 5483 : difference_type step = XPCOM_MIN(aN, mEnd - mPosition);
89 :
90 5483 : NS_ASSERTION(step > 0,
91 : "can't advance a reading iterator beyond the end of a string");
92 :
93 5483 : mPosition += step;
94 5047 : } else if (aN < 0) {
95 0 : difference_type step = XPCOM_MAX(aN, -(mPosition - mStart));
96 :
97 0 : NS_ASSERTION(step < 0,
98 : "can't advance (backward) a reading iterator beyond the end of a string");
99 :
100 0 : mPosition += step;
101 : }
102 10530 : return *this;
103 : }
104 :
105 : // We return an unsigned type here (with corresponding assert) rather than
106 : // the more usual difference_type because we want to make this class go
107 : // away in favor of mozilla::RangedPtr. Since RangedPtr has the same
108 : // requirement we are enforcing here, the transition ought to be much
109 : // smoother.
110 138 : size_type operator-(const self_type& aOther) const
111 : {
112 138 : MOZ_ASSERT(mPosition >= aOther.mPosition);
113 138 : return mPosition - aOther.mPosition;
114 : }
115 : };
116 :
117 : /**
118 : * @see nsTAString
119 : */
120 :
121 : template <class CharT>
122 : class nsWritingIterator
123 : {
124 : public:
125 : typedef nsWritingIterator<CharT> self_type;
126 : typedef ptrdiff_t difference_type;
127 : typedef size_t size_type;
128 : typedef CharT value_type;
129 : typedef CharT* pointer;
130 : typedef CharT& reference;
131 :
132 : private:
133 : friend class nsAString;
134 : friend class nsACString;
135 :
136 : // unfortunately, the API for nsWritingIterator requires that the
137 : // iterator know its start and end positions. this was needed when
138 : // we supported multi-fragment strings, but now it is really just
139 : // extra baggage. we should remove mStart and mEnd at some point.
140 :
141 : CharT* mStart;
142 : CharT* mEnd;
143 : CharT* mPosition;
144 :
145 : public:
146 27497 : nsWritingIterator()
147 : {
148 27497 : }
149 : // nsWritingIterator( const nsWritingIterator<CharT>& ); // auto-generated copy-constructor OK
150 : // nsWritingIterator<CharT>& operator=( const nsWritingIterator<CharT>& ); // auto-generated copy-assignment operator OK
151 :
152 1691484 : pointer get() const
153 : {
154 1691484 : return mPosition;
155 : }
156 :
157 998430 : reference operator*() const
158 : {
159 998430 : return *get();
160 : }
161 :
162 0 : self_type& operator++()
163 : {
164 0 : ++mPosition;
165 0 : return *this;
166 : }
167 :
168 332795 : self_type operator++(int)
169 : {
170 332795 : self_type result(*this);
171 332795 : ++mPosition;
172 332795 : return result;
173 : }
174 :
175 27 : self_type& operator--()
176 : {
177 27 : --mPosition;
178 27 : return *this;
179 : }
180 :
181 : self_type operator--(int)
182 : {
183 : self_type result(*this);
184 : --mPosition;
185 : return result;
186 : }
187 :
188 5460 : self_type& advance(difference_type aN)
189 : {
190 5460 : if (aN > 0) {
191 11 : difference_type step = XPCOM_MIN(aN, mEnd - mPosition);
192 :
193 11 : NS_ASSERTION(step > 0,
194 : "can't advance a writing iterator beyond the end of a string");
195 :
196 11 : mPosition += step;
197 5449 : } else if (aN < 0) {
198 0 : difference_type step = XPCOM_MAX(aN, -(mPosition - mStart));
199 :
200 0 : NS_ASSERTION(step < 0,
201 : "can't advance (backward) a writing iterator beyond the end of a string");
202 :
203 0 : mPosition += step;
204 : }
205 5460 : return *this;
206 : }
207 :
208 : // We return an unsigned type here (with corresponding assert) rather than
209 : // the more usual difference_type because we want to make this class go
210 : // away in favor of mozilla::RangedPtr. Since RangedPtr has the same
211 : // requirement we are enforcing here, the transition ought to be much
212 : // smoother.
213 9 : size_type operator-(const self_type& aOther) const
214 : {
215 9 : MOZ_ASSERT(mPosition >= aOther.mPosition);
216 9 : return mPosition - aOther.mPosition;
217 : }
218 : };
219 :
220 : template <class CharT>
221 : struct nsCharSinkTraits<nsWritingIterator<CharT>>
222 : {
223 : static void
224 1 : write(nsWritingIterator<CharT>& aIter, const CharT* aStr, uint32_t aN)
225 : {
226 1 : nsCharTraits<CharT>::move(aIter.get(), aStr, aN);
227 1 : aIter.advance(aN);
228 1 : }
229 : };
230 :
231 : template <class CharT>
232 : inline bool
233 5891 : operator==(const nsReadingIterator<CharT>& aLhs,
234 : const nsReadingIterator<CharT>& aRhs)
235 : {
236 5891 : return aLhs.get() == aRhs.get();
237 : }
238 :
239 : template <class CharT>
240 : inline bool
241 82422 : operator!=(const nsReadingIterator<CharT>& aLhs,
242 : const nsReadingIterator<CharT>& aRhs)
243 : {
244 82422 : return aLhs.get() != aRhs.get();
245 : }
246 :
247 :
248 : //
249 : // |nsWritingIterator|s
250 : //
251 :
252 : template <class CharT>
253 : inline bool
254 : operator==(const nsWritingIterator<CharT>& aLhs,
255 : const nsWritingIterator<CharT>& aRhs)
256 : {
257 : return aLhs.get() == aRhs.get();
258 : }
259 :
260 : template <class CharT>
261 : inline bool
262 336437 : operator!=(const nsWritingIterator<CharT>& aLhs,
263 : const nsWritingIterator<CharT>& aRhs)
264 : {
265 336437 : return aLhs.get() != aRhs.get();
266 : }
267 :
268 : #endif /* !defined(nsStringIterator_h___) */
|