fixed NPE
[phpeclipse.git] / net.sourceforge.phpeclipse / 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
14 import org.eclipse.jface.text.Assert;
15 import org.eclipse.jface.text.BadLocationException;
16 import org.eclipse.jface.text.IDocument;
17 import org.eclipse.jface.text.rules.ICharacterScanner;
18
19
20
21 /**
22  * A buffered document scanner. The buffer always contains a section 
23  * of a fixed size of the document to be scanned.
24  */
25
26 public final class BufferedDocumentScanner implements ICharacterScanner {
27
28         /** The document being scanned. */
29         private IDocument fDocument;
30         /** The offset of the document range to scan. */
31         private int fRangeOffset;
32         /** The length of the document range to scan. */
33         private int fRangeLength;
34         /** The delimiters of the document. */
35         private char[][] fDelimiters;
36
37         /** The buffer. */
38         private final char[] fBuffer;
39         /** The offset of the buffer within the document. */
40         private int fBufferOffset;
41         /** The valid length of the buffer for access. */
42         private int fBufferLength;
43         /** The offset of the scanner within the buffer. */
44         private int fOffset;
45
46         
47         /**
48          * Creates a new buffered document scanner.
49          * The buffer size is set to the given number of characters.
50          * 
51          * @param size the buffer size
52          */
53         public BufferedDocumentScanner(int size) {
54                 Assert.isTrue(size >= 1);
55                 fBuffer= new char[size];
56         }
57
58         /**
59          * Fills the buffer with the contens of the document starting at the given offset.
60          *
61          * @param offset the document offset at which the buffer starts
62          */
63         private final void updateBuffer(int offset) {
64
65                 fBufferOffset= offset;
66                 
67                 if (fBufferOffset + fBuffer.length > fRangeOffset + fRangeLength)
68                         fBufferLength= fRangeLength - (fBufferOffset - fRangeOffset);
69                 else
70                         fBufferLength= fBuffer.length;
71
72                 try {
73                         final String content= fDocument.get(fBufferOffset, fBufferLength);
74                         content.getChars(0, fBufferLength, fBuffer, 0);
75                 } catch (BadLocationException e) {
76                 }
77         }
78
79         /**
80          * Configures the scanner by providing access to the document range over which to scan.
81          *
82          * @param document the document to scan
83          * @param offset the offset of the document range to scan
84          * @param length the length of the document range to scan
85          */
86         public final void setRange(IDocument document, int offset, int length) {
87
88                 fDocument= document;
89                 fRangeOffset= offset;
90                 fRangeLength= length;
91
92                 String[] delimiters= document.getLegalLineDelimiters();
93                 fDelimiters= new char[delimiters.length][];
94                 for (int i= 0; i < delimiters.length; i++)
95                         fDelimiters[i]= delimiters[i].toCharArray();
96
97                 updateBuffer(offset);
98                 fOffset= 0;
99         }
100
101         /*
102          * @see ICharacterScanner#read()
103          */
104         public final int read() {
105
106                 if (fOffset == fBufferLength) {
107                         if (fBufferOffset + fBufferLength == fDocument.getLength())
108                                 return EOF;
109                         else {
110                                 updateBuffer(fBufferOffset + fBufferLength);
111                                 fOffset= 0;
112                         }
113                 }
114         try {
115                 return fBuffer[fOffset++];
116         } catch (ArrayIndexOutOfBoundsException e) {
117           System.out.println("Offset:"+fOffset);
118           System.out.println("Buffer:"+fBuffer);
119           throw e;
120         }
121         }
122
123         /*
124          * @see ICharacterScanner#unread
125          */
126         public final void unread() {
127
128                 if (fOffset == 0) {
129                         if (fBufferOffset == fRangeOffset) {
130                                 // error: BOF
131                         } else {
132                                 updateBuffer(fBufferOffset - fBuffer.length);
133                                 fOffset= fBuffer.length - 1;
134                         }
135                 } else {                        
136                         --fOffset;
137                 }
138         }
139
140         /*
141          * @see ICharacterScanner#getColumn()
142          */
143         public final int getColumn() {
144
145                 try {
146                         final int offset= fBufferOffset + fOffset;
147                         final int line= fDocument.getLineOfOffset(offset);
148                         final int start= fDocument.getLineOffset(line);
149                         return offset - start;
150                 } catch (BadLocationException e) {
151                 }
152
153                 return -1;
154         }
155
156         /*
157          * @see ICharacterScanner#getLegalLineDelimiters()
158          */
159         public final char[][] getLegalLineDelimiters() {
160                 return fDelimiters;
161         }
162 }