cd6833f4649a255293dccb4f58ee312a68f24bfb
[phpeclipse.git] / net.sourceforge.phpeclipse.ui / src / net / sourceforge / phpdt / internal / ui / text / BufferedDocumentScanner.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.ui.text;
12
13 import org.eclipse.jface.text.Assert;
14 import org.eclipse.jface.text.BadLocationException;
15 import org.eclipse.jface.text.IDocument;
16 import org.eclipse.jface.text.rules.ICharacterScanner;
17
18 /**
19  * A buffered document scanner. The buffer always contains a section of a fixed
20  * size of the document to be scanned.
21  */
22
23 public final class BufferedDocumentScanner implements ICharacterScanner {
24
25         /** The document being scanned. */
26         private IDocument fDocument;
27
28         /** The offset of the document range to scan. */
29         private int fRangeOffset;
30
31         /** The length of the document range to scan. */
32         private int fRangeLength;
33
34         /** The delimiters of the document. */
35         private char[][] fDelimiters;
36
37         /** The buffer. */
38         private final char[] fBuffer;
39
40         /** The offset of the buffer within the document. */
41         private int fBufferOffset;
42
43         /** The valid length of the buffer for access. */
44         private int fBufferLength;
45
46         /** The offset of the scanner within the buffer. */
47         private int fOffset;
48
49         /**
50          * Creates a new buffered document scanner. The buffer size is set to the
51          * given number of characters.
52          * 
53          * @param size
54          *            the buffer size
55          */
56         public BufferedDocumentScanner(int size) {
57                 Assert.isTrue(size >= 1);
58                 fBuffer = new char[size];
59         }
60
61         /**
62          * Fills the buffer with the contens of the document starting at the given
63          * offset.
64          * 
65          * @param offset
66          *            the document offset at which the buffer starts
67          */
68         private final void updateBuffer(int offset) {
69
70                 fBufferOffset = offset;
71
72                 if (fBufferOffset + fBuffer.length > fRangeOffset + fRangeLength)
73                         fBufferLength = fRangeLength - (fBufferOffset - fRangeOffset);
74                 else
75                         fBufferLength = fBuffer.length;
76
77                 try {
78                         final String content = fDocument.get(fBufferOffset, fBufferLength);
79                         if (content != null) {
80                                 content.getChars(0, fBufferLength, fBuffer, 0);
81                         }
82                 } catch (BadLocationException e) {
83                 }
84         }
85
86         /**
87          * Configures the scanner by providing access to the document range over
88          * which to scan.
89          * 
90          * @param document
91          *            the document to scan
92          * @param offset
93          *            the offset of the document range to scan
94          * @param length
95          *            the length of the document range to scan
96          */
97         public final void setRange(IDocument document, int offset, int length) {
98
99                 fDocument = document;
100                 fRangeOffset = offset;
101                 fRangeLength = length;
102
103                 String[] delimiters = document.getLegalLineDelimiters();
104                 fDelimiters = new char[delimiters.length][];
105                 for (int i = 0; i < delimiters.length; i++)
106                         fDelimiters[i] = delimiters[i].toCharArray();
107
108                 updateBuffer(offset);
109                 fOffset = 0;
110         }
111
112         /*
113          * @see ICharacterScanner#read()
114          */
115         public final int read() {
116
117                 if (fOffset == fBufferLength) {
118                         if (fBufferOffset + fBufferLength == fDocument.getLength())
119                                 return EOF;
120                         else {
121                                 updateBuffer(fBufferOffset + fBufferLength);
122                                 fOffset = 0;
123                         }
124                 }
125                 try {
126                         return fBuffer[fOffset++];
127                 } catch (ArrayIndexOutOfBoundsException e) {
128                         System.out.println("Offset:" + fOffset);
129                         System.out.println("Buffer:" + fBuffer.toString());
130                         throw e;
131                 }
132         }
133
134         /*
135          * @see ICharacterScanner#unread
136          */
137         public final void unread() {
138
139                 if (fOffset == 0) {
140                         if (fBufferOffset == fRangeOffset) {
141                                 // error: BOF
142                         } else {
143                                 updateBuffer(fBufferOffset - fBuffer.length);
144                                 fOffset = fBuffer.length - 1;
145                         }
146                 } else {
147                         --fOffset;
148                 }
149         }
150
151         /*
152          * @see ICharacterScanner#getColumn()
153          */
154         public final int getColumn() {
155
156                 try {
157                         final int offset = fBufferOffset + fOffset;
158                         final int line = fDocument.getLineOfOffset(offset);
159                         final int start = fDocument.getLineOffset(line);
160                         return offset - start;
161                 } catch (BadLocationException e) {
162                 }
163
164                 return -1;
165         }
166
167         /*
168          * @see ICharacterScanner#getLegalLineDelimiters()
169          */
170         public final char[][] getLegalLineDelimiters() {
171                 return fDelimiters;
172         }
173 }