1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4 ******************************************************************************
5 * Copyright (C) 1998-2012, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ******************************************************************************
8 */
9 
10 #include "utypeinfo.h"  // for 'typeid' to work
11 
12 #include "unicode/uchriter.h"
13 #include "unicode/ustring.h"
14 #include "unicode/utf16.h"
15 #include "ustr_imp.h"
16 
17 U_NAMESPACE_BEGIN
18 
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UCharCharacterIterator)19 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UCharCharacterIterator)
20 
21 UCharCharacterIterator::UCharCharacterIterator()
22   : CharacterIterator(),
23   text(0)
24 {
25     // never default construct!
26 }
27 
UCharCharacterIterator(ConstChar16Ptr textPtr,int32_t length)28 UCharCharacterIterator::UCharCharacterIterator(ConstChar16Ptr textPtr,
29                                                int32_t length)
30   : CharacterIterator(textPtr != 0 ? (length>=0 ? length : u_strlen(textPtr)) : 0),
31   text(textPtr)
32 {
33 }
34 
UCharCharacterIterator(ConstChar16Ptr textPtr,int32_t length,int32_t position)35 UCharCharacterIterator::UCharCharacterIterator(ConstChar16Ptr textPtr,
36                                                int32_t length,
37                                                int32_t position)
38   : CharacterIterator(textPtr != 0 ? (length>=0 ? length : u_strlen(textPtr)) : 0, position),
39   text(textPtr)
40 {
41 }
42 
UCharCharacterIterator(ConstChar16Ptr textPtr,int32_t length,int32_t textBegin,int32_t textEnd,int32_t position)43 UCharCharacterIterator::UCharCharacterIterator(ConstChar16Ptr textPtr,
44                                                int32_t length,
45                                                int32_t textBegin,
46                                                int32_t textEnd,
47                                                int32_t position)
48   : CharacterIterator(textPtr != 0 ? (length>=0 ? length : u_strlen(textPtr)) : 0, textBegin, textEnd, position),
49   text(textPtr)
50 {
51 }
52 
UCharCharacterIterator(const UCharCharacterIterator & that)53 UCharCharacterIterator::UCharCharacterIterator(const UCharCharacterIterator& that)
54 : CharacterIterator(that),
55   text(that.text)
56 {
57 }
58 
59 UCharCharacterIterator&
operator =(const UCharCharacterIterator & that)60 UCharCharacterIterator::operator=(const UCharCharacterIterator& that) {
61     CharacterIterator::operator=(that);
62     text = that.text;
63     return *this;
64 }
65 
~UCharCharacterIterator()66 UCharCharacterIterator::~UCharCharacterIterator() {
67 }
68 
69 UBool
operator ==(const ForwardCharacterIterator & that) const70 UCharCharacterIterator::operator==(const ForwardCharacterIterator& that) const {
71     if (this == &that) {
72         return TRUE;
73     }
74     if (typeid(*this) != typeid(that)) {
75         return FALSE;
76     }
77 
78     UCharCharacterIterator&    realThat = (UCharCharacterIterator&)that;
79 
80     return text == realThat.text
81         && textLength == realThat.textLength
82         && pos == realThat.pos
83         && begin == realThat.begin
84         && end == realThat.end;
85 }
86 
87 int32_t
hashCode() const88 UCharCharacterIterator::hashCode() const {
89     return ustr_hashUCharsN(text, textLength) ^ pos ^ begin ^ end;
90 }
91 
92 UCharCharacterIterator*
clone() const93 UCharCharacterIterator::clone() const {
94     return new UCharCharacterIterator(*this);
95 }
96 
97 UChar
first()98 UCharCharacterIterator::first() {
99     pos = begin;
100     if(pos < end) {
101         return text[pos];
102     } else {
103         return DONE;
104     }
105 }
106 
107 UChar
firstPostInc()108 UCharCharacterIterator::firstPostInc() {
109     pos = begin;
110     if(pos < end) {
111         return text[pos++];
112     } else {
113         return DONE;
114     }
115 }
116 
117 UChar
last()118 UCharCharacterIterator::last() {
119     pos = end;
120     if(pos > begin) {
121         return text[--pos];
122     } else {
123         return DONE;
124     }
125 }
126 
127 UChar
setIndex(int32_t position)128 UCharCharacterIterator::setIndex(int32_t position) {
129     if(position < begin) {
130         pos = begin;
131     } else if(position > end) {
132         pos = end;
133     } else {
134         pos = position;
135     }
136     if(pos < end) {
137         return text[pos];
138     } else {
139         return DONE;
140     }
141 }
142 
143 UChar
current() const144 UCharCharacterIterator::current() const {
145     if (pos >= begin && pos < end) {
146         return text[pos];
147     } else {
148         return DONE;
149     }
150 }
151 
152 UChar
next()153 UCharCharacterIterator::next() {
154     if (pos + 1 < end) {
155         return text[++pos];
156     } else {
157         /* make current() return DONE */
158         pos = end;
159         return DONE;
160     }
161 }
162 
163 UChar
nextPostInc()164 UCharCharacterIterator::nextPostInc() {
165     if (pos < end) {
166         return text[pos++];
167     } else {
168         return DONE;
169     }
170 }
171 
172 UBool
hasNext()173 UCharCharacterIterator::hasNext() {
174     return (UBool)(pos < end ? TRUE : FALSE);
175 }
176 
177 UChar
previous()178 UCharCharacterIterator::previous() {
179     if (pos > begin) {
180         return text[--pos];
181     } else {
182         return DONE;
183     }
184 }
185 
186 UBool
hasPrevious()187 UCharCharacterIterator::hasPrevious() {
188     return (UBool)(pos > begin ? TRUE : FALSE);
189 }
190 
191 UChar32
first32()192 UCharCharacterIterator::first32() {
193     pos = begin;
194     if(pos < end) {
195         int32_t i = pos;
196         UChar32 c;
197         U16_NEXT(text, i, end, c);
198         return c;
199     } else {
200         return DONE;
201     }
202 }
203 
204 UChar32
first32PostInc()205 UCharCharacterIterator::first32PostInc() {
206     pos = begin;
207     if(pos < end) {
208         UChar32 c;
209         U16_NEXT(text, pos, end, c);
210         return c;
211     } else {
212         return DONE;
213     }
214 }
215 
216 UChar32
last32()217 UCharCharacterIterator::last32() {
218     pos = end;
219     if(pos > begin) {
220         UChar32 c;
221         U16_PREV(text, begin, pos, c);
222         return c;
223     } else {
224         return DONE;
225     }
226 }
227 
228 UChar32
setIndex32(int32_t position)229 UCharCharacterIterator::setIndex32(int32_t position) {
230     if(position < begin) {
231         position = begin;
232     } else if(position > end) {
233         position = end;
234     }
235     if(position < end) {
236         U16_SET_CP_START(text, begin, position);
237         int32_t i = this->pos = position;
238         UChar32 c;
239         U16_NEXT(text, i, end, c);
240         return c;
241     } else {
242         this->pos = position;
243         return DONE;
244     }
245 }
246 
247 UChar32
current32() const248 UCharCharacterIterator::current32() const {
249     if (pos >= begin && pos < end) {
250         UChar32 c;
251         U16_GET(text, begin, pos, end, c);
252         return c;
253     } else {
254         return DONE;
255     }
256 }
257 
258 UChar32
next32()259 UCharCharacterIterator::next32() {
260     if (pos < end) {
261         U16_FWD_1(text, pos, end);
262         if(pos < end) {
263             int32_t i = pos;
264             UChar32 c;
265             U16_NEXT(text, i, end, c);
266             return c;
267         }
268     }
269     /* make current() return DONE */
270     pos = end;
271     return DONE;
272 }
273 
274 UChar32
next32PostInc()275 UCharCharacterIterator::next32PostInc() {
276     if (pos < end) {
277         UChar32 c;
278         U16_NEXT(text, pos, end, c);
279         return c;
280     } else {
281         return DONE;
282     }
283 }
284 
285 UChar32
previous32()286 UCharCharacterIterator::previous32() {
287     if (pos > begin) {
288         UChar32 c;
289         U16_PREV(text, begin, pos, c);
290         return c;
291     } else {
292         return DONE;
293     }
294 }
295 
296 int32_t
move(int32_t delta,CharacterIterator::EOrigin origin)297 UCharCharacterIterator::move(int32_t delta, CharacterIterator::EOrigin origin) {
298     switch(origin) {
299     case kStart:
300         pos = begin + delta;
301         break;
302     case kCurrent:
303         pos += delta;
304         break;
305     case kEnd:
306         pos = end + delta;
307         break;
308     default:
309         break;
310     }
311 
312     if(pos < begin) {
313         pos = begin;
314     } else if(pos > end) {
315         pos = end;
316     }
317 
318     return pos;
319 }
320 
321 int32_t
move32(int32_t delta,CharacterIterator::EOrigin origin)322 UCharCharacterIterator::move32(int32_t delta, CharacterIterator::EOrigin origin) {
323     // this implementation relies on the "safe" version of the UTF macros
324     // (or the trustworthiness of the caller)
325     switch(origin) {
326     case kStart:
327         pos = begin;
328         if(delta > 0) {
329             U16_FWD_N(text, pos, end, delta);
330         }
331         break;
332     case kCurrent:
333         if(delta > 0) {
334             U16_FWD_N(text, pos, end, delta);
335         } else {
336             U16_BACK_N(text, begin, pos, -delta);
337         }
338         break;
339     case kEnd:
340         pos = end;
341         if(delta < 0) {
342             U16_BACK_N(text, begin, pos, -delta);
343         }
344         break;
345     default:
346         break;
347     }
348 
349     return pos;
350 }
351 
setText(ConstChar16Ptr newText,int32_t newTextLength)352 void UCharCharacterIterator::setText(ConstChar16Ptr newText,
353                                      int32_t      newTextLength) {
354     text = newText;
355     if(newText == 0 || newTextLength < 0) {
356         newTextLength = 0;
357     }
358     end = textLength = newTextLength;
359     pos = begin = 0;
360 }
361 
362 void
getText(UnicodeString & result)363 UCharCharacterIterator::getText(UnicodeString& result) {
364     result = UnicodeString(text, textLength);
365 }
366 
367 U_NAMESPACE_END
368