Home | History | Annotate | Download | only in icu
      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 
     17 package libcore.icu;
     18 
     19 import java.text.CharacterIterator;
     20 import java.text.StringCharacterIterator;
     21 import java.util.Locale;
     22 
     23 public 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     // The address of the native peer.
     31     // Uses of this must be manually synchronized to avoid native crashes.
     32     private final long address;
     33 
     34     private final int type;
     35     private String string;
     36     private CharacterIterator charIterator;
     37 
     38     private NativeBreakIterator(long address, int type) {
     39         this.address = address;
     40         this.type = type;
     41         this.charIterator = new StringCharacterIterator("");
     42     }
     43 
     44     @Override
     45     public Object clone() {
     46         long cloneAddr = cloneImpl(this.address);
     47         NativeBreakIterator clone = new NativeBreakIterator(cloneAddr, this.type);
     48         clone.string = this.string;
     49         // The RI doesn't clone the CharacterIterator.
     50         clone.charIterator = this.charIterator;
     51         return clone;
     52     }
     53 
     54     @Override
     55     public boolean equals(Object object) {
     56         if (object == this) {
     57             return true;
     58         }
     59         if (!(object instanceof NativeBreakIterator)) {
     60             return false;
     61         }
     62         // TODO: is this sufficient? shouldn't we be checking the underlying rules?
     63         NativeBreakIterator rhs = (NativeBreakIterator) object;
     64         return type == rhs.type && charIterator.equals(rhs.charIterator);
     65     }
     66 
     67     @Override
     68     public int hashCode() {
     69         return 42; // No-one uses BreakIterator as a hash key.
     70     }
     71 
     72     @Override protected void finalize() throws Throwable {
     73         try {
     74             closeImpl(this.address);
     75         } finally {
     76             super.finalize();
     77         }
     78     }
     79 
     80     public int current() {
     81         return currentImpl(this.address, this.string);
     82     }
     83 
     84     public int first() {
     85         return firstImpl(this.address, this.string);
     86     }
     87 
     88     public int following(int offset) {
     89         return followingImpl(this.address, this.string, offset);
     90     }
     91 
     92     public CharacterIterator getText() {
     93         int newLocation = currentImpl(this.address, this.string);
     94         this.charIterator.setIndex(newLocation);
     95         return this.charIterator;
     96     }
     97 
     98     public int last() {
     99         return lastImpl(this.address, this.string);
    100     }
    101 
    102     public int next(int n) {
    103         return nextImpl(this.address, this.string, n);
    104     }
    105 
    106     public int next() {
    107         return nextImpl(this.address, this.string, 1);
    108     }
    109 
    110     public int previous() {
    111         return previousImpl(this.address, this.string);
    112     }
    113 
    114     public void setText(CharacterIterator newText) {
    115         StringBuilder sb = new StringBuilder();
    116         for (char c = newText.first(); c != CharacterIterator.DONE; c = newText.next()) {
    117             sb.append(c);
    118         }
    119         setText(sb.toString(), newText);
    120     }
    121 
    122     public void setText(String newText) {
    123         setText(newText, new StringCharacterIterator(newText));
    124     }
    125 
    126     private void setText(String s, CharacterIterator it) {
    127         this.string = s;
    128         this.charIterator = it;
    129         setTextImpl(this.address, this.string);
    130     }
    131 
    132     public boolean hasText() {
    133         return (string != null);
    134     }
    135 
    136     public boolean isBoundary(int offset) {
    137         return isBoundaryImpl(this.address, this.string, offset);
    138     }
    139 
    140     public int preceding(int offset) {
    141         return precedingImpl(this.address, this.string, offset);
    142     }
    143 
    144     public static NativeBreakIterator getCharacterInstance(Locale locale) {
    145         return new NativeBreakIterator(getCharacterInstanceImpl(locale.toLanguageTag()), BI_CHAR_INSTANCE);
    146     }
    147 
    148     public static NativeBreakIterator getLineInstance(Locale locale) {
    149         return new NativeBreakIterator(getLineInstanceImpl(locale.toLanguageTag()), BI_LINE_INSTANCE);
    150     }
    151 
    152     public static NativeBreakIterator getSentenceInstance(Locale locale) {
    153         return new NativeBreakIterator(getSentenceInstanceImpl(locale.toLanguageTag()), BI_SENT_INSTANCE);
    154     }
    155 
    156     public static NativeBreakIterator getWordInstance(Locale locale) {
    157         return new NativeBreakIterator(getWordInstanceImpl(locale.toLanguageTag()), BI_WORD_INSTANCE);
    158     }
    159 
    160     private static native long getCharacterInstanceImpl(String locale);
    161     private static native long getWordInstanceImpl(String locale);
    162     private static native long getLineInstanceImpl(String locale);
    163     private static native long getSentenceInstanceImpl(String locale);
    164     private static synchronized native long cloneImpl(long address);
    165 
    166     private static synchronized native void closeImpl(long address);
    167 
    168     private static synchronized native void setTextImpl(long address, String text);
    169     private static synchronized native int precedingImpl(long address, String text, int offset);
    170     private static synchronized native boolean isBoundaryImpl(long address, String text, int offset);
    171     private static synchronized native int nextImpl(long address, String text, int n);
    172     private static synchronized native int previousImpl(long address, String text);
    173     private static synchronized native int currentImpl(long address, String text);
    174     private static synchronized native int firstImpl(long address, String text);
    175     private static synchronized native int followingImpl(long address, String text, int offset);
    176     private static synchronized native int lastImpl(long address, String text);
    177 }
    178