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
17U_NAMESPACE_BEGIN
18
19UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UCharCharacterIterator)
20
21UCharCharacterIterator::UCharCharacterIterator()
22  : CharacterIterator(),
23  text(0)
24{
25    // never default construct!
26}
27
28UCharCharacterIterator::UCharCharacterIterator(ConstChar16Ptr textPtr,
29                                               int32_t length)
30  : CharacterIterator(textPtr != 0 ? (length>=0 ? length : u_strlen(textPtr)) : 0),
31  text(textPtr)
32{
33}
34
35UCharCharacterIterator::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
43UCharCharacterIterator::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
53UCharCharacterIterator::UCharCharacterIterator(const UCharCharacterIterator& that)
54: CharacterIterator(that),
55  text(that.text)
56{
57}
58
59UCharCharacterIterator&
60UCharCharacterIterator::operator=(const UCharCharacterIterator& that) {
61    CharacterIterator::operator=(that);
62    text = that.text;
63    return *this;
64}
65
66UCharCharacterIterator::~UCharCharacterIterator() {
67}
68
69bool
70UCharCharacterIterator::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    const UCharCharacterIterator&    realThat = static_cast<const 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
87int32_t
88UCharCharacterIterator::hashCode() const {
89    return ustr_hashUCharsN(text, textLength) ^ pos ^ begin ^ end;
90}
91
92UCharCharacterIterator*
93UCharCharacterIterator::clone() const {
94    return new UCharCharacterIterator(*this);
95}
96
97char16_t
98UCharCharacterIterator::first() {
99    pos = begin;
100    if(pos < end) {
101        return text[pos];
102    } else {
103        return DONE;
104    }
105}
106
107char16_t
108UCharCharacterIterator::firstPostInc() {
109    pos = begin;
110    if(pos < end) {
111        return text[pos++];
112    } else {
113        return DONE;
114    }
115}
116
117char16_t
118UCharCharacterIterator::last() {
119    pos = end;
120    if(pos > begin) {
121        return text[--pos];
122    } else {
123        return DONE;
124    }
125}
126
127char16_t
128UCharCharacterIterator::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
143char16_t
144UCharCharacterIterator::current() const {
145    if (pos >= begin && pos < end) {
146        return text[pos];
147    } else {
148        return DONE;
149    }
150}
151
152char16_t
153UCharCharacterIterator::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
163char16_t
164UCharCharacterIterator::nextPostInc() {
165    if (pos < end) {
166        return text[pos++];
167    } else {
168        return DONE;
169    }
170}
171
172UBool
173UCharCharacterIterator::hasNext() {
174    return (UBool)(pos < end ? true : false);
175}
176
177char16_t
178UCharCharacterIterator::previous() {
179    if (pos > begin) {
180        return text[--pos];
181    } else {
182        return DONE;
183    }
184}
185
186UBool
187UCharCharacterIterator::hasPrevious() {
188    return (UBool)(pos > begin ? true : false);
189}
190
191UChar32
192UCharCharacterIterator::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
204UChar32
205UCharCharacterIterator::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
216UChar32
217UCharCharacterIterator::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
228UChar32
229UCharCharacterIterator::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
247UChar32
248UCharCharacterIterator::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
258UChar32
259UCharCharacterIterator::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
274UChar32
275UCharCharacterIterator::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
285UChar32
286UCharCharacterIterator::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
296int32_t
297UCharCharacterIterator::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
321int32_t
322UCharCharacterIterator::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
352void 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
362void
363UCharCharacterIterator::getText(UnicodeString& result) {
364    result = UnicodeString(text, textLength);
365}
366
367U_NAMESPACE_END
368