1/* 2******************************************************************************* 3* 4* Copyright (C) 2004-2010, International Business Machines 5* Corporation and others. All Rights Reserved. 6* 7******************************************************************************* 8* file name: ReplaceableContextIterator.java 9* encoding: US-ASCII 10* tab size: 8 (not used) 11* indentation:4 12* 13* created on: 2005feb04 14* created by: Markus W. Scherer 15* 16* Implementation of UCaseProps.ContextIterator, iterates over a Replaceable. 17* Java port of casetrn.cpp/utrans_rep_caseContextIterator(). 18*/ 19 20package com.ibm.icu.text; 21 22import com.ibm.icu.impl.UCaseProps; 23 24/** 25 * Implementation of UCaseProps.ContextIterator, iterates over a Replaceable. 26 * See casetrn.cpp/utrans_rep_caseContextIterator(). 27 * See also UCharacter.StringContextIterator. 28 */ 29class ReplaceableContextIterator implements UCaseProps.ContextIterator { 30 /** 31 * Constructor. 32 * @param rep Replaceable to iterate over. 33 */ 34 ReplaceableContextIterator() { 35 this.rep=null; 36 limit=cpStart=cpLimit=index=contextStart=contextLimit=0; 37 dir=0; 38 reachedLimit=false; 39 } 40 41 /** 42 * Set the text for iteration. 43 * @param rep Iteration text. 44 */ 45 public void setText(Replaceable rep) { 46 this.rep=rep; 47 limit=contextLimit=rep.length(); 48 cpStart=cpLimit=index=contextStart=0; 49 dir=0; 50 reachedLimit=false; 51 } 52 53 /** 54 * Set the index where nextCaseMapCP() is to start iterating. 55 * @param index Iteration start index for nextCaseMapCP(). 56 */ 57 public void setIndex(int index) { 58 cpStart=cpLimit=index; 59 this.index=0; 60 dir=0; 61 reachedLimit=false; 62 } 63 64 /** 65 * Get the index of where the code point currently being case-mapped starts. 66 * @return The start index of the current code point. 67 */ 68 public int getCaseMapCPStart() { 69 return cpStart; 70 } 71 72 /** 73 * Set the iteration limit for nextCaseMapCP() to an index within the string. 74 * If the limit parameter is negative or past the string, then the 75 * string length is restored as the iteration limit. 76 * 77 * @param lim The iteration limit. 78 */ 79 public void setLimit(int lim) { 80 if(0<=lim && lim<=rep.length()) { 81 limit=lim; 82 } else { 83 limit=rep.length(); 84 } 85 reachedLimit=false; 86 } 87 88 /** 89 * Set the start and limit indexes for context iteration with next(). 90 * @param contextStart Start of context for next(). 91 * @param contextLimit Limit of context for next(). 92 */ 93 public void setContextLimits(int contextStart, int contextLimit) { 94 if(contextStart<0) { 95 this.contextStart=0; 96 } else if(contextStart<=rep.length()) { 97 this.contextStart=contextStart; 98 } else { 99 this.contextStart=rep.length(); 100 } 101 if(contextLimit<this.contextStart) { 102 this.contextLimit=this.contextStart; 103 } else if(contextLimit<=rep.length()) { 104 this.contextLimit=contextLimit; 105 } else { 106 this.contextLimit=rep.length(); 107 } 108 reachedLimit=false; 109 } 110 111 /** 112 * Iterate forward through the string to fetch the next code point 113 * to be case-mapped, and set the context indexes for it. 114 * 115 * @return The next code point to be case-mapped, or <0 when the iteration is done. 116 */ 117 public int nextCaseMapCP() { 118 int c; 119 if(cpLimit<limit) { 120 cpStart=cpLimit; 121 c=rep.char32At(cpLimit); 122 cpLimit+=UTF16.getCharCount(c); 123 return c; 124 } else { 125 return -1; 126 } 127 } 128 129 /** 130 * Replace the current code point by its case mapping, 131 * and update the indexes. 132 * 133 * @param text Replacement text. 134 * @return The delta for the change of the text length. 135 */ 136 public int replace(String text) { 137 int delta=text.length()-(cpLimit-cpStart); 138 rep.replace(cpStart, cpLimit, text); 139 cpLimit+=delta; 140 limit+=delta; 141 contextLimit+=delta; 142 return delta; 143 } 144 145 /** 146 * Did forward context iteration with next() reach the iteration limit? 147 * @return Boolean value. 148 */ 149 public boolean didReachLimit() { 150 return reachedLimit; 151 } 152 153 // implement UCaseProps.ContextIterator 154 public void reset(int direction) { 155 if(direction>0) { 156 /* reset for forward iteration */ 157 this.dir=1; 158 index=cpLimit; 159 } else if(direction<0) { 160 /* reset for backward iteration */ 161 this.dir=-1; 162 index=cpStart; 163 } else { 164 // not a valid direction 165 this.dir=0; 166 index=0; 167 } 168 reachedLimit=false; 169 } 170 171 public int next() { 172 int c; 173 174 if(dir>0) { 175 if(index<contextLimit) { 176 c=rep.char32At(index); 177 index+=UTF16.getCharCount(c); 178 return c; 179 } else { 180 // forward context iteration reached the limit 181 reachedLimit=true; 182 } 183 } else if(dir<0 && index>contextStart) { 184 c=rep.char32At(index-1); 185 index-=UTF16.getCharCount(c); 186 return c; 187 } 188 return -1; 189 } 190 191 // variables 192 protected Replaceable rep; 193 protected int index, limit, cpStart, cpLimit, contextStart, contextLimit; 194 protected int dir; // 0=initial state >0=forward <0=backward 195 protected boolean reachedLimit; 196} 197