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

com.tangosol.io.AbstractByteArrayReadBuffer Maven / Gradle / Ivy

There is a newer version: 24.09
Show newest version
/*
 * Copyright (c) 2000, 2022, Oracle and/or its affiliates.
 *
 * Licensed under the Universal Permissive License v 1.0 as shown at
 * https://oss.oracle.com/licenses/upl.
 */

package com.tangosol.io;


import com.tangosol.util.Binary;
import com.tangosol.util.ExternalizableHelper;

import java.io.DataOutput;
import java.io.EOFException;
import java.io.IOException;
import java.io.OutputStream;

import java.nio.ByteBuffer;

import jakarta.json.bind.annotation.JsonbProperty;


/**
* The AbstractByteArrayReadBuffer abstract class is intended to serve as
* a base class for the following:
* 
    *
  1. the pre-existing Binary class
  2. *
  3. a new byte[] based class that does not attempt to add the immutability * aspect provided by the Binary class
  4. *
  5. a new ByteBuffer based class that will work with Java NIO
  6. *
*

* This implementation is not intended to be thread safe. * * @author cp 2005.01.18 */ public abstract class AbstractByteArrayReadBuffer extends AbstractReadBuffer { // ----- constructors --------------------------------------------------- /** * Default constructor; intended for deserialization use by subclasses. *

* Note that this default constructor leaves the buffer in an invalid * state. */ protected AbstractByteArrayReadBuffer() { } /** * Construct an AbstractByteArrayReadBuffer on a portion of a byte array. * * @param ab a byte array * @param of an offset into the byte array * @param cb the number of bytes to utilize * * @exception IndexOutOfBoundsException if of or * cb is negative, or of + cb is * larger than ab.length * @exception NullPointerException if ab is null */ protected AbstractByteArrayReadBuffer(byte[] ab, int of, int cb) { m_ab = ab; resetRange(of, cb); } // ----- ReadBuffer methods --------------------------------------------- /** * {@inheritDoc} */ public int length() { return m_cb; } /** * {@inheritDoc} */ public byte byteAt(int of) { if (of >= 0 && of < m_cb) { return m_ab[m_of + of]; } else { throw new IndexOutOfBoundsException("of=" + of + ", length()=" + m_cb); } } /** * {@inheritDoc} */ public void copyBytes(int ofBegin, int ofEnd, byte abDest[], int ofDest) { if (ofBegin < 0 || ofEnd > m_cb || ofBegin > ofEnd) { throw new IndexOutOfBoundsException("ofBegin=" + ofBegin + ", ofEnd=" + ofEnd + ", Binary.length=" + m_cb); } System.arraycopy(m_ab, m_of + ofBegin, abDest, ofDest, ofEnd - ofBegin); } /** * {@inheritDoc} */ public void writeTo(OutputStream out) throws IOException { out.write(m_ab, m_of, m_cb); } /** * {@inheritDoc} */ public void writeTo(OutputStream out, int of, int cb) throws IOException { out.write(m_ab, m_of + of, cb); } /** * {@inheritDoc} */ public void writeTo(DataOutput out) throws IOException { out.write(m_ab, m_of, m_cb); } /** * {@inheritDoc} */ public void writeTo(DataOutput out, int of, int cb) throws IOException { out.write(m_ab, m_of + of, cb); } /** * {@inheritDoc} */ public void writeTo(ByteBuffer buf) { buf.put(m_ab, m_of, m_cb); } /** * {@inheritDoc} */ public void writeTo(ByteBuffer buf, int of, int cb) throws IOException { buf.put(m_ab, m_of + of, cb); } /** * {@inheritDoc} */ public byte[] toByteArray(int of, int cb) { checkBounds(of, cb); if (cb == 0) { return NO_BYTES; } byte[] abNew; byte[] ab = m_ab; // adjust offset based on what part of the underlying byte[] this // buffer is "over" of += m_of; if (of == 0 && cb == ab.length && !isByteArrayPrivate()) { // just return the underlying (non-private) byte[] return ab; } abNew = new byte[cb]; System.arraycopy(ab, of, abNew, 0, cb); return abNew; } /** * {@inheritDoc} */ public Binary toBinary() { int cb = m_cb; return cb == 0 ? NO_BINARY : new Binary(m_ab, m_of, cb); } /** * {@inheritDoc} */ public Binary toBinary(int of, int cb) { checkBounds(of, cb); return cb == 0 ? NO_BINARY : new Binary(m_ab, m_of + of, cb); } /** * {@inheritDoc} */ public ByteBuffer toByteBuffer() { return ByteBuffer.wrap(m_ab, m_of, m_cb).asReadOnlyBuffer(); } /** * {@inheritDoc} */ public ByteBuffer toByteBuffer(int of, int cb) { checkBounds(of, cb); return ByteBuffer.wrap(m_ab, m_of + of, cb).asReadOnlyBuffer(); } /** * {@inheritDoc} */ public boolean equals(Object o) { if (o instanceof AbstractByteArrayReadBuffer) { AbstractByteArrayReadBuffer that = (AbstractByteArrayReadBuffer) o; if (this == that) { return true; } int cb = this.m_cb; return cb == that.m_cb && Binary.equals(this.m_ab, this.m_of, that.m_ab, that.m_of, cb); } else { return super.equals(o); } } // ----- factory methods ------------------------------------------------ /** * {@inheritDoc} */ protected BufferInput instantiateBufferInput() { return new ByteArrayBufferInput(); } // ----- internal ------------------------------------------------------- /** * Reset the portion of the byte array the ReadBuffer operates upon. * * @param of an offset into the byte array * @param cb the number of bytes to utilize * * @exception IndexOutOfBoundsException if of or * cb are negative, or of + cb is * larger than the buffer's length */ protected void resetRange(int of, int cb) { byte[] ab = m_ab; if (of < 0 || cb < 0 || of + cb > ab.length) { throw new IndexOutOfBoundsException("of=" + of + ", cb=" + cb + ", ab.length=" + ab.length); } m_of = of; m_cb = cb; } /** * Determine if the underlying byte[] should be treated as private data. * * @return true iff the underlying data should not ever be exposed by * this object */ protected abstract boolean isByteArrayPrivate(); // ----- inner class: BufferInput implementation ------------------------ /** * This is a simple implementation of the BufferInput interface on top of * a byte array. *

* This implementation extends InputStream, but only so that it can be * passed to anything that takes an InputStream. */ public final class ByteArrayBufferInput extends AbstractBufferInput { // ----- constructors ------------------------------------------- /** * Default constructor. */ public ByteArrayBufferInput() { } // ----- InputStreaming methods --------------------------------- /** * {@inheritDoc} */ public int read() throws IOException { int of = getOffset(); if (of < m_cb) { // increment read position setOffsetInternal(of + 1); // return the unsigned byte from the previous read position return m_ab[m_of + of] & 0xFF; } else { return -1; } } /** * {@inheritDoc} */ public int read(byte ab[], int of, int cb) throws IOException { // validate parameters int cbDest = ab.length; if (of < 0 || cb < 0 || of + cb > cbDest) { throw new IndexOutOfBoundsException("ab.length=" + cbDest + ", of=" + of + ", cb=" + cb); } // avoid confusing "nothing requested" with "nothing remains" if (cb == 0) { return 0; } // get the current position within the buffer int ofIn = getOffset(); // determine the amount to read by taking the smaller of the // requested and the remainder int cbRead = Math.min(cb, m_cb - ofIn); // check for eof if (cbRead == 0) { return -1; } else { // transfer the read data to the passed byte array System.arraycopy(m_ab, m_of + ofIn, ab, of, cbRead); // update the read offset and return the number of bytes read setOffsetInternal(ofIn + cbRead); return cbRead; } } // ----- DataInput methods -------------------------------------- /** * {@inheritDoc} */ public byte readByte() throws IOException { int ofAdd = getOffset(); if (ofAdd < m_cb) { // increment read position setOffsetInternal(ofAdd + 1); // return the unsigned byte from the previous read position return m_ab[m_of + ofAdd]; } else { throw new EOFException(); } } /** * {@inheritDoc} */ public int readUnsignedShort() throws IOException { // check for EOF int ofAdd = getOffset(); if (m_cb - ofAdd < 2) { // pretend we exhausted the stream trying to read the value setOffsetInternal(m_cb); throw new EOFException(); } // increment read position setOffsetInternal(ofAdd + 2); // build and return the value byte[] ab = m_ab; int of = m_of + ofAdd; return ((ab[of] & 0xFF) << 8) | (ab[of + 1] & 0xFF); } /** * {@inheritDoc} */ public int readInt() throws IOException { // check for EOF int ofAdd = getOffset(); if (m_cb - ofAdd < 4) { // pretend we exhausted the stream trying to read the value setOffsetInternal(m_cb); throw new EOFException(); } // increment read position setOffsetInternal(ofAdd + 4); // build and return the value byte[] ab = m_ab; int of = m_of + ofAdd; return ((ab[of ] ) << 24) | ((ab[of + 1] & 0xFF) << 16) | ((ab[of + 2] & 0xFF) << 8 ) | ((ab[of + 3] & 0xFF) ); } /** * {@inheritDoc} */ public long readLong() throws IOException { // check for EOF int ofAdd = getOffset(); if (m_cb - ofAdd < 8) { // pretend we exhausted the stream trying to read the value setOffsetInternal(m_cb); throw new EOFException(); } // increment read position setOffsetInternal(ofAdd + 8); // build and return the value byte[] ab = m_ab; int of = m_of + ofAdd; long n1 = ((ab[of ] ) << 24) | ((ab[of + 1] & 0xFF) << 16) | ((ab[of + 2] & 0xFF) << 8 ) | ((ab[of + 3] & 0xFF) ); long n2 = ((ab[of + 4] ) << 24) | ((ab[of + 5] & 0xFF) << 16) | ((ab[of + 6] & 0xFF) << 8 ) | ((ab[of + 7] & 0xFF) ); return (n1 << 32) | (n2 & 0xFFFFFFFFL); } // ----- BufferInput methods ------------------------------------ /** * {@inheritDoc} */ public int readPackedInt() throws IOException { byte[] ab = m_ab; int ofRaw = m_of; int of = ofRaw + getOffset(); int cb = ofRaw + m_cb; // check EOF if (of >= cb) { throw new EOFException(); } int b = ab[of++] & 0xFF; int n = b & 0x3F; // only 6 bits of data in first byte int cBits = 6; boolean fNeg = (b & 0x40) != 0; // seventh bit is a sign bit while ((b & 0x80) != 0) // eighth bit is the continuation bit { // check EOF if (of >= cb) { throw new EOFException(); } b = ab[of++] & 0xFF; n |= ((b & 0x7F) << cBits); cBits += 7; } if (fNeg) { n = ~n; } // increment read position setOffsetInternal(of - ofRaw); return n; } /** * {@inheritDoc} */ public long readPackedLong() throws IOException { byte[] ab = m_ab; int ofRaw = m_of; int of = ofRaw + getOffset(); int cb = ofRaw + m_cb; // check EOF if (of >= cb) { throw new EOFException(); } int b = ab[of++] & 0xFF; long l = b & 0x3F; // only 6 bits of data in first byte int cBits = 6; boolean fNeg = (b & 0x40) != 0; // seventh bit is a sign bit while ((b & 0x80) != 0) // eighth bit is the continuation bit { // check EOF if (of >= cb) { throw new EOFException(); } b = ab[of++] & 0xFF; l |= (((long) (b & 0x7F)) << cBits); cBits += 7; } if (fNeg) { l = ~l; } // increment read position setOffsetInternal(of - ofRaw); return l; } // ----- internal ----------------------------------------------- /** * {@inheritDoc} */ protected String convertUTF(int of, int cb) throws IOException { return ExternalizableHelper.convertUTF( m_ab, m_of + of, cb, getCharBuf(cb)); } } // ----- data members --------------------------------------------------- /** * The byte array that holds the binary data. * This value should not be changed. */ @JsonbProperty("byteArray") protected byte[] m_ab; /** * Offset into the byte array at which the binary data is located. * This value should not be changed. */ @JsonbProperty("offset") protected int m_of; /** * Number of bytes in the byte array that belong to this ReadBuffer object. * This value should not be changed. */ @JsonbProperty("length") protected int m_cb; }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy