416ddaf361b3d7cd84b0bb2c9866ccf1ad01086c
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / ui / text / DocumentCharacterIterator.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2005 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.ui.text;
12
13 import java.text.CharacterIterator;
14
15 import org.eclipse.jface.text.Assert;
16 import org.eclipse.jface.text.BadLocationException;
17 import org.eclipse.jface.text.IDocument;
18
19 /**
20  * An <code>IDocument</code> based implementation of
21  * <code>CharacterIterator</code> and <code>CharSequence</code>. Note that
22  * the supplied document is not copied; if the document is modified during the
23  * lifetime of a <code>DocumentCharacterIterator</code>, the methods
24  * returning document content may not always return the same values. Also, if
25  * accessing the document fails with a {@link BadLocationException}, any of
26  * <code>CharacterIterator</code> methods as well as <code>charAt</code>may
27  * return {@link CharacterIterator#DONE}.
28  * 
29  * @since 3.0
30  */
31 public class DocumentCharacterIterator implements CharacterIterator,
32                 CharSequence {
33
34         private int fIndex = -1;
35
36         private final IDocument fDocument;
37
38         private final int fFirst;
39
40         private final int fLast;
41
42         private void invariant() {
43                 Assert.isTrue(fIndex >= fFirst);
44                 Assert.isTrue(fIndex <= fLast);
45         }
46
47         /**
48          * Creates an iterator for the entire document.
49          * 
50          * @param document
51          *            the document backing this iterator
52          */
53         public DocumentCharacterIterator(IDocument document) {
54                 this(document, 0);
55         }
56
57         /**
58          * Creates an iterator, starting at offset <code>first</code>.
59          * 
60          * @param document
61          *            the document backing this iterator
62          * @param first
63          *            the first character to consider
64          * @throws IllegalArgumentException
65          *             if the indices are out of bounds
66          */
67         public DocumentCharacterIterator(IDocument document, int first)
68                         throws IllegalArgumentException {
69                 this(document, first, document.getLength());
70         }
71
72         /**
73          * Creates an iterator for the document contents from <code>first</code>
74          * (inclusive) to <code>last</code> (exclusive).
75          * 
76          * @param document
77          *            the document backing this iterator
78          * @param first
79          *            the first character to consider
80          * @param last
81          *            the last character index to consider
82          * @throws IllegalArgumentException
83          *             if the indices are out of bounds
84          */
85         public DocumentCharacterIterator(IDocument document, int first, int last)
86                         throws IllegalArgumentException {
87                 if (document == null)
88                         throw new NullPointerException();
89                 if (first < 0 || first > last)
90                         throw new IllegalArgumentException();
91                 if (last > document.getLength())
92                         throw new IllegalArgumentException();
93                 fDocument = document;
94                 fFirst = first;
95                 fLast = last;
96                 fIndex = first;
97                 invariant();
98         }
99
100         /*
101          * @see java.text.CharacterIterator#first()
102          */
103         public char first() {
104                 return setIndex(getBeginIndex());
105         }
106
107         /*
108          * @see java.text.CharacterIterator#last()
109          */
110         public char last() {
111                 if (fFirst == fLast)
112                         return setIndex(getEndIndex());
113                 else
114                         return setIndex(getEndIndex() - 1);
115         }
116
117         /*
118          * @see java.text.CharacterIterator#current()
119          */
120         public char current() {
121                 if (fIndex >= fFirst && fIndex < fLast)
122                         try {
123                                 return fDocument.getChar(fIndex);
124                         } catch (BadLocationException e) {
125                                 // ignore
126                         }
127                 return DONE;
128         }
129
130         /*
131          * @see java.text.CharacterIterator#next()
132          */
133         public char next() {
134                 return setIndex(Math.min(fIndex + 1, getEndIndex()));
135         }
136
137         /*
138          * @see java.text.CharacterIterator#previous()
139          */
140         public char previous() {
141                 if (fIndex > getBeginIndex()) {
142                         return setIndex(fIndex - 1);
143                 } else {
144                         return DONE;
145                 }
146         }
147
148         /*
149          * @see java.text.CharacterIterator#setIndex(int)
150          */
151         public char setIndex(int position) {
152                 if (position >= getBeginIndex() && position <= getEndIndex())
153                         fIndex = position;
154                 else
155                         throw new IllegalArgumentException();
156
157                 invariant();
158                 return current();
159         }
160
161         /*
162          * @see java.text.CharacterIterator#getBeginIndex()
163          */
164         public int getBeginIndex() {
165                 return fFirst;
166         }
167
168         /*
169          * @see java.text.CharacterIterator#getEndIndex()
170          */
171         public int getEndIndex() {
172                 return fLast;
173         }
174
175         /*
176          * @see java.text.CharacterIterator#getIndex()
177          */
178         public int getIndex() {
179                 return fIndex;
180         }
181
182         /*
183          * @see java.text.CharacterIterator#clone()
184          */
185         public Object clone() {
186                 try {
187                         return super.clone();
188                 } catch (CloneNotSupportedException e) {
189                         throw new InternalError();
190                 }
191         }
192
193         /*
194          * @see java.lang.CharSequence#length()
195          */
196         public int length() {
197                 return getEndIndex() - getBeginIndex();
198         }
199
200         /**
201          * {@inheritDoc}
202          * <p>
203          * Note that, if the document is modified concurrently, this method may
204          * return {@link CharacterIterator#DONE} if a {@link BadLocationException}
205          * was thrown when accessing the backing document.
206          * </p>
207          * 
208          * @param index
209          *            {@inheritDoc}
210          * @return {@inheritDoc}
211          */
212         public char charAt(int index) {
213                 if (index >= 0 && index < length())
214                         try {
215                                 return fDocument.getChar(getBeginIndex() + index);
216                         } catch (BadLocationException e) {
217                                 // ignore and return DONE
218                                 return DONE;
219                         }
220                 else
221                         throw new IndexOutOfBoundsException();
222         }
223
224         /*
225          * @see java.lang.CharSequence#subSequence(int, int)
226          */
227         public CharSequence subSequence(int start, int end) {
228                 if (start < 0)
229                         throw new IndexOutOfBoundsException();
230                 if (end < start)
231                         throw new IndexOutOfBoundsException();
232                 if (end > length())
233                         throw new IndexOutOfBoundsException();
234                 return new DocumentCharacterIterator(fDocument,
235                                 getBeginIndex() + start, getBeginIndex() + end);
236         }
237 }