PeekableInputStream.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.io.input.buffer;

  18. import java.io.IOException;
  19. import java.io.InputStream;
  20. import java.util.Objects;

  21. import org.apache.commons.io.IOUtils;

  22. /**
  23.  * Implements a buffered input stream, which allows to peek into the buffers first bytes. This comes in handy when
  24.  * manually implementing scanners, lexers, parsers, and the like.
  25.  *
  26.  * @since 2.7
  27.  */
  28. public class PeekableInputStream extends CircularBufferInputStream {

  29.     /**
  30.      * Constructs a new instance, which filters the given input stream, and uses a reasonable default buffer size ({@link IOUtils#DEFAULT_BUFFER_SIZE}).
  31.      *
  32.      * @param inputStream The input stream, which is being buffered.
  33.      */
  34.     public PeekableInputStream(final InputStream inputStream) {
  35.         super(inputStream);
  36.     }

  37.     /**
  38.      * Constructs a new instance, which filters the given input stream, and uses the given buffer size.
  39.      *
  40.      * @param inputStream The input stream, which is being buffered.
  41.      * @param bufferSize The size of the {@link CircularByteBuffer}, which is used internally.
  42.      */
  43.     public PeekableInputStream(final InputStream inputStream, final int bufferSize) {
  44.         super(inputStream, bufferSize);
  45.     }

  46.     /**
  47.      * Returns whether the next bytes in the buffer are as given by {@code sourceBuffer}. This is equivalent to
  48.      * {@link #peek(byte[], int, int)} with {@code offset} == 0, and {@code length} == {@code sourceBuffer.length}
  49.      *
  50.      * @param sourceBuffer the buffer to compare against
  51.      * @return true if the next bytes are as given
  52.      * @throws IOException Refilling the buffer failed.
  53.      */
  54.     public boolean peek(final byte[] sourceBuffer) throws IOException {
  55.         Objects.requireNonNull(sourceBuffer, "sourceBuffer");
  56.         return peek(sourceBuffer, 0, sourceBuffer.length);
  57.     }

  58.     /**
  59.      * Returns whether the next bytes in the buffer are as given by {@code sourceBuffer}, {code offset}, and
  60.      * {@code length}.
  61.      *
  62.      * @param sourceBuffer the buffer to compare against
  63.      * @param offset the start offset
  64.      * @param length the length to compare
  65.      * @return true if the next bytes in the buffer are as given
  66.      * @throws IOException if there is a problem calling fillBuffer()
  67.      */
  68.     public boolean peek(final byte[] sourceBuffer, final int offset, final int length) throws IOException {
  69.         Objects.requireNonNull(sourceBuffer, "sourceBuffer");
  70.         if (sourceBuffer.length > bufferSize) {
  71.             throw new IllegalArgumentException("Peek request size of " + sourceBuffer.length
  72.                 + " bytes exceeds buffer size of " + bufferSize + " bytes");
  73.         }
  74.         if (buffer.getCurrentNumberOfBytes() < sourceBuffer.length) {
  75.             fillBuffer();
  76.         }
  77.         return buffer.peek(sourceBuffer, offset, length);
  78.     }
  79. }