All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.unix4j.io.ReaderInput Maven / Gradle / Ivy

There is a newer version: 0.6
Show newest version
package org.unix4j.io;

import java.io.IOException;
import java.io.Reader;

import org.unix4j.line.Line;
import org.unix4j.line.SingleCharSequenceLine;

/**
 * Input device based on a {@link Reader} forming the base for most input
 * devices; handles parsing and recognition of {@link Line lines}.
 */
public class ReaderInput extends AbstractInput {

	private final Reader reader;
	private final char[] buffer = new char[1024];
	private int length;
	private int offset;

	/**
	 * Constructor with reader.
	 * 
	 * @param reader
	 *            the reader forming the basis of this input device.
	 */
	public ReaderInput(Reader reader) {
		this.reader = reader;
		readBuffer();
	}

	@Override
	public boolean hasMoreLines() {
		return length > offset;
	}

	@Override
	public Line readLine() {
		if (length == 0) {
			readBuffer();
		}
		if (length > offset) {
			return makeLine(null);
		}
		// no more lines
		return null;
	}

	private Line makeLine(StringBuilder lineBuilder) {
		int len = length;
		int index = offset;
		do {
			while (index < len) {
				final char ch0 = buffer[index];
				if (ch0 == '\n' || ch0 == '\r') {
					int contentEnd = index;
					index++;
					if (index < len) {
						final char ch1 = buffer[index];
						if ((ch1 == '\n' || ch1 == '\r') && ch0 != ch1) {
							index++;
						}
						if (lineBuilder == null) {
							lineBuilder = new StringBuilder(index - offset);
						}
						lineBuilder.append(buffer, offset, index - offset);
						if (index < len) {
							offset = index;
						} else {
							readBuffer();
						}
						return new SingleCharSequenceLine(lineBuilder, index - contentEnd);
					} else {
						if (lineBuilder == null) {
							lineBuilder = new StringBuilder(len - offset + 1);
						}
						lineBuilder.append(buffer, offset, len - offset);
						return makeLineMaybeWithOneMoreLineEndingChar(lineBuilder);
					}
				}
				index++;
			}
			if (lineBuilder == null) {
				lineBuilder = new StringBuilder(len - offset + 16);
			}
			lineBuilder.append(buffer, offset, len - offset);
			readBuffer();
			index = offset;
			len = length;
		} while (index < len);

		// eof, no newline, return rest as a line if there is something to
		// return
		return lineBuilder.length() > 0 ? new SingleCharSequenceLine(lineBuilder, 0) : null;
	}

	private Line makeLineMaybeWithOneMoreLineEndingChar(StringBuilder lineBuilder) {
		int lineEndingLength = 1;
		readBuffer();
		if (offset < length) {
			final char ch = buffer[offset];
			if (ch == '\n' || ch == '\r') {
				if (lineBuilder.charAt(lineBuilder.length() - 1) != ch) {
					lineBuilder.append(ch);
					lineEndingLength++;
					offset++;
				}
			}
		}
		return new SingleCharSequenceLine(lineBuilder, lineEndingLength);
	}

	private void readBuffer() {
		try {
			this.length = reader.read(buffer);
			this.offset = 0;
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy