1/*
2*******************************************************************************
3* Copyright (C) 2010-2014, International Business Machines
4* Corporation and others.  All Rights Reserved.
5*******************************************************************************
6* UTF16CollationIterator.java, ported from utf16collationiterator.h/.cpp
7*
8* C++ version created on: 2010oct27
9* created by: Markus W. Scherer
10*/
11
12package com.ibm.icu.impl.coll;
13
14/**
15 * UTF-16 collation element and character iterator.
16 * Handles normalized UTF-16 text, with length or NUL-terminated.
17 * Unnormalized text is handled by a subclass.
18 */
19public class UTF16CollationIterator extends CollationIterator {
20    /**
21     * Partial constructor, see {@link CollationIterator#CollationIterator(CollationData)}.
22     */
23    public UTF16CollationIterator(CollationData d) {
24        super(d);
25    }
26
27    public UTF16CollationIterator(CollationData d, boolean numeric, CharSequence s, int p) {
28        super(d, numeric);
29        seq = s;
30        start = 0;
31        pos = p;
32        limit = s.length();
33    }
34
35    @Override
36    public boolean equals(Object other) {
37        if(!super.equals(other)) { return false; }
38        UTF16CollationIterator o = (UTF16CollationIterator)other;
39        // Compare the iterator state but not the text: Assume that the caller does that.
40        return (pos - start) == (o.pos - o.start);
41    }
42
43    @Override
44    public int hashCode() {
45        assert false : "hashCode not designed";
46        return 42; // any arbitrary constant will do
47    }
48
49    @Override
50    public void resetToOffset(int newOffset) {
51        reset();
52        pos = start + newOffset;
53    }
54
55    @Override
56    public int getOffset() {
57        return pos - start;
58    }
59
60    public void setText(boolean numeric, CharSequence s, int p) {
61        reset(numeric);
62        seq = s;
63        start = 0;
64        pos = p;
65        limit = s.length();
66    }
67
68    @Override
69    public int nextCodePoint() {
70        if(pos == limit) {
71            return Collation.SENTINEL_CP;
72        }
73        char c = seq.charAt(pos++);
74        char trail;
75        if(Character.isHighSurrogate(c) && pos != limit &&
76                Character.isLowSurrogate(trail = seq.charAt(pos))) {
77            ++pos;
78            return Character.toCodePoint(c, trail);
79        } else {
80            return c;
81        }
82    }
83
84    @Override
85    public int previousCodePoint() {
86        if(pos == start) {
87            return Collation.SENTINEL_CP;
88        }
89        char c = seq.charAt(--pos);
90        char lead;
91        if(Character.isLowSurrogate(c) && pos != start &&
92                Character.isHighSurrogate(lead = seq.charAt(pos - 1))) {
93            --pos;
94            return Character.toCodePoint(lead, c);
95        } else {
96            return c;
97        }
98    }
99
100    @Override
101    protected long handleNextCE32() {
102        if(pos == limit) {
103            return NO_CP_AND_CE32;
104        }
105        char c = seq.charAt(pos++);
106        return makeCodePointAndCE32Pair(c, trie.getFromU16SingleLead(c));
107    }
108
109    @Override
110    protected char handleGetTrailSurrogate() {
111        if(pos == limit) { return 0; }
112        char trail;
113        if(Character.isLowSurrogate(trail = seq.charAt(pos))) { ++pos; }
114        return trail;
115    }
116
117    /* boolean foundNULTerminator(); */
118
119    @Override
120    protected void forwardNumCodePoints(int num) {
121        while(num > 0 && pos != limit) {
122            char c = seq.charAt(pos++);
123            --num;
124            if(Character.isHighSurrogate(c) && pos != limit &&
125                    Character.isLowSurrogate(seq.charAt(pos))) {
126                ++pos;
127            }
128        }
129    }
130
131    @Override
132    protected void backwardNumCodePoints(int num) {
133        while(num > 0 && pos != start) {
134            char c = seq.charAt(--pos);
135            --num;
136            if(Character.isLowSurrogate(c) && pos != start &&
137                    Character.isHighSurrogate(seq.charAt(pos-1))) {
138                --pos;
139            }
140        }
141    }
142
143    protected CharSequence seq;
144    protected int start;
145    protected int pos;
146    protected int limit;
147}
148