int BufferedInputStream::doReadArrayBounded()

in activemq-cpp/src/main/decaf/io/BufferedInputStream.cpp [138:243]


int BufferedInputStream::doReadArrayBounded(unsigned char* buffer, int size, int offset, int length) {

    try {

        // Use a local reference in case of unsynchronized close.
        unsigned char* lbuffer = this->proxyBuffer;

        if (lbuffer == NULL) {
            throw IOException(__FILE__, __LINE__, "Stream is closed");
        }

        if (buffer == NULL) {
            throw NullPointerException(__FILE__, __LINE__, "Buffer passed was NULL.");
        }

        if (offset > size || offset < 0) {
            throw IndexOutOfBoundsException(__FILE__, __LINE__, "offset parameter out of Bounds: %d.", offset);
        }

        if (length < 0 || length > size - offset) {
            throw IndexOutOfBoundsException(__FILE__, __LINE__, "length parameter out of Bounds: %d.", length);
        }

        // For zero, do nothing
        if (length == 0) {
            return 0;
        }

        // Use a local reference in case of unsynchronized close.
        InputStream* inputStream = this->inputStream;

        if (inputStream == NULL) {
            throw IOException(__FILE__, __LINE__, "Stream is closed");
        }

        int required = 0;

        // There are bytes available in the buffer so use them up first and
        // then we check to see if any are available on the stream, if not
        // then just return what we had.
        if (this->pos < this->count) {

            int available = this->count - this->pos;
            int copylength = available >= length ? length : available;

            System::arraycopy(lbuffer, this->pos, buffer, offset, copylength);
            this->pos += copylength;

            if (copylength == length || inputStream->available() == 0) {
                return (int) copylength;
            }

            offset += copylength;
            required = length - copylength;
        } else {
            required = length;
        }

        while (true) {

            int read = 0;

            // If we're not marked and the required size is greater than the
            // buffer, simply read the bytes directly bypassing the buffer.
            if (this->markPos == -1 && required >= this->bufferSize) {

                read = inputStream->read(buffer, size, offset, required);
                if (read == -1) {
                    return required == length ? -1 : (int) (length - required);
                }

            } else {

                if (bufferData(inputStream, lbuffer) == -1) {
                    return required == length ? -1 : (int) (length - required);
                }

                // Stream might have closed while we were buffering.
                if (isClosed() || this->proxyBuffer == NULL) {
                    throw IOException(__FILE__, __LINE__, "BufferedInputStream::bufferData - Stream is closed");
                }

                int available = this->count - this->pos;
                read = available >= required ? required : available;
                System::arraycopy(lbuffer, this->pos, buffer, offset, read);
                this->pos += read;
            }

            required -= read;

            if (required == 0) {
                return length;
            }

            if (inputStream->available() == 0) {
                return length - required;
            }

            offset += read;
        }
    }
    DECAF_CATCH_RETHROW( IOException)
    DECAF_CATCH_RETHROW( NullPointerException)
    DECAF_CATCH_RETHROW( IndexOutOfBoundsException)
    DECAF_CATCHALL_THROW( IOException)
}