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 
15 U_NAMESPACE_BEGIN
16 
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UCharCharacterIterator)17 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UCharCharacterIterator)
18 
19 UCharCharacterIterator::UCharCharacterIterator()
20   : CharacterIterator(),
21   text(0)
22 {
23     // never default construct!
24 }
25 
UCharCharacterIterator(const UChar * textPtr,int32_t length)26 UCharCharacterIterator::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 
UCharCharacterIterator(const UChar * textPtr,int32_t length,int32_t position)33 UCharCharacterIterator::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 
UCharCharacterIterator(const UChar * textPtr,int32_t length,int32_t textBegin,int32_t textEnd,int32_t position)41 UCharCharacterIterator::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 
UCharCharacterIterator(const UCharCharacterIterator & that)51 UCharCharacterIterator::UCharCharacterIterator(const UCharCharacterIterator& that)
52 : CharacterIterator(that),
53   text(that.text)
54 {
55 }
56 
57 UCharCharacterIterator&
operator =(const UCharCharacterIterator & that)58 UCharCharacterIterator::operator=(const UCharCharacterIterator& that) {
59     CharacterIterator::operator=(that);
60     text = that.text;
61     return *this;
62 }
63 
~UCharCharacterIterator()64 UCharCharacterIterator::~UCharCharacterIterator() {
65 }
66 
67 UBool
operator ==(const ForwardCharacterIterator & that) const68 UCharCharacterIterator::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 
85 int32_t
hashCode() const86 UCharCharacterIterator::hashCode() const {
87     return ustr_hashUCharsN(text, textLength) ^ pos ^ begin ^ end;
88 }
89 
90 CharacterIterator*
clone() const91 UCharCharacterIterator::clone() const {
92     return new UCharCharacterIterator(*this);
93 }
94 
95 UChar
first()96 UCharCharacterIterator::first() {
97     pos = begin;
98     if(pos < end) {
99         return text[pos];
100     } else {
101         return DONE;
102     }
103 }
104 
105 UChar
firstPostInc()106 UCharCharacterIterator::firstPostInc() {
107     pos = begin;
108     if(pos < end) {
109         return text[pos++];
110     } else {
111         return DONE;
112     }
113 }
114 
115 UChar
last()116 UCharCharacterIterator::last() {
117     pos = end;
118     if(pos > begin) {
119         return text[--pos];
120     } else {
121         return DONE;
122     }
123 }
124 
125 UChar
setIndex(int32_t position)126 UCharCharacterIterator::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 
141 UChar
current() const142 UCharCharacterIterator::current() const {
143     if (pos >= begin && pos < end) {
144         return text[pos];
145     } else {
146         return DONE;
147     }
148 }
149 
150 UChar
next()151 UCharCharacterIterator::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 
161 UChar
nextPostInc()162 UCharCharacterIterator::nextPostInc() {
163     if (pos < end) {
164         return text[pos++];
165     } else {
166         return DONE;
167     }
168 }
169 
170 UBool
hasNext()171 UCharCharacterIterator::hasNext() {
172     return (UBool)(pos < end ? TRUE : FALSE);
173 }
174 
175 UChar
previous()176 UCharCharacterIterator::previous() {
177     if (pos > begin) {
178         return text[--pos];
179     } else {
180         return DONE;
181     }
182 }
183 
184 UBool
hasPrevious()185 UCharCharacterIterator::hasPrevious() {
186     return (UBool)(pos > begin ? TRUE : FALSE);
187 }
188 
189 UChar32
first32()190 UCharCharacterIterator::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 
202 UChar32
first32PostInc()203 UCharCharacterIterator::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 
214 UChar32
last32()215 UCharCharacterIterator::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 
226 UChar32
setIndex32(int32_t position)227 UCharCharacterIterator::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 
245 UChar32
current32() const246 UCharCharacterIterator::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 
256 UChar32
next32()257 UCharCharacterIterator::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 
272 UChar32
next32PostInc()273 UCharCharacterIterator::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 
283 UChar32
previous32()284 UCharCharacterIterator::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 
294 int32_t
move(int32_t delta,CharacterIterator::EOrigin origin)295 UCharCharacterIterator::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 
319 int32_t
move32(int32_t delta,CharacterIterator::EOrigin origin)320 UCharCharacterIterator::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 
setText(const UChar * newText,int32_t newTextLength)350 void 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 
360 void
getText(UnicodeString & result)361 UCharCharacterIterator::getText(UnicodeString& result) {
362     result = UnicodeString(text, textLength);
363 }
364 
365 U_NAMESPACE_END
366