| /******************************************************************************* |
| * Copyright (c) 2000, 2005 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.dltk.internal.ui.text; |
| |
| import java.text.CharacterIterator; |
| |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.jface.text.BadLocationException; |
| import org.eclipse.jface.text.IDocument; |
| |
| |
| /** |
| * An <code>IDocument</code> based implementation of |
| * <code>CharacterIterator</code> and <code>CharSequence</code>. Note that |
| * the supplied document is not copied; if the document is modified during the |
| * lifetime of a <code>DocumentCharacterIterator</code>, the methods |
| * returning document content may not always return the same values. Also, if |
| * accessing the document fails with a {@link BadLocationException}, any of |
| * <code>CharacterIterator</code> methods as well as <code>charAt</code>may |
| * return {@link CharacterIterator#DONE}. |
| * |
| * |
| */ |
| public class DocumentCharacterIterator implements CharacterIterator, CharSequence { |
| |
| private int fIndex= -1; |
| private final IDocument fDocument; |
| private final int fFirst; |
| private final int fLast; |
| |
| private void invariant() { |
| Assert.isTrue(fIndex >= fFirst); |
| Assert.isTrue(fIndex <= fLast); |
| } |
| |
| /** |
| * Creates an iterator for the entire document. |
| * |
| * @param document the document backing this iterator |
| */ |
| public DocumentCharacterIterator(IDocument document) { |
| this(document, 0); |
| } |
| |
| /** |
| * Creates an iterator, starting at offset <code>first</code>. |
| * |
| * @param document the document backing this iterator |
| * @param first the first character to consider |
| * @throws IllegalArgumentException if the indices are out of bounds |
| */ |
| public DocumentCharacterIterator(IDocument document, int first) throws IllegalArgumentException { |
| this(document, first, document.getLength()); |
| } |
| |
| /** |
| * Creates an iterator for the document contents from <code>first</code> |
| * (inclusive) to <code>last</code> (exclusive). |
| * |
| * @param document the document backing this iterator |
| * @param first the first character to consider |
| * @param last the last character index to consider |
| * @throws IllegalArgumentException if the indices are out of bounds |
| */ |
| public DocumentCharacterIterator(IDocument document, int first, int last) throws IllegalArgumentException { |
| if (document == null) |
| throw new NullPointerException(); |
| if (first < 0 || first > last) |
| throw new IllegalArgumentException(); |
| if (last > document.getLength()) |
| throw new IllegalArgumentException(); |
| fDocument= document; |
| fFirst= first; |
| fLast= last; |
| fIndex= first; |
| invariant(); |
| } |
| |
| /* |
| * @see java.text.CharacterIterator#first() |
| */ |
| public char first() { |
| return setIndex(getBeginIndex()); |
| } |
| |
| /* |
| * @see java.text.CharacterIterator#last() |
| */ |
| public char last() { |
| if (fFirst == fLast) |
| return setIndex(getEndIndex()); |
| else |
| return setIndex(getEndIndex() - 1); |
| } |
| |
| /* |
| * @see java.text.CharacterIterator#current() |
| */ |
| public char current() { |
| if (fIndex >= fFirst && fIndex < fLast) |
| try { |
| return fDocument.getChar(fIndex); |
| } catch (BadLocationException e) { |
| // ignore |
| } |
| return DONE; |
| } |
| |
| /* |
| * @see java.text.CharacterIterator#next() |
| */ |
| public char next() { |
| return setIndex(Math.min(fIndex + 1, getEndIndex())); |
| } |
| |
| /* |
| * @see java.text.CharacterIterator#previous() |
| */ |
| public char previous() { |
| if (fIndex > getBeginIndex()) { |
| return setIndex(fIndex - 1); |
| } else { |
| return DONE; |
| } |
| } |
| |
| /* |
| * @see java.text.CharacterIterator#setIndex(int) |
| */ |
| public char setIndex(int position) { |
| if (position >= getBeginIndex() && position <= getEndIndex()) |
| fIndex= position; |
| else |
| throw new IllegalArgumentException(); |
| |
| invariant(); |
| return current(); |
| } |
| |
| /* |
| * @see java.text.CharacterIterator#getBeginIndex() |
| */ |
| public int getBeginIndex() { |
| return fFirst; |
| } |
| |
| /* |
| * @see java.text.CharacterIterator#getEndIndex() |
| */ |
| public int getEndIndex() { |
| return fLast; |
| } |
| |
| /* |
| * @see java.text.CharacterIterator#getIndex() |
| */ |
| public int getIndex() { |
| return fIndex; |
| } |
| |
| /* |
| * @see java.text.CharacterIterator#clone() |
| */ |
| public Object clone() { |
| try { |
| return super.clone(); |
| } catch (CloneNotSupportedException e) { |
| throw new InternalError(); |
| } |
| } |
| |
| /* |
| * @see java.lang.CharSequence#length() |
| */ |
| public int length() { |
| return getEndIndex() - getBeginIndex(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| * <p> |
| * Note that, if the document is modified concurrently, this method may |
| * return {@link CharacterIterator#DONE} if a {@link BadLocationException} |
| * was thrown when accessing the backing document. |
| * </p> |
| * |
| * @param index {@inheritDoc} |
| * @return {@inheritDoc} |
| */ |
| public char charAt(int index) { |
| if (index >= 0 && index < length()) |
| try { |
| return fDocument.getChar(getBeginIndex() + index); |
| } catch (BadLocationException e) { |
| // ignore and return DONE |
| return DONE; |
| } |
| else |
| throw new IndexOutOfBoundsException(); |
| } |
| |
| /* |
| * @see java.lang.CharSequence#subSequence(int, int) |
| */ |
| public CharSequence subSequence(int start, int end) { |
| if (start < 0) |
| throw new IndexOutOfBoundsException(); |
| if (end < start) |
| throw new IndexOutOfBoundsException(); |
| if (end > length()) |
| throw new IndexOutOfBoundsException(); |
| return new DocumentCharacterIterator(fDocument, getBeginIndex() + start, getBeginIndex() + end); |
| } |
| } |