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