blob: 29f69f9ec2231655d3e5ba6895296ad1f0fd5bdf [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2018-2020 Martin Weber.
*
* Content is provided to you under the terms and conditions of the Eclipse Public License Version 2.0 "EPL".
* A copy of the EPL is available at http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*******************************************************************************/
package org.eclipse.cdt.jsoncdb.core.participant.builtins;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Objects;
import org.eclipse.cdt.jsoncdb.core.participant.IRawSourceFileInfoCollector;
/**
* An OutputStream that passes each line written to it to a
* IBuiltinsOutputProcessor.
*
* @author Martin Weber
*
* @implNote this is visible for testing only
*/
public class OutputSniffer extends OutputStream {
private static final String SEP = System.lineSeparator();
private final StringBuilder buffer;
private final IBuiltinsOutputProcessor processor;
private final IRawSourceFileInfoCollector infoCollector;
private final OutputStream os;
/**
* @param outputStream the OutputStream to write to or {@code null}
* @param infoCollector collector for information about C preprocessor symbols
* and include paths
*/
public OutputSniffer(IBuiltinsOutputProcessor processor, OutputStream outputStream,
IRawSourceFileInfoCollector infoCollector) {
this.processor = Objects.requireNonNull(processor, "processor"); //$NON-NLS-1$
this.infoCollector = Objects.requireNonNull(infoCollector, "infoCollector"); //$NON-NLS-1$
this.os = outputStream;
buffer = new StringBuilder(512);
}
@Override
public void write(int c) throws IOException {
if (os != null)
os.write(c);
synchronized (this) {
buffer.append(new String(new byte[] { (byte) c }));
splitLines();
}
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
if (os != null)
os.write(b, off, len);
synchronized (this) {
buffer.append(new String(b, off, len));
splitLines();
}
}
@Override
public void flush() throws IOException {
if (os != null)
os.flush();
synchronized (this) {
splitLines();
// process remaining bytes
String line = buffer.toString();
buffer.setLength(0);
processLine(line);
}
}
@Override
public void close() throws IOException {
if (os != null)
os.close();
flush();
}
/**
* Splits the buffer into separate lines and sends these to the parsers.
*
*/
private void splitLines() {
int idx;
while ((idx = buffer.indexOf(SEP)) != -1) {
String line = buffer.substring(0, idx);
buffer.delete(0, idx + SEP.length());
processLine(line);
}
}
/**
* @param line
*/
private void processLine(String line) {
processor.processLine(line, infoCollector);
}
}