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

org.rx.io.MemoryStream Maven / Gradle / Ivy

package org.rx.io;

import lombok.SneakyThrows;
import org.rx.beans.$;
import org.rx.annotation.ErrorCode;
import org.rx.core.SystemException;
import org.rx.socks.BytesSegment;

import java.io.*;
import java.util.Arrays;
import java.util.function.Supplier;

import static org.rx.core.Contract.*;

public class MemoryStream extends IOStream {
    public static final class BytesWriter extends ByteArrayOutputStream {
        private volatile int minPosition, length, maxLength = MaxInt;

        public int getPosition() {
            return count;
        }

        public synchronized void setPosition(int position) {
            require(position, minPosition <= position);

            count = position;
        }

        public int getLength() {
            return length;
        }

        public synchronized void setLength(int length) {
            require(length, length <= maxLength);

            this.length = length;
        }

        public synchronized byte[] getBuffer() {
            return buf;
        }

        public synchronized void setBuffer(byte[] buffer) {
            require(buffer);

            buf = buffer;
        }

        public BytesWriter(int capacity) {
            super(capacity);
        }

        public BytesWriter(byte[] buffer, int offset, int count, boolean nonResizable) {
            super(0);
            require(buffer);
            require(offset, offset >= 0);
            if (nonResizable) {
                require(count, offset + count <= buffer.length);
                minPosition = offset;
                maxLength = count;
            }

            setBuffer(buffer);
            setPosition(offset);
            setLength(count);
        }

        @Override
        public synchronized void write(int b) {
            beforeWrite(1);
            super.write(b);
            afterWrite();
        }

        @Override
        public synchronized void write(byte[] b, int off, int len) {
            require(b);

            beforeWrite(len);
            super.write(b, off, len);
            afterWrite();
        }

        private void beforeWrite(int count) {
            require(count, getPosition() + count < maxLength);
        }

        private void afterWrite() {
            if (getPosition() > getLength()) {
                setLength(getPosition());
            }
        }

        @Override
        public synchronized void writeTo(OutputStream out) throws IOException {
            require(out);

            out.write(getBuffer(), minPosition, getLength());
        }

        @Override
        public int size() {
            return getLength();
        }

        @Override
        public void reset() {
            setPosition(minPosition);
        }
    }

    public static final class BytesReader extends ByteArrayInputStream {
        public int getPosition() {
            return pos;
        }

        public synchronized void setPosition(int position) {
            this.pos = position;
        }

        public int getLength() {
            return count;
        }

        public synchronized void setLength(int length) {
            count = length;
        }

        public BytesReader(byte[] buffer, int offset, int count) {
            super(buffer);
            setBuffer(buffer, offset, count, offset);
        }

        public synchronized void setBuffer(byte[] buffer, int offset, int count, int mark) {
            require(buffer);
            require(offset, offset >= 0);
            //require(count, offset + count < buffer.length);

            this.buf = buffer;
            this.pos = offset;
            this.count = count;
            this.mark = mark;
        }
    }

    private boolean publiclyVisible;

    @Override
    public MemoryStream.BytesReader getReader() {
        checkRead();
        return super.getReader();
    }

    @Override
    public boolean canSeek() {
        return true;
    }

    @Override
    public int getPosition() {
        return writer.getPosition();
    }

    @Override
    public void setPosition(int position) {
        checkNotClosed();

        writer.setPosition(position);
        checkRead();
    }

    @Override
    public int getLength() {
        return writer.getLength();
    }

    public void setLength(int length) {
        checkNotClosed();

        writer.setLength(length);
        checkRead();
    }

    @ErrorCode
    public byte[] getBuffer() {
        checkNotClosed();
        if (!publiclyVisible) {
            throw new SystemException(values());
        }

        return writer.getBuffer();
    }

    private Supplier x;

    public MemoryStream() {
        this(32, false);
    }

    public MemoryStream(int capacity, boolean publiclyVisible) {
        super(null, new BytesWriter(capacity));
        initReader(publiclyVisible);
    }

    public MemoryStream(byte[] buffer, int offset, int count) {
        this(buffer, offset, count, true, false);
    }

    public MemoryStream(byte[] buffer, int offset, int count, boolean nonResizable, boolean publiclyVisible) {
        super(null, new BytesWriter(buffer, offset, count, nonResizable));
        initReader(publiclyVisible);
    }

    private void initReader(boolean publiclyVisible) {
        super.reader = new BytesReader(writer.getBuffer(), writer.getPosition(), writer.getLength());
        this.publiclyVisible = publiclyVisible;
    }

    private void checkRead() {
        reader.setBuffer(writer.getBuffer(), writer.getPosition(), writer.getLength(), writer.minPosition);
    }

    @Override
    public int available() {
        checkRead();
        return super.available();
    }

    @Override
    public int read() {
        checkRead();
        return super.read();
    }

    @Override
    public int read(byte[] buffer, int offset, int count) {
        checkRead();
        return super.read(buffer, offset, count);
    }

    @Override
    public void copyTo(IOStream to) {
        require(to);

        copyTo(to.getWriter());
    }

    public void copyTo(OutputStream to) {
        checkNotClosed();
        require(to);

        checkRead();
        int mark = reader.getPosition();
        copyTo(reader, to);
        reader.setPosition(mark);
    }

    @Override
    public void write(int b) {
        super.write(b);
        checkRead();
    }

    @Override
    public void write(byte[] buffer, int offset, int count) {
        super.write(buffer, offset, count);
        checkRead();
    }

    public void writeTo(IOStream from) {
        checkNotClosed();
        require(from);

        writeTo(from.getWriter());
    }

    @SneakyThrows
    public void writeTo(OutputStream from) {
        checkNotClosed();
        require(from);

        writer.writeTo(from);
    }

    public boolean tryGetBuffer($ out) {
        checkNotClosed();

        if (out == null || !publiclyVisible) {
            return false;
        }
        out.v = new BytesSegment(writer.getBuffer(), getPosition(), getLength());
        return true;
    }

    public synchronized byte[] toArray() {
        checkNotClosed();

        return Arrays.copyOf(writer.getBuffer(), writer.length);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy