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

org.apache.abdera.i18n.text.io.DynamicPushbackInputStream Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  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.  For additional information regarding
 * copyright in this work, please see the NOTICE file in the top level
 * directory of this distribution.
 */
package org.apache.abdera.i18n.text.io;

import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;

/**
 * PushbackInputStream implementation that performs dynamic resizing of the unread buffer
 */
public class DynamicPushbackInputStream extends PushbackInputStream {

    private final int origsize;

    public DynamicPushbackInputStream(InputStream in) {
        super(in);
        this.origsize = 1;
    }

    public DynamicPushbackInputStream(InputStream in, int initialSize) {
        super(in, initialSize);
        this.origsize = initialSize;
    }

    /**
     * Clear the buffer
     */
    public int clear() {
        int m = buf.length;
        buf = new byte[origsize];
        pos = origsize;
        return m;
    }

    /**
     * Shrink the buffer. This will reclaim currently unused space in the buffer, reducing memory but potentially
     * increasing the cost of resizing the buffer
     */
    public int shrink() {
        byte[] old = buf;
        if (pos == 0)
            return 0; // nothing to do
        int n = old.length - pos;
        int m, p, s, l;
        if (n < origsize) {
            buf = new byte[origsize];
            p = pos;
            s = origsize - n;
            l = old.length - p;
            m = old.length - origsize;
            pos = s;
        } else {
            buf = new byte[n];
            p = pos;
            s = 0;
            l = n;
            m = old.length - l;
            pos = 0;
        }
        System.arraycopy(old, p, buf, s, l);
        return m;
    }

    private void resize(int len) {
        byte[] old = buf;
        buf = new byte[old.length + len];
        System.arraycopy(old, 0, buf, len, old.length);
    }

    public void unread(byte[] b, int off, int len) throws IOException {
        if (len > pos && pos + len > buf.length) {
            resize(len - pos);
            pos += len - pos;
        }
        super.unread(b, off, len);
    }

    public void unread(int b) throws IOException {
        if (pos == 0) {
            resize(1);
            pos++;
        }
        super.unread(b);
    }

    public int read() throws IOException {
        int m = super.read();
        if (pos >= buf.length && buf.length > origsize)
            shrink();
        return m;
    }

    public int read(byte[] b, int off, int len) throws IOException {
        this.available(); // workaround for a problem in PushbackInputStream, without this, the amount of bytes read
                          // from some streams will be incorrect
        int r = super.read(b, off, len);
        if (pos >= buf.length && buf.length > origsize)
            shrink();
        return r;
    }

    public long skip(long n) throws IOException {
        long r = super.skip(n);
        if (pos >= buf.length && buf.length > origsize)
            shrink();
        return r;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy