View Javadoc

1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.lang.cpp;
5   
6   import java.io.IOException;
7   import java.io.PushbackReader;
8   import java.io.Reader;
9   
10  /**
11   * A custom {@link Reader} which completely omits C/C++ continuation character
12   * sequences from an underlying reader. Specifically the sequences {@code \ \n}
13   * (backslash, carriage return), or {@code \ \r \n} (backslash, line feed,
14   * carriage return).
15   * <p>
16   * This reader exists because to modify a JavaCC lexer to understand arbitrary
17   * continuations inside of any token is cumbersome, and just removing them from
18   * the input entirely is easier to implement. See this discussion on the JavaCC
19   * mailing list on <a href=
20   * "http://java.net/projects/javacc/lists/users/archive/2005-06/message/16">line
21   * continuation character</a>.
22   */
23  public class ContinuationReader extends Reader {
24  	private static final int EOF = -1;
25  	private static final char BACKSLASH = '\\';
26  	private static final char CARRIAGE_RETURN = '\n';
27  	private static final char LINE_FEED = '\r';
28  
29  	protected final PushbackReader in;
30  
31  	public ContinuationReader(Reader in) {
32  		this.in = new PushbackReader(in, 2);
33  	}
34  
35  	@Override
36  	public int read(char[] cbuf, int off, int len) throws IOException {
37  		int count = 0;
38  		while (count < len) {
39  			int c1 = in.read();
40  			if (c1 == EOF) {
41  				break;
42  			} else if (c1 == BACKSLASH) {
43  				int c2 = in.read();
44  				if (c2 == EOF) {
45  					// No match
46  				} else if (c2 == CARRIAGE_RETURN) {
47  					// Match: backslash, carriage return
48  					continue;
49  				} else if (c2 == LINE_FEED) {
50  					int c3 = in.read();
51  					if (c3 == EOF) {
52  						// No match
53  						in.unread(c2);
54  					} else if (c3 == CARRIAGE_RETURN) {
55  						// Match: backslash, line feed, carriage return
56  						continue;
57  					} else {
58  						// No match
59  						in.unread(c3);
60  						in.unread(c2);
61  					}
62  				} else {
63  					// No match
64  					in.unread(c2);
65  				}
66  			}
67  			cbuf[off + count] = (char) c1;
68  			count++;
69  		}
70  
71  		return count > 0 ? count : -1;
72  	}
73  
74  	@Override
75  	public void close() throws IOException {
76  		in.close();
77  	}
78  }