| /* |
| ******************************************************************************* |
| * |
| * Copyright (C) 2004-2010, International Business Machines |
| * Corporation and others. All Rights Reserved. |
| * |
| ******************************************************************************* |
| * file name: ReplaceableContextIterator.java |
| * encoding: US-ASCII |
| * tab size: 8 (not used) |
| * indentation:4 |
| * |
| * created on: 2005feb04 |
| * created by: Markus W. Scherer |
| * |
| * Implementation of UCaseProps.ContextIterator, iterates over a Replaceable. |
| * Java port of casetrn.cpp/utrans_rep_caseContextIterator(). |
| */ |
| |
| package com.ibm.icu.text; |
| |
| import com.ibm.icu.impl.UCaseProps; |
| |
| /** |
| * Implementation of UCaseProps.ContextIterator, iterates over a Replaceable. |
| * See casetrn.cpp/utrans_rep_caseContextIterator(). |
| * See also UCharacter.StringContextIterator. |
| */ |
| class ReplaceableContextIterator implements UCaseProps.ContextIterator { |
| /** |
| * Constructor. |
| * @param rep Replaceable to iterate over. |
| */ |
| ReplaceableContextIterator() { |
| this.rep=null; |
| limit=cpStart=cpLimit=index=contextStart=contextLimit=0; |
| dir=0; |
| reachedLimit=false; |
| } |
| |
| /** |
| * Set the text for iteration. |
| * @param rep Iteration text. |
| */ |
| public void setText(Replaceable rep) { |
| this.rep=rep; |
| limit=contextLimit=rep.length(); |
| cpStart=cpLimit=index=contextStart=0; |
| dir=0; |
| reachedLimit=false; |
| } |
| |
| /** |
| * Set the index where nextCaseMapCP() is to start iterating. |
| * @param index Iteration start index for nextCaseMapCP(). |
| */ |
| public void setIndex(int index) { |
| cpStart=cpLimit=index; |
| this.index=0; |
| dir=0; |
| reachedLimit=false; |
| } |
| |
| /** |
| * Get the index of where the code point currently being case-mapped starts. |
| * @return The start index of the current code point. |
| */ |
| public int getCaseMapCPStart() { |
| return cpStart; |
| } |
| |
| /** |
| * Set the iteration limit for nextCaseMapCP() to an index within the string. |
| * If the limit parameter is negative or past the string, then the |
| * string length is restored as the iteration limit. |
| * |
| * @param lim The iteration limit. |
| */ |
| public void setLimit(int lim) { |
| if(0<=lim && lim<=rep.length()) { |
| limit=lim; |
| } else { |
| limit=rep.length(); |
| } |
| reachedLimit=false; |
| } |
| |
| /** |
| * Set the start and limit indexes for context iteration with next(). |
| * @param contextStart Start of context for next(). |
| * @param contextLimit Limit of context for next(). |
| */ |
| public void setContextLimits(int contextStart, int contextLimit) { |
| if(contextStart<0) { |
| this.contextStart=0; |
| } else if(contextStart<=rep.length()) { |
| this.contextStart=contextStart; |
| } else { |
| this.contextStart=rep.length(); |
| } |
| if(contextLimit<this.contextStart) { |
| this.contextLimit=this.contextStart; |
| } else if(contextLimit<=rep.length()) { |
| this.contextLimit=contextLimit; |
| } else { |
| this.contextLimit=rep.length(); |
| } |
| reachedLimit=false; |
| } |
| |
| /** |
| * Iterate forward through the string to fetch the next code point |
| * to be case-mapped, and set the context indexes for it. |
| * |
| * @return The next code point to be case-mapped, or <0 when the iteration is done. |
| */ |
| public int nextCaseMapCP() { |
| int c; |
| if(cpLimit<limit) { |
| cpStart=cpLimit; |
| c=rep.char32At(cpLimit); |
| cpLimit+=UTF16.getCharCount(c); |
| return c; |
| } else { |
| return -1; |
| } |
| } |
| |
| /** |
| * Replace the current code point by its case mapping, |
| * and update the indexes. |
| * |
| * @param text Replacement text. |
| * @return The delta for the change of the text length. |
| */ |
| public int replace(String text) { |
| int delta=text.length()-(cpLimit-cpStart); |
| rep.replace(cpStart, cpLimit, text); |
| cpLimit+=delta; |
| limit+=delta; |
| contextLimit+=delta; |
| return delta; |
| } |
| |
| /** |
| * Did forward context iteration with next() reach the iteration limit? |
| * @return Boolean value. |
| */ |
| public boolean didReachLimit() { |
| return reachedLimit; |
| } |
| |
| // implement UCaseProps.ContextIterator |
| public void reset(int direction) { |
| if(direction>0) { |
| /* reset for forward iteration */ |
| this.dir=1; |
| index=cpLimit; |
| } else if(direction<0) { |
| /* reset for backward iteration */ |
| this.dir=-1; |
| index=cpStart; |
| } else { |
| // not a valid direction |
| this.dir=0; |
| index=0; |
| } |
| reachedLimit=false; |
| } |
| |
| public int next() { |
| int c; |
| |
| if(dir>0) { |
| if(index<contextLimit) { |
| c=rep.char32At(index); |
| index+=UTF16.getCharCount(c); |
| return c; |
| } else { |
| // forward context iteration reached the limit |
| reachedLimit=true; |
| } |
| } else if(dir<0 && index>contextStart) { |
| c=rep.char32At(index-1); |
| index-=UTF16.getCharCount(c); |
| return c; |
| } |
| return -1; |
| } |
| |
| // variables |
| protected Replaceable rep; |
| protected int index, limit, cpStart, cpLimit, contextStart, contextLimit; |
| protected int dir; // 0=initial state >0=forward <0=backward |
| protected boolean reachedLimit; |
| } |