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  }