NativeBreakIterator.java revision 52dfb928ffdae183b91805bb6983f6e6aa87c9af
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package libcore.icu;
18
19import java.text.CharacterIterator;
20import java.text.StringCharacterIterator;
21import java.util.Locale;
22
23public final class NativeBreakIterator implements Cloneable {
24    // Acceptable values for the 'type' field.
25    private static final int BI_CHAR_INSTANCE = 1;
26    private static final int BI_WORD_INSTANCE = 2;
27    private static final int BI_LINE_INSTANCE = 3;
28    private static final int BI_SENT_INSTANCE = 4;
29
30    private final int address;
31    private final int type;
32    private CharacterIterator charIter;
33
34    private NativeBreakIterator(int address, int type) {
35        this.address = address;
36        this.type = type;
37        this.charIter = new StringCharacterIterator("");
38    }
39
40    @Override
41    public Object clone() {
42        int cloneAddr = cloneImpl(this.address);
43        NativeBreakIterator clone = new NativeBreakIterator(cloneAddr, this.type);
44        // The RI doesn't clone the CharacterIterator.
45        clone.charIter = this.charIter;
46        return clone;
47    }
48
49    @Override
50    public boolean equals(Object object) {
51        if (object == this) {
52            return true;
53        }
54        if (!(object instanceof NativeBreakIterator)) {
55            return false;
56        }
57        // TODO: is this sufficient? shouldn't we be checking the underlying rules?
58        NativeBreakIterator rhs = (NativeBreakIterator) object;
59        return type == rhs.type && charIter.equals(rhs.charIter);
60    }
61
62    @Override
63    public int hashCode() {
64        return 42; // No-one uses BreakIterator as a hash key.
65    }
66
67    @Override protected void finalize() throws Throwable {
68        try {
69            closeBreakIteratorImpl(this.address);
70        } finally {
71            super.finalize();
72        }
73    }
74
75    public int current() {
76        return currentImpl(this.address);
77    }
78
79    public int first() {
80        return firstImpl(this.address);
81    }
82
83    public int following(int offset) {
84        return followingImpl(this.address, offset);
85    }
86
87    public CharacterIterator getText() {
88        int newLoc = currentImpl(this.address);
89        this.charIter.setIndex(newLoc);
90        return this.charIter;
91    }
92
93    public int last() {
94        return lastImpl(this.address);
95    }
96
97    public int next(int n) {
98        return nextImpl(this.address, n);
99    }
100
101    public int next() {
102        return nextImpl(this.address, 1);
103    }
104
105    public int previous() {
106        return previousImpl(this.address);
107    }
108
109    public void setText(CharacterIterator newText) {
110        StringBuilder sb = new StringBuilder();
111        for (char c = newText.first(); c != CharacterIterator.DONE; c = newText.next()) {
112            sb.append(c);
113        }
114        setText(sb.toString(), newText);
115    }
116
117    public void setText(String newText) {
118        setText(newText, new StringCharacterIterator(newText));
119    }
120
121    private void setText(String s, CharacterIterator it) {
122        this.charIter = it;
123        setTextImpl(this.address, s);
124    }
125
126    public boolean isBoundary(int offset) {
127        return isBoundaryImpl(this.address, offset);
128    }
129
130    public int preceding(int offset) {
131        return precedingImpl(this.address, offset);
132    }
133
134    public static NativeBreakIterator getCharacterInstance(Locale where) {
135        return new NativeBreakIterator(getCharacterInstanceImpl(where.toString()), BI_CHAR_INSTANCE);
136    }
137
138    public static NativeBreakIterator getLineInstance(Locale where) {
139        return new NativeBreakIterator(getLineInstanceImpl(where.toString()), BI_LINE_INSTANCE);
140    }
141
142    public static NativeBreakIterator getSentenceInstance(Locale where) {
143        return new NativeBreakIterator(getSentenceInstanceImpl(where.toString()), BI_SENT_INSTANCE);
144    }
145
146    public static NativeBreakIterator getWordInstance(Locale where) {
147        return new NativeBreakIterator(getWordInstanceImpl(where.toString()), BI_WORD_INSTANCE);
148    }
149
150    private static native int getCharacterInstanceImpl(String locale);
151    private static native int getWordInstanceImpl(String locale);
152    private static native int getLineInstanceImpl(String locale);
153    private static native int getSentenceInstanceImpl(String locale);
154    private static native void closeBreakIteratorImpl(int address);
155    private static native void setTextImpl(int address, String text);
156    private static native int cloneImpl(int address);
157    private static native int precedingImpl(int address, int offset);
158    private static native boolean isBoundaryImpl(int address, int offset);
159    private static native int nextImpl(int address, int n);
160    private static native int previousImpl(int address);
161    private static native int currentImpl(int address);
162    private static native int firstImpl(int address);
163    private static native int followingImpl(int address, int offset);
164    private static native int lastImpl(int address);
165}
166