/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef _DECAF_IO_PUSHBACKINPUTSTREAM_H_ #define _DECAF_IO_PUSHBACKINPUTSTREAM_H_ #include #include #include namespace decaf { namespace io { /** * A PushbackInputStream adds functionality to another input stream, namely the ability to * "push back" or "unread" one byte. This is useful in situations where it is convenient for * a fragment of code to read an indefinite number of data bytes that are delimited by a * particular byte value; after reading the terminating byte, the code fragment can "unread" * it, so that the next read operation on the input stream will reread the byte that was * pushed back. For example, bytes representing the characters constituting an identifier * might be terminated by a byte representing an operator character; a method whose job * is to read just an identifier can read until it sees the operator and then push the * operator back to be re-read. * * @since 1.0 */ class PushbackInputStream: public FilterInputStream { private: unsigned char* buffer; int bufferSize; int pos; private: PushbackInputStream(const PushbackInputStream&); PushbackInputStream& operator=(const PushbackInputStream&); public: /** * Creates a PushbackInputStream and saves its argument, the input stream in, for later * use. Initially, there is no pushed-back byte. * * @param stream * The InputStream instance to wrap. * @param * Boolean value indicating if this FilterInputStream owns the wrapped stream. */ PushbackInputStream(InputStream* stream, bool own = false); /** * Creates a PushbackInputStream and saves its argument, the input stream in, for later * use. Initially, there is no pushed-back byte. * * @param stream * The InputStream instance to wrap. * @param bufSize * The number of byte to allocate for pushback into this stream. * @param * Boolean value indicating if this FilterInputStream owns the wrapped stream. * * @throws IllegalArgumentException if the bufSize argument is < zero. */ PushbackInputStream(InputStream* stream, int bufSize, bool own = false); virtual ~PushbackInputStream(); /** * Pushes back the given byte, the byte is copied to the front of the pushback buffer, future * calls to read start reading from the beginning of these pushed back byte. * * @param value * The byte that is to be placed at the front of the push back buffer. * * @throws IOException if there is not enough space in the pushback buffer or this stream * has already been closed. */ void unread(unsigned char value); /** * Pushes back the given array of bytes, the bytes are copied to the front of the pushback * buffer, future calls to read start reading from the beginning of these pushed back bytes. * * @param buffer * The bytes to copy to the front of push back buffer. * @param size * The size of the array to be copied. * * @throws NullPointerException if the buffer passed is NULL. * @throws IndexOutOfBoundsException if the size value given is negative. * @throws IOException if there is not enough space in the pushback buffer or this stream * has already been closed. */ void unread(const unsigned char* buffer, int size); /** * Pushes back the given array of bytes, the bytes are copied to the front of the pushback * buffer, future calls to read start reading from the beginning of these pushed back bytes. * * @param buffer * The bytes to copy to the front of push back buffer. * @param size * The size of the array to be copied. * @param offset * The position in the buffer to start copying from. * @param length * The number of bytes to push back from the passed buffer. * * @throws NullPointerException if the buffer passed is NULL. * @throws IndexOutOfBoundsException if the offset + length is greater than the buffer size. * @throws IOException if there is not enough space in the pushback buffer or this stream * has already been closed. */ void unread(const unsigned char* buffer, int size, int offset, int length); /** * {@inheritDoc} * * Returns the sum of the number of pushed back bytes if any and the amount of bytes * available in the underlying stream via a call to available. */ virtual int available() const; /** * {@inheritDoc} * * This method first skips bytes in the local pushed back buffer before attempting to * complete the request by calling the underlying stream skip method with the remainder * of bytes that needs to be skipped. */ virtual long long skip(long long num); /** * Does nothing except throw an IOException. * * {@inheritDoc} */ virtual void mark(int readLimit); /** * Does nothing except throw an IOException. * * {@inheritDoc} */ virtual void reset(); /** * Does nothing except throw an IOException. * * {@inheritDoc} */ virtual bool markSupported() const { return false; } protected: virtual int doReadByte(); virtual int doReadArrayBounded(unsigned char* buffer, int size, int offset, int length); }; }} #endif /* _DECAF_IO_PUSHBACKINPUTSTREAM_H_ */