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

com.jsftoolkit.utils.DelimitedReader Maven / Gradle / Ivy

Go to download

The core classes for the JSF Toolkit Component Framework. Includes all framework base and utility classes as well as component kick-start/code-generation and registration tools. Also includes some classes for testing that are reused in other projects. They cannot be factored out into a separate project because they are referenced by the tests and they reference this code (circular dependence).

The newest version!
package com.jsftoolkit.utils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.PushbackReader;

/**
 * A DelimitedReader wraps another Reader and allows reading from that Reader,
 * up to a given delimeter (a byte sequence).
 * 

* It is useful for wrapping Readers that you want to pass to a Scanner or other * buffering reader but that will need to be accessed directly later. i.e. you * need a Scanner but aren't willing to give up all the data. *

* This class will never buffer ahead, so it may be desirable to wrap * the passed in reader in a {@link BufferedReader} before handing it to this * class. *

* The matched delimeter can be obtained by calling {@link #getMatch()} after * EOS is returned. * * @author noah * */ public class DelimitedReader extends Reader { private final String delimeter; // the delimeter to look for private final PushbackReader reader; // stream to read bytes from private final boolean[] mask; private char[] match = null; /** * * @param in * @param delimeter */ public DelimitedReader(Reader in, String delimeter) { this(new PushbackReader(in, delimeter.length()), delimeter); } /** * Assumes the given delimeter should be matched exactly. * * @param in * @param delimeter */ public DelimitedReader(PushbackReader in, String delimeter) { this(in, delimeter, Utils.fill(new boolean[delimeter.length()], true)); } /** * * @param reader * a {@link PushbackReader}. Note that the pushback buffer must * be at least as long as delimeter - 1 * @param delimeter * the delimeter to halt after * @param mask * the delimeter mask. Indicates if the char at the given * position should be matched (true) or not matched (false). */ public DelimitedReader(PushbackReader in, String delimeter, boolean[] mask) { this.reader = in; this.delimeter = delimeter; this.mask = mask; } /** * Wraps the reader in a {@link PushbackReader} and calls * {@link #DelimitedReader(PushbackReader, String, boolean[])}. * * @param in * @param delimeter * @param mask */ public DelimitedReader(Reader in, String delimeter, boolean[] mask) { this(new PushbackReader(in, delimeter.length()), delimeter, mask); } @Override /** * Obeys the general contract of read. Returns -1 at end of stream. */ public int read() throws IOException { if (match == null) { int read = reader.read(); if (read == -1) { match = new char[0]; } else if (matches(read, 0)) { // if the char matches the first character of the delimeter, see // if the whole delimeter is there int[] buf = new int[delimeter.length()]; buf[0] = read; int i = 1; while (i < delimeter.length() && matches((buf[i] = reader.read()), i)) { i++; } if (i == delimeter.length()) { // matched, so return EOS match = Utils.toCharArray(buf); return -1; } else { // not a match, so we unread the extra chars for (int j = i; j > 0; j--) { reader.unread(buf[j]); } } } return read; } return -1; } protected boolean matches(int b, int index) { return mask[index] ? delimeter.charAt(index) == b : b != -1 && delimeter.charAt(index) != b; } @Override /** * Reads up to the delimeter or EOS. In other words, consumes all the bytes * up to and including the delimeter. Does not close the underlying stream. */ public void close() throws IOException { while (read() != -1) ; } /** * Returns the bytes the matched the delimeter (useful when you specify a * mask that is not all matching). * * This method returns null if the EOS or delimeter has not been reached. It * returns an empty array if the delimeter was not matched. Note that EOS * will not match anything, even if the mask bit for the last character is * set to not match. i.e. If only one more character is needed to match the * delimeter but the EOS is reached, then this method returns an empty * array. * * @return */ public char[] getMatch() { return match; } /** * Returns the wrapped reader. When this ({@link DelimitedReader}) reader * reaches the end of stream, the next character returned by the wrapped * reader will be the character immediately following the delimeter. Note * that this reader may be different from the one passed into the * constructor. * * @return the wrapped reader. */ public PushbackReader getReader() { return reader; } @Override public int read(char[] cbuf, int off, int len) throws IOException { int i; int read = -1; for (i = 0; i < len && (read = read()) != -1; i++) { cbuf[i + off] = (char) read; } return read == -1 && i == 0 ? -1 : i; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy