upload tizen1.0 source
[sdk/ide/product.git] / org.eclipse.cdt.ui / src / org / eclipse / cdt / internal / ui / text / CCodeReader.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2008 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  *     QNX Software System
11  *******************************************************************************/
12 package org.eclipse.cdt.internal.ui.text;
13
14 import java.io.IOException;
15
16 import org.eclipse.jface.text.BadLocationException;
17 import org.eclipse.jface.text.IDocument;
18
19 /**
20  * Reads from a document either forwards or backwards. May be configured to
21  * skip comments and strings.
22  */
23 public class CCodeReader extends SingleCharReader {
24         
25         /** The EOF character */
26         public static final int EOF= -1;
27         
28         private boolean fSkipComments= false;
29         private boolean fSkipStrings= false;
30         private boolean fForward= false;
31         
32         private IDocument fDocument;
33         private int fOffset;
34         
35         private int fEnd= -1;
36         private int fCachedLineNumber= -1;
37         private int fCachedLineOffset= -1;
38         
39         
40         public CCodeReader() {
41         }
42         
43         /**
44          * Returns the offset of the last read character. Should only be called after read has been called.
45          */
46         public int getOffset() {
47                 return fForward ? fOffset -1 : fOffset;
48         }
49         
50         public void configureForwardReader(IDocument document, int offset, int length, boolean skipComments, boolean skipStrings) throws IOException {
51                 fDocument= document;
52                 fOffset= offset;
53                 fSkipComments= skipComments;
54                 fSkipStrings= skipStrings;
55                 
56                 fForward= true;
57                 fEnd= Math.min(fDocument.getLength(), fOffset + length);                
58         }
59         
60         public void configureBackwardReader(IDocument document, int offset, boolean skipComments, boolean skipStrings) throws IOException {
61                 fDocument= document;
62                 fOffset= offset;
63                 fSkipComments= skipComments;
64                 fSkipStrings= skipStrings;
65                 
66                 fForward= false;
67                 try {
68                         fCachedLineNumber= fDocument.getLineOfOffset(fOffset);
69                 } catch (BadLocationException x) {
70                         throw new IOException(x.getMessage());
71                 }
72         }
73         
74         /*
75          * @see Reader#close()
76          */
77         @Override
78         public void close() throws IOException {
79                 fDocument= null;
80         }
81         
82         /*
83          * @see SingleCharReader#read()
84          */
85         @Override
86         public int read() throws IOException {
87                 try {
88                         return fForward ? readForwards() : readBackwards();
89                 } catch (BadLocationException x) {
90                         throw new IOException(x.getMessage());
91                 }
92         }
93         
94         private void gotoCommentEnd() throws BadLocationException {
95                 while (fOffset < fEnd) {
96                         char current= fDocument.getChar(fOffset++);
97                         if (current == '*') {
98                                 if (fOffset < fEnd && fDocument.getChar(fOffset) == '/') {
99                                         ++ fOffset;
100                                         return;
101                                 }
102                         }
103                 }
104         }
105         
106         private void gotoStringEnd(char delimiter) throws BadLocationException {
107                 while (fOffset < fEnd) {
108                         char current= fDocument.getChar(fOffset++);
109                         if (current == '\\') {
110                                 // ignore escaped characters
111                                 ++ fOffset;
112                         } else if (current == delimiter) {
113                                 return;
114                         }
115                 }
116         }
117         
118         private void gotoLineEnd() throws BadLocationException {
119                 int line= fDocument.getLineOfOffset(fOffset);
120                 fOffset= fDocument.getLineOffset(line + 1);
121         }
122         
123         private int readForwards() throws BadLocationException {
124                 while (fOffset < fEnd) {
125                         char current= fDocument.getChar(fOffset++);
126                         
127                         switch (current) {
128                                 case '/':
129                                         
130                                         if (fSkipComments && fOffset < fEnd) {
131                                                 char next= fDocument.getChar(fOffset);
132                                                 if (next == '*') {
133                                                         // a comment starts, advance to the comment end
134                                                         ++ fOffset;
135                                                         gotoCommentEnd();
136                                                         continue;
137                                                 } else if (next == '/') {
138                                                         // '//'-comment starts, advance to the line end
139                                                         gotoLineEnd();
140                                                         continue;
141                                                 }
142                                         }
143                                         
144                                         return current;
145                                         
146                                 case '"':
147                                 case '\'':
148                                 
149                                         if (fSkipStrings) {
150                                                 gotoStringEnd(current);
151                                                 continue;
152                                         }
153                                         
154                                         return current;
155                         }
156                         
157                         return current;
158                 }
159                 
160                 return EOF;
161         }
162         
163         private void handleSingleLineComment() throws BadLocationException {
164                 int line= fDocument.getLineOfOffset(fOffset);
165                 if (line < fCachedLineNumber) {
166                         fCachedLineNumber= line;
167                         fCachedLineOffset= fDocument.getLineOffset(line);
168                         int offset= fOffset;
169                         while (fCachedLineOffset < offset) {
170                                 char current= fDocument.getChar(offset--);
171                                 if (current == '/' && fCachedLineOffset <= offset && fDocument.getChar(offset) == '/') {
172                                         fOffset= offset;
173                                         return;
174                                 }
175                         }
176                 }
177         }
178         
179         private void gotoCommentStart() throws BadLocationException {
180                 while (0 < fOffset) {
181                         char current= fDocument.getChar(fOffset--);
182                         if (current == '*' && 0 <= fOffset && fDocument.getChar(fOffset) == '/')
183                                 return;
184                 }
185         }
186         
187         private void gotoStringStart(char delimiter) throws BadLocationException {
188                 while (0 < fOffset) {
189                         char current= fDocument.getChar(fOffset);
190                         if (current == delimiter) {
191                                 if ( !(0 <= fOffset && fDocument.getChar(fOffset -1) == '\\'))
192                                         return;
193                         }
194                         -- fOffset;
195                 }
196         }
197                 
198         private int readBackwards() throws BadLocationException {
199                 
200                 while (0 < fOffset) {
201                         -- fOffset;
202                         
203                         handleSingleLineComment();
204                         
205                         char current= fDocument.getChar(fOffset);
206                         switch (current) {
207                                 case '/':
208                                         
209                                         if (fSkipComments && fOffset > 1) {
210                                                 char next= fDocument.getChar(fOffset - 1);
211                                                 if (next == '*') {
212                                                         // a comment ends, advance to the comment start
213                                                         fOffset -= 2;
214                                                         gotoCommentStart();
215                                                         continue;
216                                                 }
217                                         }
218                                         
219                                         return current;
220                                         
221                                 case '"':
222                                 case '\'':
223                                 
224                                         if (fSkipStrings) {
225                                                 -- fOffset;
226                                                 gotoStringStart(current);
227                                                 continue;
228                                         }
229                                         
230                                         return current;
231                         }
232                         
233                         return current;
234                 }
235                 
236                 return EOF;
237         }
238 }