1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/*
2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * you may not use this file except in compliance with the License.
6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * You may obtain a copy of the License at
7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project *
10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and
14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License.
15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */
16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
17c27a366a89e470690e99374b15270e7b9169ade1Elliott Hughespackage libcore.icu;
18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
199672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughesimport java.text.CharacterIterator;
209672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughesimport java.text.StringCharacterIterator;
219672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughesimport java.util.Locale;
229672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes
239672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughespublic final class NativeBreakIterator implements Cloneable {
249672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    // Acceptable values for the 'type' field.
259672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    private static final int BI_CHAR_INSTANCE = 1;
269672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    private static final int BI_WORD_INSTANCE = 2;
279672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    private static final int BI_LINE_INSTANCE = 3;
289672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    private static final int BI_SENT_INSTANCE = 4;
299672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes
30eb9689bf8aee71f16fbe22a2c90d25628dd431ecElliott Hughes    // The address of the native peer.
31eb9689bf8aee71f16fbe22a2c90d25628dd431ecElliott Hughes    // Uses of this must be manually synchronized to avoid native crashes.
321e5d730e58d94c3bfa14b7dde5ab3981fe5a170bElliott Hughes    private final long address;
33eb9689bf8aee71f16fbe22a2c90d25628dd431ecElliott Hughes
349672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    private final int type;
35015843683630bd8e8f060c052ecd2e5a804a8396Elliott Hughes    private String string;
36015843683630bd8e8f060c052ecd2e5a804a8396Elliott Hughes    private CharacterIterator charIterator;
379672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes
381e5d730e58d94c3bfa14b7dde5ab3981fe5a170bElliott Hughes    private NativeBreakIterator(long address, int type) {
39866e7ae17a3da81a02b0b144e0c9c2b3196d293aElliott Hughes        this.address = address;
409672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes        this.type = type;
41015843683630bd8e8f060c052ecd2e5a804a8396Elliott Hughes        this.charIterator = new StringCharacterIterator("");
429672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    }
439672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes
449672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    @Override
459672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    public Object clone() {
461e5d730e58d94c3bfa14b7dde5ab3981fe5a170bElliott Hughes        long cloneAddr = cloneImpl(this.address);
479672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes        NativeBreakIterator clone = new NativeBreakIterator(cloneAddr, this.type);
48015843683630bd8e8f060c052ecd2e5a804a8396Elliott Hughes        clone.string = this.string;
499672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes        // The RI doesn't clone the CharacterIterator.
50015843683630bd8e8f060c052ecd2e5a804a8396Elliott Hughes        clone.charIterator = this.charIterator;
519672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes        return clone;
529672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    }
539672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes
549672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    @Override
559672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    public boolean equals(Object object) {
56ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        if (object == this) {
57ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes            return true;
58ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        }
59ebe438a0734f24ded1772778e5e712c820981234Elliott Hughes        if (!(object instanceof NativeBreakIterator)) {
609672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes            return false;
619672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes        }
629672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes        // TODO: is this sufficient? shouldn't we be checking the underlying rules?
639672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes        NativeBreakIterator rhs = (NativeBreakIterator) object;
64015843683630bd8e8f060c052ecd2e5a804a8396Elliott Hughes        return type == rhs.type && charIterator.equals(rhs.charIterator);
659672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    }
669672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes
679672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    @Override
689672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    public int hashCode() {
699672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes        return 42; // No-one uses BreakIterator as a hash key.
709672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    }
719672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes
72e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom    @Override protected void finalize() throws Throwable {
73e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom        try {
74015843683630bd8e8f060c052ecd2e5a804a8396Elliott Hughes            closeImpl(this.address);
75e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom        } finally {
76e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom            super.finalize();
77e2f58c9501eac730d048199906dc41fe8e4cd6e9Brian Carlstrom        }
789672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    }
799672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes
809672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    public int current() {
81015843683630bd8e8f060c052ecd2e5a804a8396Elliott Hughes        return currentImpl(this.address, this.string);
829672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    }
839672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes
849672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    public int first() {
85015843683630bd8e8f060c052ecd2e5a804a8396Elliott Hughes        return firstImpl(this.address, this.string);
869672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    }
879672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes
889672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    public int following(int offset) {
89015843683630bd8e8f060c052ecd2e5a804a8396Elliott Hughes        return followingImpl(this.address, this.string, offset);
909672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    }
919672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes
929672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    public CharacterIterator getText() {
93015843683630bd8e8f060c052ecd2e5a804a8396Elliott Hughes        int newLocation = currentImpl(this.address, this.string);
94015843683630bd8e8f060c052ecd2e5a804a8396Elliott Hughes        this.charIterator.setIndex(newLocation);
95015843683630bd8e8f060c052ecd2e5a804a8396Elliott Hughes        return this.charIterator;
969672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    }
979672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes
989672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    public int last() {
99015843683630bd8e8f060c052ecd2e5a804a8396Elliott Hughes        return lastImpl(this.address, this.string);
1009672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    }
1019672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes
1029672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    public int next(int n) {
103015843683630bd8e8f060c052ecd2e5a804a8396Elliott Hughes        return nextImpl(this.address, this.string, n);
1049672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    }
1059672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes
1069672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    public int next() {
107015843683630bd8e8f060c052ecd2e5a804a8396Elliott Hughes        return nextImpl(this.address, this.string, 1);
1089672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    }
1099672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes
1109672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    public int previous() {
111015843683630bd8e8f060c052ecd2e5a804a8396Elliott Hughes        return previousImpl(this.address, this.string);
112adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project    }
113adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1149672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    public void setText(CharacterIterator newText) {
1159672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes        StringBuilder sb = new StringBuilder();
1169672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes        for (char c = newText.first(); c != CharacterIterator.DONE; c = newText.next()) {
1179672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes            sb.append(c);
1189672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes        }
11952dfb928ffdae183b91805bb6983f6e6aa87c9afElliott Hughes        setText(sb.toString(), newText);
1209672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    }
121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1229672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    public void setText(String newText) {
12352dfb928ffdae183b91805bb6983f6e6aa87c9afElliott Hughes        setText(newText, new StringCharacterIterator(newText));
12452dfb928ffdae183b91805bb6983f6e6aa87c9afElliott Hughes    }
12552dfb928ffdae183b91805bb6983f6e6aa87c9afElliott Hughes
12652dfb928ffdae183b91805bb6983f6e6aa87c9afElliott Hughes    private void setText(String s, CharacterIterator it) {
127015843683630bd8e8f060c052ecd2e5a804a8396Elliott Hughes        this.string = s;
128015843683630bd8e8f060c052ecd2e5a804a8396Elliott Hughes        this.charIterator = it;
129015843683630bd8e8f060c052ecd2e5a804a8396Elliott Hughes        setTextImpl(this.address, this.string);
130015843683630bd8e8f060c052ecd2e5a804a8396Elliott Hughes    }
131015843683630bd8e8f060c052ecd2e5a804a8396Elliott Hughes
132015843683630bd8e8f060c052ecd2e5a804a8396Elliott Hughes    public boolean hasText() {
133015843683630bd8e8f060c052ecd2e5a804a8396Elliott Hughes        return (string != null);
1349672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    }
135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1369672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    public boolean isBoundary(int offset) {
137015843683630bd8e8f060c052ecd2e5a804a8396Elliott Hughes        return isBoundaryImpl(this.address, this.string, offset);
1389672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    }
139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1409672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    public int preceding(int offset) {
141015843683630bd8e8f060c052ecd2e5a804a8396Elliott Hughes      return precedingImpl(this.address, this.string, offset);
1429672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    }
143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1449672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    public static NativeBreakIterator getCharacterInstance(Locale where) {
1459672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes        return new NativeBreakIterator(getCharacterInstanceImpl(where.toString()), BI_CHAR_INSTANCE);
1469672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    }
147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1489672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    public static NativeBreakIterator getLineInstance(Locale where) {
1499672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes        return new NativeBreakIterator(getLineInstanceImpl(where.toString()), BI_LINE_INSTANCE);
1509672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    }
151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1529672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    public static NativeBreakIterator getSentenceInstance(Locale where) {
1539672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes        return new NativeBreakIterator(getSentenceInstanceImpl(where.toString()), BI_SENT_INSTANCE);
1549672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    }
155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1569672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    public static NativeBreakIterator getWordInstance(Locale where) {
1579672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes        return new NativeBreakIterator(getWordInstanceImpl(where.toString()), BI_WORD_INSTANCE);
1589672b4887f2972c1b7c5f3d1a6cf882deccf857fElliott Hughes    }
159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project
1601e5d730e58d94c3bfa14b7dde5ab3981fe5a170bElliott Hughes    private static native long getCharacterInstanceImpl(String locale);
1611e5d730e58d94c3bfa14b7dde5ab3981fe5a170bElliott Hughes    private static native long getWordInstanceImpl(String locale);
1621e5d730e58d94c3bfa14b7dde5ab3981fe5a170bElliott Hughes    private static native long getLineInstanceImpl(String locale);
1631e5d730e58d94c3bfa14b7dde5ab3981fe5a170bElliott Hughes    private static native long getSentenceInstanceImpl(String locale);
1641e5d730e58d94c3bfa14b7dde5ab3981fe5a170bElliott Hughes    private static synchronized native long cloneImpl(long address);
165eb9689bf8aee71f16fbe22a2c90d25628dd431ecElliott Hughes
1661e5d730e58d94c3bfa14b7dde5ab3981fe5a170bElliott Hughes    private static synchronized native void closeImpl(long address);
167eb9689bf8aee71f16fbe22a2c90d25628dd431ecElliott Hughes
1681e5d730e58d94c3bfa14b7dde5ab3981fe5a170bElliott Hughes    private static synchronized native void setTextImpl(long address, String text);
1691e5d730e58d94c3bfa14b7dde5ab3981fe5a170bElliott Hughes    private static synchronized native int precedingImpl(long address, String text, int offset);
1701e5d730e58d94c3bfa14b7dde5ab3981fe5a170bElliott Hughes    private static synchronized native boolean isBoundaryImpl(long address, String text, int offset);
1711e5d730e58d94c3bfa14b7dde5ab3981fe5a170bElliott Hughes    private static synchronized native int nextImpl(long address, String text, int n);
1721e5d730e58d94c3bfa14b7dde5ab3981fe5a170bElliott Hughes    private static synchronized native int previousImpl(long address, String text);
1731e5d730e58d94c3bfa14b7dde5ab3981fe5a170bElliott Hughes    private static synchronized native int currentImpl(long address, String text);
1741e5d730e58d94c3bfa14b7dde5ab3981fe5a170bElliott Hughes    private static synchronized native int firstImpl(long address, String text);
1751e5d730e58d94c3bfa14b7dde5ab3981fe5a170bElliott Hughes    private static synchronized native int followingImpl(long address, String text, int offset);
1761e5d730e58d94c3bfa14b7dde5ab3981fe5a170bElliott Hughes    private static synchronized native int lastImpl(long address, String text);
177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project}
178