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

org.jgroups.util.ByteArrayDataInputStream Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up with different versions on classes on the class path).

There is a newer version: 34.0.0.Final
Show newest version
package org.jgroups.util;

import java.io.*;
import java.nio.ByteBuffer;
import java.util.Objects;

/**
 * Implements {@link java.io.DataInput} over a byte[] buffer. This class is not thread safe.
 * @author Bela Ban
 * @since  3.5
 */
public class ByteArrayDataInputStream extends InputStream implements DataInput {
    protected final byte[] buf;
    protected int          pos;   // current position to read next byte from buf

    // index of last byte to be read, reading beyond will return -1 or throw EOFException. Limit has to be <= buf.length
    protected final int    limit;
    protected static final ByteBuffer EMPTY=ByteBuffer.allocate(0);

    public ByteArrayDataInputStream(byte[] buf) {
        this(buf, 0, buf != null? buf.length : 0);
    }

    public ByteArrayDataInputStream(byte[] buf, int offset, int length) {
        this.buf=buf;
        this.limit=Math.min(buf.length, offset+length);
        this.pos=checkBounds(offset);
    }

    public ByteArrayDataInputStream(ByteBuffer buffer) {
        int offset=buffer.hasArray()? buffer.arrayOffset() + buffer.position() : buffer.position(),
          len=buffer.remaining();
        if(!buffer.isDirect()) {
            this.buf=buffer.array();
            this.pos=offset;
            this.limit=offset+len;
        }
        else { // by default use a copy; but of course implementers of Receiver can override this
            byte[] tmp=new byte[len];
            buffer.get(tmp, 0, len);
            this.buf=tmp;
            this.pos=0;
            this.limit=len;
        }
    }

    public ByteArrayDataInputStream position(int pos) {
        this.pos=checkBounds(pos); return this;
    }

    public int position() {return pos;}
    public int limit()    {return limit;}
    public int capacity() {return buf.length;}



    /**
     * Reads the next byte of data from buf. The value byte is returned as an {@code int} in the range {@code 0} to
     * {@code 255}. If no byte is available because the end of the buffer has been reached, the value {@code -1} is
     * returned.
     * @return  the next byte of data, or {@code -1} if the end of the stream has been reached.
     */
    public int read() {
        return (pos < limit) ? (buf[pos++] & 0xff) : -1;
    }

    public int read(byte[] b, int off, int len) {
        Objects.requireNonNull(b);

        if(off < 0 || len < 0 || len > b.length - off)
            throw new IndexOutOfBoundsException();

        if(pos >= limit)
            return -1;

        int avail=limit - pos;
        if(len > avail)
            len=avail;
        if(len <= 0)
            return 0;

        System.arraycopy(buf, pos, b, off, len);
        pos += len;
        return len;
    }

    public void readFully(byte[] b) throws IOException {
        readFully(b, 0, b.length);
    }

    public void readFully(byte[] b, int off, int len) throws IOException {
        if (len < 0)
            throw new IndexOutOfBoundsException();
        int n = 0;
        while (n < len) {
            int count=read(b, off + n, len - n);
            if (count < 0)
                throw new EOFException();
            n += count;
        }
    }

    /**
     * Non-copying reading of len bytes from the input stream into a {@link ByteBuffer}.
     * 
* Reads len bytes from the input stream and wraps them in a {@link ByteBuffer}. Note that the buffer is pinned to * a subrange of the underlying 'buf' byte[] array: make sure that the contents of 'buf' don't change until you're * done with 'buf', or else you'll end up with unpredictable behavior. */ public ByteBuffer readBuffer(int len) { int avail=limit - pos; if(len > avail || len < 0) throw new IndexOutOfBoundsException(); if(len == 0) return EMPTY; ByteBuffer val=ByteBuffer.wrap(buf, pos, len); pos += len; return val; } public int skipBytes(int n) { int k = limit - pos; if (n < k) k=Math.max(n, 0); pos += k; return k; } public boolean readBoolean() throws IOException { int ch=read(); if(ch < 0) throw new EOFException(); return ch != 0; } public byte readByte() throws IOException { int ch=read(); if (ch < 0) throw new EOFException(); return (byte)(ch); } public int readUnsignedByte() throws IOException { int ch=read(); if (ch < 0) throw new EOFException(); return ch; } public short readShort() throws IOException { int ch1=read(); int ch2=read(); if ((ch1 | ch2) < 0) throw new EOFException(); return (short)((ch1 << 8) + (ch2 << 0)); } public int readUnsignedShort() throws IOException { int ch1=read(); int ch2=read(); if ((ch1 | ch2) < 0) throw new EOFException(); return (ch1 << 8) + (ch2 << 0); } public char readChar() throws IOException { int ch1=read(); int ch2=read(); if ((ch1 | ch2) < 0) throw new EOFException(); return (char)((ch1 << 8) + (ch2 << 0)); } public int readInt() throws IOException { int ch1=read(); int ch2=read(); int ch3=read(); int ch4=read(); if ((ch1 | ch2 | ch3 | ch4) < 0) throw new EOFException(); return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0)); } public long readLong() throws IOException { return (((long)read() << 56) + ((long)(read() & 0xff) << 48) + ((long)(read() & 0xff) << 40) + ((long)(read() & 0xff) << 32) + ((long)(read() & 0xff) << 24) + ((read() & 0xff) << 16) + ((read() & 0xff) << 8) + ((read() & 0xff) << 0)); } public float readFloat() throws IOException { return Float.intBitsToFloat(readInt()); } public double readDouble() throws IOException { return Double.longBitsToDouble(readLong()); } public String readLine() throws IOException { StringBuilder sb=new StringBuilder(35); int ch; while(true) { ch=read(); if(ch == -1) return sb.length() == 0? null : sb.toString(); if(ch == '\r') ; else { if(ch == '\n') break; sb.append((char)ch); } } return sb.toString(); } public String readUTF() throws IOException { int utflen=readUnsignedShort(); byte[] bytearr=new byte[utflen]; char[] chararr=new char[utflen]; if(((short)utflen) == -1) return null; int c, char2, char3; int count = 0; int chararr_count=0; readFully(bytearr,0,utflen); while (count < utflen) { c = (int) bytearr[count] & 0xff; if (c > 127) break; count++; chararr[chararr_count++]=(char)c; } while (count < utflen) { c = (int) bytearr[count] & 0xff; switch (c >> 4) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: /* 0xxxxxxx*/ count++; chararr[chararr_count++]=(char)c; break; case 12: case 13: /* 110x xxxx 10xx xxxx*/ count += 2; if (count > utflen) throw new UTFDataFormatException( "malformed input: partial character at end"); char2=bytearr[count-1]; if ((char2 & 0xC0) != 0x80) throw new UTFDataFormatException( "malformed input around byte " + count); chararr[chararr_count++]=(char)(((c & 0x1F) << 6) | (char2 & 0x3F)); break; case 14: /* 1110 xxxx 10xx xxxx 10xx xxxx */ count += 3; if (count > utflen) throw new UTFDataFormatException( "malformed input: partial character at end"); char2=bytearr[count-2]; char3=bytearr[count-1]; if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80)) throw new UTFDataFormatException( "malformed input around byte " + (count-1)); chararr[chararr_count++]=(char)(((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)); break; default: /* 10xx xxxx, 1111 xxxx */ throw new UTFDataFormatException( "malformed input around byte " + count); } } // The number of chars produced may be less than utflen return new String(chararr, 0, chararr_count); } public String toString() { return "pos=" + pos + " lim=" + limit + " cap=" + buf.length; } protected int checkBounds(int pos) { if(pos < 0 || pos >= limit) throw new IndexOutOfBoundsException("pos=" + pos + ", limit=" + limit); return pos; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy