下面列出了java.text.CharacterIterator#setIndex ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Advances the iterator one step backwards.
* @return The position of the last boundary position before the
* current iteration position
*/
@Override
public int previous() {
CharacterIterator text = getText();
// if we have cached break positions and we're still in the range
// covered by them, just move one step backward in the cache
if (cachedBreakPositions != null && positionInCache > 0) {
--positionInCache;
text.setIndex(cachedBreakPositions[positionInCache]);
return cachedBreakPositions[positionInCache];
}
// otherwise, dump the cache and use the inherited previous() method to move
// backward. This may fill up the cache with new break positions, in which
// case we have to mark our position in the cache
else {
cachedBreakPositions = null;
int result = super.previous();
if (cachedBreakPositions != null) {
positionInCache = cachedBreakPositions.length - 2;
}
return result;
}
}
/**
*
* @return -1 if <var>iterator</var> does not contain this pattern.
*/
public int matches(CharacterIterator iterator, int start, int limit) {
if (this.ignoreCase) return this.matchesIgnoreCase(iterator, start, limit);
int plength = this.pattern.length;
if (plength == 0) return start;
int index = start+plength;
while (index <= limit) {
int pindex = plength;
int nindex = index+1;
char ch;
do {
if ((ch = iterator.setIndex(--index)) != this.pattern[--pindex])
break;
if (pindex == 0)
return index;
} while (pindex > 0);
index += this.shiftTable[ch % this.shiftTable.length]+1;
if (index < nindex) index = nindex;
}
return -1;
}
/**
* Advances the iterator one step backwards.
* @return The position of the last boundary position before the
* current iteration position
*/
@Override
public int previous() {
CharacterIterator text = getText();
// if we have cached break positions and we're still in the range
// covered by them, just move one step backward in the cache
if (cachedBreakPositions != null && positionInCache > 0) {
--positionInCache;
text.setIndex(cachedBreakPositions[positionInCache]);
return cachedBreakPositions[positionInCache];
}
// otherwise, dump the cache and use the inherited previous() method to move
// backward. This may fill up the cache with new break positions, in which
// case we have to mark our position in the cache
else {
cachedBreakPositions = null;
int result = super.previous();
if (cachedBreakPositions != null) {
positionInCache = cachedBreakPositions.length - 2;
}
return result;
}
}
/**
* Set the iterator to analyze a new piece of text. This function resets
* the current iteration position to the beginning of the text.
* @param newText An iterator over the text to analyze.
*/
@Override
public void setText(CharacterIterator newText) {
// Test iterator to see if we need to wrap it in a SafeCharIterator.
// The correct behavior for CharacterIterators is to allow the
// position to be set to the endpoint of the iterator. Many
// CharacterIterators do not uphold this, so this is a workaround
// to permit them to use this class.
int end = newText.getEndIndex();
boolean goodIterator;
try {
newText.setIndex(end); // some buggy iterators throw an exception here
goodIterator = newText.getIndex() == end;
}
catch(IllegalArgumentException e) {
goodIterator = false;
}
if (goodIterator) {
text = newText;
}
else {
text = new SafeCharIterator(newText);
}
text.first();
cachedLastKnownBreak = BreakIterator.DONE;
}
@Override
public int findBreaks(CharacterIterator text, int startPos, int endPos,
int breakType, DequeI foundBreaks) {
int result = 0;
// Find the span of characters included in the set.
// The span to break begins at the current position int the text, and
// extends towards the start or end of the text, depending on 'reverse'.
int start = text.getIndex();
int current;
int rangeStart;
int rangeEnd;
int c = CharacterIteration.current32(text);
while ((current = text.getIndex()) < endPos && fSet.contains(c)) {
CharacterIteration.next32(text);
c = CharacterIteration.current32(text);
}
rangeStart = start;
rangeEnd = current;
// if (breakType >= 0 && breakType < 32 && (((uint32_t)1 << breakType) & fTypes)) {
// TODO: Why does icu4c have this?
result = divideUpDictionaryRange(text, rangeStart, rangeEnd, foundBreaks);
text.setIndex(current);
return result;
}
/**
* Sets the current iteration position to the end of the text.
* (i.e., the CharacterIterator's ending offset).
* @return The text's past-the-end offset.
*/
@Override
public int last() {
CharacterIterator t = getText();
// I'm not sure why, but t.last() returns the offset of the last character,
// rather than the past-the-end offset
t.setIndex(t.getEndIndex());
return t.getIndex();
}
public boolean backUp(CharacterIterator fIter) {
if (current > 0) {
fIter.setIndex(offset + lengths[--current]);
return true;
}
return false;
}
/**
* Sets the current iteration position to the first boundary position after
* the specified position.
* @param offset The position to begin searching forward from
* @return The position of the first boundary after "offset"
*/
public int following(int offset) {
CharacterIterator text = getText();
checkOffset(offset, text);
// if we have no cached break positions, or if "offset" is outside the
// range covered by the cache, then dump the cache and call our
// inherited following() method. This will call other methods in this
// class that may refresh the cache.
if (cachedBreakPositions == null || offset < cachedBreakPositions[0] ||
offset >= cachedBreakPositions[cachedBreakPositions.length - 1]) {
cachedBreakPositions = null;
return super.following(offset);
}
// on the other hand, if "offset" is within the range covered by the
// cache, then just search the cache for the first break position
// after "offset"
else {
positionInCache = 0;
while (positionInCache < cachedBreakPositions.length
&& offset >= cachedBreakPositions[positionInCache]) {
++positionInCache;
}
text.setIndex(cachedBreakPositions[positionInCache]);
return text.getIndex();
}
}
/**
* Sets the current iteration position to the first boundary position after
* the specified position.
* @param offset The position to begin searching forward from
* @return The position of the first boundary after "offset"
*/
@Override
public int following(int offset) {
CharacterIterator text = getText();
checkOffset(offset, text);
// if we have no cached break positions, or if "offset" is outside the
// range covered by the cache, then dump the cache and call our
// inherited following() method. This will call other methods in this
// class that may refresh the cache.
if (cachedBreakPositions == null || offset < cachedBreakPositions[0] ||
offset >= cachedBreakPositions[cachedBreakPositions.length - 1]) {
cachedBreakPositions = null;
return super.following(offset);
}
// on the other hand, if "offset" is within the range covered by the
// cache, then just search the cache for the first break position
// after "offset"
else {
positionInCache = 0;
while (positionInCache < cachedBreakPositions.length
&& offset >= cachedBreakPositions[positionInCache]) {
++positionInCache;
}
text.setIndex(cachedBreakPositions[positionInCache]);
return text.getIndex();
}
}
/**
* Sets the current iteration position to the end of the text.
* (i.e., the CharacterIterator's ending offset).
* @return The text's past-the-end offset.
*/
@Override
public int last() {
CharacterIterator t = getText();
// I'm not sure why, but t.last() returns the offset of the last character,
// rather than the past-the-end offset
t.setIndex(t.getEndIndex());
return t.getIndex();
}
/**
* Sets the iterator to refer to the last boundary position before the
* specified position.
* @offset The position to begin searching for a break from.
* @return The position of the last boundary before the starting position.
*/
@Override
public int preceding(int offset) {
// if we start by updating the current iteration position to the
// position specified by the caller, we can just use previous()
// to carry out this operation
CharacterIterator text = getText();
checkOffset(offset, text);
text.setIndex(offset);
return previous();
}
/**
* Sets the current iteration position to the first boundary position after
* the specified position.
* @param offset The position to begin searching forward from
* @return The position of the first boundary after "offset"
*/
@Override
public int following(int offset) {
CharacterIterator text = getText();
checkOffset(offset, text);
// if we have no cached break positions, or if "offset" is outside the
// range covered by the cache, then dump the cache and call our
// inherited following() method. This will call other methods in this
// class that may refresh the cache.
if (cachedBreakPositions == null || offset < cachedBreakPositions[0] ||
offset >= cachedBreakPositions[cachedBreakPositions.length - 1]) {
cachedBreakPositions = null;
return super.following(offset);
}
// on the other hand, if "offset" is within the range covered by the
// cache, then just search the cache for the first break position
// after "offset"
else {
positionInCache = 0;
while (positionInCache < cachedBreakPositions.length
&& offset >= cachedBreakPositions[positionInCache]) {
++positionInCache;
}
text.setIndex(cachedBreakPositions[positionInCache]);
return text.getIndex();
}
}
static final String substring(CharacterIterator iterator, int begin, int end) {
char[] src = new char[end-begin];
for (int i = 0; i < src.length; i ++)
src[i] = iterator.setIndex(i+begin);
return new String(src);
}
@Override
public Object clone() {
CharacterIterator ret = new CharSequenceCharacterIterator(charSequence);
ret.setIndex(index);
return ret;
}
/**
* Moves the iterator backwards, to the last boundary preceding this one.
* @return The position of the last boundary position preceding this one.
* @stable ICU 2.0
*/
@Override
public int previous() {
int result;
int startPos;
CharacterIterator text = getText();
fLastStatusIndexValid = false;
// if we have cached break positions and we're still in the range
// covered by them, just move one step backward in the cache
if (fCachedBreakPositions != null) {
if (fPositionInCache > 0) {
--fPositionInCache;
// If we're at the beginning of the cache, need to reevaluate the
// rule status
if (fPositionInCache <= 0) {
fLastStatusIndexValid = false;
}
int pos = fCachedBreakPositions[fPositionInCache];
text.setIndex(pos);
return pos;
} else {
reset();
}
}
// if we're already sitting at the beginning of the text, return DONE
startPos = current();
if (fText == null || startPos == fText.getBeginIndex()) {
fLastRuleStatusIndex = 0;
fLastStatusIndexValid = true;
return BreakIterator.DONE;
}
// Rules with an exact reverse table are handled here.
if (fRData.fSRTable != null || fRData.fSFTable != null) {
result = handlePrevious(fRData.fRTable);
if (fDictionaryCharCount > 0) {
result = checkDictionary(result, startPos, true);
}
return result;
}
// old rule syntax
// set things up. handlePrevious() will back us up to some valid
// break position before the current position (we back our internal
// iterator up one step to prevent handlePrevious() from returning
// the current position), but not necessarily the last one before
// where we started
int start = current();
previous32(fText);
int lastResult = handlePrevious(fRData.fRTable);
if (lastResult == BreakIterator.DONE) {
lastResult = fText.getBeginIndex();
fText.setIndex(lastResult);
}
result = lastResult;
int lastTag = 0;
boolean breakTagValid = false;
// iterate forward from the known break position until we pass our
// starting point. The last break position before the starting
// point is our return value
for (;;) {
result = next();
if (result == BreakIterator.DONE || result >= start) {
break;
}
lastResult = result;
lastTag = fLastRuleStatusIndex;
breakTagValid = true;
}
// fLastBreakTag wants to have the value for section of text preceding
// the result position that we are to return (in lastResult.) If
// the backwards rules overshot and the above loop had to do two or more
// handleNext()s to move up to the desired return position, we will have a valid
// tag value. But, if handlePrevious() took us to exactly the correct result position,
// we wont have a tag value for that position, which is only set by handleNext().
// Set the current iteration position to be the last break position
// before where we started, and then return that value.
fText.setIndex(lastResult);
fLastRuleStatusIndex = lastTag; // for use by getRuleStatus()
fLastStatusIndexValid = breakTagValid;
return lastResult;
}
/**
* This method is the actual implementation of the next() method. All iteration
* vectors through here. This method initializes the state machine to state 1
* and advances through the text character by character until we reach the end
* of the text or the state machine transitions to state 0. We update our return
* value every time the state machine passes through a possible end state.
*/
protected int handleNext() {
// if we're already at the end of the text, return DONE.
CharacterIterator text = getText();
if (text.getIndex() == text.getEndIndex()) {
return BreakIterator.DONE;
}
// no matter what, we always advance at least one character forward
int result = getNextIndex();
int lookaheadResult = 0;
// begin in state 1
int state = START_STATE;
int category;
int c = getCurrent();
// loop until we reach the end of the text or transition to state 0
while (c != CharacterIterator.DONE && state != STOP_STATE) {
// look up the current character's character category (which tells us
// which column in the state table to look at)
category = lookupCategory(c);
// if the character isn't an ignore character, look up a state
// transition in the state table
if (category != IGNORE) {
state = lookupState(state, category);
}
// if the state we've just transitioned to is a lookahead state,
// (but not also an end state), save its position. If it's
// both a lookahead state and an end state, update the break position
// to the last saved lookup-state position
if (lookaheadStates[state]) {
if (endStates[state]) {
result = lookaheadResult;
}
else {
lookaheadResult = getNextIndex();
}
}
// otherwise, if the state we've just transitioned to is an accepting
// state, update the break position to be the current iteration position
else {
if (endStates[state]) {
result = getNextIndex();
}
}
c = getNext();
}
// if we've run off the end of the text, and the very last character took us into
// a lookahead state, advance the break position to the lookahead position
// (the theory here is that if there are no characters at all after the lookahead
// position, that always matches the lookahead criteria)
if (c == CharacterIterator.DONE && lookaheadResult == text.getEndIndex()) {
result = lookaheadResult;
}
text.setIndex(result);
return result;
}
static final String substring(CharacterIterator iterator, int begin, int end) {
char[] src = new char[end-begin];
for (int i = 0; i < src.length; i ++)
src[i] = iterator.setIndex(i+begin);
return new String(src);
}
/**
* This method is the actual implementation of the next() method. All iteration
* vectors through here. This method initializes the state machine to state 1
* and advances through the text character by character until we reach the end
* of the text or the state machine transitions to state 0. We update our return
* value every time the state machine passes through a possible end state.
*/
protected int handleNext() {
// if we're already at the end of the text, return DONE.
CharacterIterator text = getText();
if (text.getIndex() == text.getEndIndex()) {
return BreakIterator.DONE;
}
// no matter what, we always advance at least one character forward
int result = getNextIndex();
int lookaheadResult = 0;
// begin in state 1
int state = START_STATE;
int category;
int c = getCurrent();
// loop until we reach the end of the text or transition to state 0
while (c != CharacterIterator.DONE && state != STOP_STATE) {
// look up the current character's character category (which tells us
// which column in the state table to look at)
category = lookupCategory(c);
// if the character isn't an ignore character, look up a state
// transition in the state table
if (category != IGNORE) {
state = lookupState(state, category);
}
// if the state we've just transitioned to is a lookahead state,
// (but not also an end state), save its position. If it's
// both a lookahead state and an end state, update the break position
// to the last saved lookup-state position
if (lookaheadStates[state]) {
if (endStates[state]) {
result = lookaheadResult;
}
else {
lookaheadResult = getNextIndex();
}
}
// otherwise, if the state we've just transitioned to is an accepting
// state, update the break position to be the current iteration position
else {
if (endStates[state]) {
result = getNextIndex();
}
}
c = getNext();
}
// if we've run off the end of the text, and the very last character took us into
// a lookahead state, advance the break position to the lookahead position
// (the theory here is that if there are no characters at all after the lookahead
// position, that always matches the lookahead criteria)
if (c == CharacterIterator.DONE && lookaheadResult == text.getEndIndex()) {
result = lookaheadResult;
}
text.setIndex(result);
return result;
}
/**
* Returns the logical bounds of the characters indexed in the
* specified {@link CharacterIterator} in the
* specified <code>FontRenderContext</code>. The logical bounds
* contains the origin, ascent, advance, and height, which includes
* the leading. The logical bounds does not always enclose all the
* text. For example, in some languages and in some fonts, accent
* marks can be positioned above the ascent or below the descent.
* To obtain a visual bounding box, which encloses all the text,
* use the {@link TextLayout#getBounds() getBounds} method of
* <code>TextLayout</code>.
* <p>Note: The returned bounds is in baseline-relative coordinates
* (see {@link java.awt.Font class notes}).
* @param ci the specified <code>CharacterIterator</code>
* @param beginIndex the initial offset in <code>ci</code>
* @param limit the end offset in <code>ci</code>
* @param frc the specified <code>FontRenderContext</code>
* @return a <code>Rectangle2D</code> that is the bounding box of the
* characters indexed in the specified <code>CharacterIterator</code>
* in the specified <code>FontRenderContext</code>.
* @see FontRenderContext
* @see Font#createGlyphVector
* @since 1.2
* @throws IndexOutOfBoundsException if <code>beginIndex</code> is
* less than the start index of <code>ci</code>, or
* <code>limit</code> is greater than the end index of
* <code>ci</code>, or <code>beginIndex</code> is greater
* than <code>limit</code>
*/
public Rectangle2D getStringBounds(CharacterIterator ci,
int beginIndex, int limit,
FontRenderContext frc) {
int start = ci.getBeginIndex();
int end = ci.getEndIndex();
if (beginIndex < start) {
throw new IndexOutOfBoundsException("beginIndex: " + beginIndex);
}
if (limit > end) {
throw new IndexOutOfBoundsException("limit: " + limit);
}
if (beginIndex > limit) {
throw new IndexOutOfBoundsException("range length: " +
(limit - beginIndex));
}
char[] arr = new char[limit - beginIndex];
ci.setIndex(beginIndex);
for(int idx = 0; idx < arr.length; idx++) {
arr[idx] = ci.current();
ci.next();
}
return getStringBounds(arr,0,arr.length,frc);
}
/**
* Returns the logical bounds of the characters indexed in the
* specified {@link CharacterIterator} in the
* specified <code>FontRenderContext</code>. The logical bounds
* contains the origin, ascent, advance, and height, which includes
* the leading. The logical bounds does not always enclose all the
* text. For example, in some languages and in some fonts, accent
* marks can be positioned above the ascent or below the descent.
* To obtain a visual bounding box, which encloses all the text,
* use the {@link TextLayout#getBounds() getBounds} method of
* <code>TextLayout</code>.
* <p>Note: The returned bounds is in baseline-relative coordinates
* (see {@link java.awt.Font class notes}).
* @param ci the specified <code>CharacterIterator</code>
* @param beginIndex the initial offset in <code>ci</code>
* @param limit the end offset in <code>ci</code>
* @param frc the specified <code>FontRenderContext</code>
* @return a <code>Rectangle2D</code> that is the bounding box of the
* characters indexed in the specified <code>CharacterIterator</code>
* in the specified <code>FontRenderContext</code>.
* @see FontRenderContext
* @see Font#createGlyphVector
* @since 1.2
* @throws IndexOutOfBoundsException if <code>beginIndex</code> is
* less than the start index of <code>ci</code>, or
* <code>limit</code> is greater than the end index of
* <code>ci</code>, or <code>beginIndex</code> is greater
* than <code>limit</code>
*/
public Rectangle2D getStringBounds(CharacterIterator ci,
int beginIndex, int limit,
FontRenderContext frc) {
int start = ci.getBeginIndex();
int end = ci.getEndIndex();
if (beginIndex < start) {
throw new IndexOutOfBoundsException("beginIndex: " + beginIndex);
}
if (limit > end) {
throw new IndexOutOfBoundsException("limit: " + limit);
}
if (beginIndex > limit) {
throw new IndexOutOfBoundsException("range length: " +
(limit - beginIndex));
}
char[] arr = new char[limit - beginIndex];
ci.setIndex(beginIndex);
for(int idx = 0; idx < arr.length; idx++) {
arr[idx] = ci.current();
ci.next();
}
return getStringBounds(arr,0,arr.length,frc);
}