17935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/* 27935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ******************************************************************************* 37935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Copyright (C) 1996-2014, International Business Machines Corporation and 47935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * others. All Rights Reserved. 57935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ******************************************************************************* 67935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 77935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertpackage com.ibm.icu.text; 87935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 97935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport java.text.CharacterIterator; 107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.lang.UCharacter; 127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.ICUCloneNotSupportedException; 137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertimport com.ibm.icu.util.ULocale; 147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert/** 177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Inserts the specified characters at word breaks. To restrict it to particular characters, use a filter. 187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * TODO: this is an internal class, and only temporary. Remove it once we have \b notation in Transliterator. 197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubertfinal class BreakTransliterator extends Transliterator { 217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private BreakIterator bi; 227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private String insertion; 237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int[] boundaries = new int[50]; 247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int boundaryCount = 0; 257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public BreakTransliterator(String ID, UnicodeFilter filter, BreakIterator bi, String insertion) { 277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert super(ID, filter); 287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.bi = bi; 297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.insertion = insertion; 307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public BreakTransliterator(String ID, UnicodeFilter filter) { 337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this(ID, filter, null, " "); 347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ///CLOVER:OFF 377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // The following method is not called by anything and can't be reached 387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public String getInsertion() { 397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return insertion; 407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ///CLOVER:ON 427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ///CLOVER:OFF 447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // The following method is not called by anything and can't be reached 457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setInsertion(String insertion) { 467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.insertion = insertion; 477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ///CLOVER:ON 497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public BreakIterator getBreakIterator() { 517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Defer initialization of BreakIterator because it is slow, 527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // typically over 2000 ms. 537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (bi == null) bi = BreakIterator.getWordInstance(new ULocale("th_TH")); 547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return bi; 557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ///CLOVER:OFF 587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // The following method is not called by anything and can't be reached 597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setBreakIterator(BreakIterator bi) { 607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.bi = bi; 617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ///CLOVER:ON 637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final int LETTER_OR_MARK_MASK = 657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert (1<<Character.UPPERCASE_LETTER) 667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert | (1<<Character.LOWERCASE_LETTER) 677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert | (1<<Character.TITLECASE_LETTER) 687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert | (1<<Character.MODIFIER_LETTER) 697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert | (1<<Character.OTHER_LETTER) 707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert | (1<<Character.COMBINING_SPACING_MARK) 717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert | (1<<Character.NON_SPACING_MARK) 727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert | (1<<Character.ENCLOSING_MARK) 737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ; 747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert protected synchronized void handleTransliterate(Replaceable text, Position pos, boolean incremental) { 757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boundaryCount = 0; 767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int boundary = 0; 777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert getBreakIterator(); // Lazy-create it if necessary 787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert bi.setText(new ReplaceableCharacterIterator(text, pos.start, pos.limit, pos.start)); 797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // TODO: fix clumsy workaround used below. 807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert char[] tempBuffer = new char[text.length()]; 827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert text.getChars(0, text.length(), tempBuffer, 0); 837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert bi.setText(new StringCharacterIterator(new String(tempBuffer), pos.start, pos.limit, pos.start)); 847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // end debugging 867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // To make things much easier, we will stack the boundaries, and then insert at the end. 887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // generally, we won't need too many, since we will be filtered. 897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert for(boundary = bi.first(); boundary != BreakIterator.DONE && boundary < pos.limit; boundary = bi.next()) { 917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (boundary == 0) continue; 927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // HACK: Check to see that preceeding item was a letter 937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int cp = UTF16.charAt(text, boundary-1); 957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int type = UCharacter.getType(cp); 967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert //System.out.println(Integer.toString(cp,16) + " (before): " + type); 977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (((1<<type) & LETTER_OR_MARK_MASK) == 0) continue; 987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert cp = UTF16.charAt(text, boundary); 1007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert type = UCharacter.getType(cp); 1017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert //System.out.println(Integer.toString(cp,16) + " (after): " + type); 1027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (((1<<type) & LETTER_OR_MARK_MASK) == 0) continue; 1037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (boundaryCount >= boundaries.length) { // realloc if necessary 1057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int[] temp = new int[boundaries.length * 2]; 1067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert System.arraycopy(boundaries, 0, temp, 0, boundaries.length); 1077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boundaries = temp; 1087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boundaries[boundaryCount++] = boundary; 1117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert //System.out.println(boundary); 1127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int delta = 0; 1157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert int lastBoundary = 0; 1167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (boundaryCount != 0) { // if we found something, adjust 1187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert delta = boundaryCount * insertion.length(); 1197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert lastBoundary = boundaries[boundaryCount-1]; 1207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // we do this from the end backwards, so that we don't have to keep updating. 1227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert while (boundaryCount > 0) { 1247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert boundary = boundaries[--boundaryCount]; 1257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert text.replace(boundary, boundary, insertion); 1267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Now fix up the return values 1307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos.contextLimit += delta; 1317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos.limit += delta; 1327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos.start = incremental ? lastBoundary + delta : pos.limit; 1337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Registers standard variants with the system. Called by 1387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Transliterator during initialization. 1397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static void register() { 1417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // false means that it is invisible 1427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Transliterator trans = new BreakTransliterator("Any-BreakInternal", null); 1437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Transliterator.registerInstance(trans, false); 1447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* 1457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert Transliterator.registerFactory("Any-Break", new Transliterator.Factory() { 1467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public Transliterator getInstance(String ID) { 1477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return new BreakTransliterator("Any-Break", null); 1487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }); 1507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Hack, just to get a real character iterator. 1547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert static final class ReplaceableCharacterIterator implements CharacterIterator 1557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 1567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private Replaceable text; 1577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int begin; 1587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int end; 1597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // invariant: begin <= pos <= end 1607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert private int pos; 1617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Constructs an iterator with an initial index of 0. 1647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*public ReplaceableCharacterIterator(Replaceable text) 1667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 1677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this(text, 0); 1687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }*/ 1697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Constructs an iterator with the specified initial index. 1727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param text The String to be iterated over 1747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pos Initial iterator position 1757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /*public ReplaceableCharacterIterator(Replaceable text, int pos) 1777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 1787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this(text, 0, text.length(), pos); 1797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert }*/ 1807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 1827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Constructs an iterator over the given range of the given string, with the 1837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * index set at the specified position. 1847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 1857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param text The String to be iterated over 1867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param begin Index of the first character 1877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param end Index of the character following the last character 1887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param pos Initial iterator position 1897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 1907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public ReplaceableCharacterIterator(Replaceable text, int begin, int end, int pos) { 1917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (text == null) { 1927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new NullPointerException(); 1937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.text = text; 1957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 1967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (begin < 0 || begin > end || end > text.length()) { 1977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Invalid substring range"); 1987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 1997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (pos < begin || pos > end) { 2017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Invalid position"); 2027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.begin = begin; 2057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.end = end; 2067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.pos = pos; 2077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Reset this iterator to point to a new string. This package-visible 2117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * method is used by other java.text classes that want to avoid allocating 2127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * new ReplaceableCharacterIterator objects every time their setText method 2137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * is called. 2147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * 2157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param text The String to be iterated over 2167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void setText(Replaceable text) { 2187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (text == null) { 2197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new NullPointerException(); 2207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.text = text; 2227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.begin = 0; 2237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.end = text.length(); 2247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert this.pos = 0; 2257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Implements CharacterIterator.first() for String. 2297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see CharacterIterator#first 2307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public char first() 2327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 2337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos = begin; 2347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return current(); 2357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Implements CharacterIterator.last() for String. 2397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see CharacterIterator#last 2407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public char last() 2427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 2437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (end != begin) { 2447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos = end - 1; 2457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } else { 2467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos = end; 2477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return current(); 2497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Implements CharacterIterator.setIndex() for String. 2537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see CharacterIterator#setIndex 2547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public char setIndex(int p) 2567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 2577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (p < begin || p > end) { 2587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new IllegalArgumentException("Invalid index"); 2597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos = p; 2617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return current(); 2627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Implements CharacterIterator.current() for String. 2667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see CharacterIterator#current 2677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public char current() 2697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 2707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (pos >= begin && pos < end) { 2717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return text.charAt(pos); 2727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert else { 2747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return DONE; 2757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Implements CharacterIterator.next() for String. 2807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see CharacterIterator#next 2817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public char next() 2837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 2847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (pos < end - 1) { 2857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos++; 2867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return text.charAt(pos); 2877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert else { 2897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos = end; 2907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return DONE; 2917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 2937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 2947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 2957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Implements CharacterIterator.previous() for String. 2967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see CharacterIterator#previous 2977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 2987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public char previous() 2997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 3007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (pos > begin) { 3017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert pos--; 3027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return text.charAt(pos); 3037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert else { 3057935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return DONE; 3067935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3077935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3087935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3097935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 3107935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Implements CharacterIterator.getBeginIndex() for String. 3117935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see CharacterIterator#getBeginIndex 3127935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3137935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int getBeginIndex() 3147935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 3157935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return begin; 3167935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3177935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3187935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 3197935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Implements CharacterIterator.getEndIndex() for String. 3207935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see CharacterIterator#getEndIndex 3217935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3227935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int getEndIndex() 3237935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 3247935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return end; 3257935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3267935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3277935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 3287935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Implements CharacterIterator.getIndex() for String. 3297935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see CharacterIterator#getIndex 3307935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3317935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int getIndex() 3327935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 3337935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return pos; 3347935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3357935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3367935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 3377935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Compares the equality of two ReplaceableCharacterIterator objects. 3387935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @param obj the ReplaceableCharacterIterator object to be compared with. 3397935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return true if the given obj is the same as this 3407935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * ReplaceableCharacterIterator object; false otherwise. 3417935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3427935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public boolean equals(Object obj) 3437935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 3447935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (this == obj) { 3457935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return true; 3467935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3477935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!(obj instanceof ReplaceableCharacterIterator)) { 3487935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 3497935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3507935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3517935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ReplaceableCharacterIterator that = (ReplaceableCharacterIterator) obj; 3527935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3537935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (hashCode() != that.hashCode()) { 3547935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 3557935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3567935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (!text.equals(that.text)) { 3577935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 3587935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3597935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (pos != that.pos || begin != that.begin || end != that.end) { 3607935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return false; 3617935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3627935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return true; 3637935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3647935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3657935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 3667935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Computes a hashcode for this iterator. 3677935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return A hash code 3687935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3697935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public int hashCode() 3707935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 3717935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return text.hashCode() ^ pos ^ begin ^ end; 3727935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3737935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3747935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /** 3757935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * Creates a copy of this iterator. 3767935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @return A copy of this 3777935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3787935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public Object clone() 3797935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert { 3807935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert try { 3817935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert ReplaceableCharacterIterator other 3827935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert = (ReplaceableCharacterIterator) super.clone(); 3837935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert return other; 3847935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3857935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert catch (CloneNotSupportedException e) { 3867935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert throw new ICUCloneNotSupportedException(); 3877935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3887935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3897935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 3907935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 3917935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert /* (non-Javadoc) 3927935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert * @see com.ibm.icu.text.Transliterator#addSourceTargetSet(com.ibm.icu.text.UnicodeSet, com.ibm.icu.text.UnicodeSet, com.ibm.icu.text.UnicodeSet) 3937935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert */ 3947935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert @Override 3957935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert public void addSourceTargetSet(UnicodeSet inputFilter, UnicodeSet sourceSet, UnicodeSet targetSet) { 3967935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert UnicodeSet myFilter = getFilterAsUnicodeSet(inputFilter); 3977935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // Doesn't actually modify the source characters, so leave them alone. 3987935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert // add the characters inserted 3997935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert if (myFilter.size() != 0) { 4007935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert targetSet.addAll(insertion); 4017935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4027935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert } 4037935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert 4047935b1839a081ed19ae0d33029ad3c09632a2caaFredrik Roubert} 405