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