1/*
2 * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26/*
27 * (C) Copyright IBM Corp. 2003 - All Rights Reserved
28 *
29 * The original version of this source code and documentation is
30 * copyrighted and owned by IBM. These materials are provided
31 * under terms of a License Agreement between IBM and Sun.
32 * This technology is protected by multiple US and International
33 * patents. This notice and attribution to IBM may not be removed.
34 */
35
36package sun.font;
37
38import java.text.CharacterIterator;
39
40public abstract class CodePointIterator {
41    public static final int DONE = -1;
42
43    public abstract void setToStart();
44    public abstract void setToLimit();
45
46    public abstract int next();
47    public abstract int prev();
48
49    public abstract int charIndex();
50
51    public static CodePointIterator create(char[] text) {
52        return new CharArrayCodePointIterator(text);
53    }
54
55    public static CodePointIterator create(char[] text, int start, int limit) {
56        return new CharArrayCodePointIterator(text, start, limit);
57    }
58
59    public static CodePointIterator create(CharSequence text) {
60        return new CharSequenceCodePointIterator(text);
61    }
62
63    public static CodePointIterator create(CharacterIterator iter) {
64        return new CharacterIteratorCodePointIterator(iter);
65    }
66}
67
68final class CharArrayCodePointIterator extends CodePointIterator {
69    private char[] text;
70    private int start;
71    private int limit;
72    private int index;
73
74    public CharArrayCodePointIterator(char[] text) {
75        this.text = text;
76        this.limit = text.length;
77    }
78
79    public CharArrayCodePointIterator(char[] text, int start, int limit) {
80        if (start < 0 || limit < start || limit > text.length) {
81            throw new IllegalArgumentException();
82        }
83
84        this.text = text;
85        this.start = this.index = start;
86        this.limit = limit;
87    }
88
89    public void setToStart() {
90        index = start;
91    }
92
93    public void setToLimit() {
94        index = limit;
95    }
96
97    public int next() {
98        if (index < limit) {
99            char cp1 = text[index++];
100            if (Character.isHighSurrogate(cp1) && index < limit) {
101                char cp2 = text[index];
102                if (Character.isLowSurrogate(cp2)) {
103                    ++index;
104                    return Character.toCodePoint(cp1, cp2);
105                }
106            }
107            return cp1;
108        }
109        return DONE;
110    }
111
112    public int prev() {
113        if (index > start) {
114            char cp2 = text[--index];
115            if (Character.isLowSurrogate(cp2) && index > start) {
116                char cp1 = text[index - 1];
117                if (Character.isHighSurrogate(cp1)) {
118                    --index;
119                    return Character.toCodePoint(cp1, cp2);
120                }
121            }
122            return cp2;
123        }
124        return DONE;
125    }
126
127    public int charIndex() {
128        return index;
129    }
130}
131
132final class CharSequenceCodePointIterator extends CodePointIterator {
133    private CharSequence text;
134    private int index;
135
136    public CharSequenceCodePointIterator(CharSequence text) {
137        this.text = text;
138    }
139
140    public void setToStart() {
141        index = 0;
142    }
143
144    public void setToLimit() {
145        index = text.length();
146    }
147
148    public int next() {
149        if (index < text.length()) {
150            char cp1 = text.charAt(index++);
151            if (Character.isHighSurrogate(cp1) && index < text.length()) {
152                char cp2 = text.charAt(index+1);
153                if (Character.isLowSurrogate(cp2)) {
154                    ++index;
155                    return Character.toCodePoint(cp1, cp2);
156                }
157            }
158            return cp1;
159        }
160        return DONE;
161    }
162
163    public int prev() {
164        if (index > 0) {
165            char cp2 = text.charAt(--index);
166            if (Character.isLowSurrogate(cp2) && index > 0) {
167                char cp1 = text.charAt(index - 1);
168                if (Character.isHighSurrogate(cp1)) {
169                    --index;
170                    return Character.toCodePoint(cp1, cp2);
171                }
172            }
173            return cp2;
174        }
175        return DONE;
176    }
177
178    public int charIndex() {
179        return index;
180    }
181}
182
183// note this has different iteration semantics than CharacterIterator
184final class CharacterIteratorCodePointIterator extends CodePointIterator {
185    private CharacterIterator iter;
186
187    public CharacterIteratorCodePointIterator(CharacterIterator iter) {
188        this.iter = iter;
189    }
190
191    public void setToStart() {
192        iter.setIndex(iter.getBeginIndex());
193    }
194
195    public void setToLimit() {
196        iter.setIndex(iter.getEndIndex());
197    }
198
199    public int next() {
200        char cp1 = iter.current();
201        if (cp1 != CharacterIterator.DONE) {
202            char cp2 = iter.next();
203            if (Character.isHighSurrogate(cp1) && cp2 != CharacterIterator.DONE) {
204                if (Character.isLowSurrogate(cp2)) {
205                    iter.next();
206                    return Character.toCodePoint(cp1, cp2);
207                }
208            }
209            return cp1;
210        }
211        return DONE;
212    }
213
214    public int prev() {
215        char cp2 = iter.previous();
216        if (cp2 != CharacterIterator.DONE) {
217            if (Character.isLowSurrogate(cp2)) {
218                char cp1 = iter.previous();
219                if (Character.isHighSurrogate(cp1)) {
220                    return Character.toCodePoint(cp1, cp2);
221                }
222                iter.next();
223            }
224            return cp2;
225        }
226        return DONE;
227    }
228
229    public int charIndex() {
230        return iter.getIndex();
231    }
232}
233