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

uk.ac.starlink.util.GenericNioBuffer Maven / Gradle / Ivy

package uk.ac.starlink.util;

import java.lang.reflect.Array;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.ReadOnlyBufferException;
import java.nio.ShortBuffer;

/**
 * Convenience class which wraps one of the NIO <Type>Buffer
 * classes to provide generic functionality.  Using this class merely
 * allows one to invoke some of the methods which are defined on 
 * all the specific buffer types but not on the Buffer superclass itself
 * without a lot of pesky typecasting.
 *
 * @author   Mark Taylor (Starlink)
 */
public class GenericNioBuffer {

    private static abstract class Accessor {
        abstract void get( Object dst, int offset, int length );
        abstract void put( Object scr, int offset, int length );
        abstract Buffer duplicate();
        abstract boolean hasArray();
        abstract int arrayOffset();
        abstract Object array();
        abstract Class getElementClass();
    }

    private final Accessor acc;
    private final Buffer buf;


    /**
     * Construct a GenericNioBuffer based on an existing 
     * {@link java.nio.Buffer}.
     *
     * @param   buf  the NIO buffer
     */
    public GenericNioBuffer( final Buffer buf ) {
        this.buf = buf;
        if ( buf instanceof ByteBuffer ) {
            acc = new Accessor() {
                ByteBuffer buffer = (ByteBuffer) buf;
                void get( Object dst, int offset, int length ) {
                    buffer.get( (byte[]) dst, offset, length );
                }
                void put( Object src, int offset, int length ) {
                    buffer.put( (byte[]) src, offset, length );
                }
                Buffer duplicate() {
                    return buffer.duplicate();
                }
                boolean hasArray() {
                    return buffer.hasArray();
                }
                int arrayOffset() {
                    return buffer.arrayOffset();
                }
                Object array() {
                    return buffer.array();
                }
                Class getElementClass() {
                    return byte.class;
                }
            };
        }
        else if ( buf instanceof ShortBuffer ) {
            acc = new Accessor() {
                ShortBuffer buffer = (ShortBuffer) buf;
                void get( Object dst, int offset, int length ) {
                    buffer.get( (short[]) dst, offset, length );
                }
                void put( Object src, int offset, int length ) {
                    buffer.put( (short[]) src, offset, length );
                }
                Buffer duplicate() {
                    return buffer.duplicate();
                }
                boolean hasArray() {
                    return buffer.hasArray();
                }
                int arrayOffset() {
                    return buffer.arrayOffset();
                }
                Object array() {
                    return buffer.array();
                }
                Class getElementClass() {
                    return short.class;
                }
            };
        }
        else if ( buf instanceof IntBuffer ) {
            acc = new Accessor() {
                IntBuffer buffer = (IntBuffer) buf;
                void get( Object dst, int offset, int length ) {
                    buffer.get( (int[]) dst, offset, length );
                }
                void put( Object src, int offset, int length ) {
                    buffer.put( (int[]) src, offset, length );
                }
                Buffer duplicate() {
                    return buffer.duplicate();
                }
                boolean hasArray() {
                    return buffer.hasArray();
                }
                int arrayOffset() {
                    return buffer.arrayOffset();
                }
                Object array() {
                    return buffer.array();
                }
                Class getElementClass() {
                    return int.class;
                }
            };
        }
        else if ( buf instanceof FloatBuffer ) {
            acc = new Accessor() {
                FloatBuffer buffer = (FloatBuffer) buf;
                void get( Object dst, int offset, int length ) {
                    buffer.get( (float[]) dst, offset, length );
                }
                void put( Object src, int offset, int length ) {
                    buffer.put( (float[]) src, offset, length );
                }
                Buffer duplicate() {
                    return buffer.duplicate();
                }
                boolean hasArray() {
                    return buffer.hasArray();
                }
                int arrayOffset() {
                    return buffer.arrayOffset();
                }
                Object array() {
                    return buffer.array();
                }
                Class getElementClass() {
                    return float.class;
                }
            };
        }
        else if ( buf instanceof DoubleBuffer ) {
            acc = new Accessor() {
                DoubleBuffer buffer = (DoubleBuffer) buf;
                void get( Object dst, int offset, int length ) {
                    buffer.get( (double[]) dst, offset, length );
                }
                void put( Object src, int offset, int length ) {
                    buffer.put( (double[]) src, offset, length );
                }
                Buffer duplicate() {
                    return buffer.duplicate();
                }
                boolean hasArray() {
                    return buffer.hasArray();
                }
                int arrayOffset() {
                    return buffer.arrayOffset();
                }
                Object array() {
                    return buffer.array();
                }
                Class getElementClass() {
                    return double.class;
                }
            };
        }
        else { 
            throw new IllegalArgumentException(
                "Buffer " + buf + " is of unsupported type" ); 
        }
    }

    /**
     * Returns the buffer object on which this generic buffer is based.
     *
     * @return  the buffer set at construction
     */
    public Buffer getBuffer() {
        return buf;
    }

    /**
     * Generic relative bulk get method.
     * Fils a given destination array with primitives transferred 
     * from this buffer.
     *
     * @param   dst   an array of primitives matching the type of the 
     *                nio Buffer
     * @see java.nio.DoubleBuffer#get(double[])
     */
    public void get( Object dst ) {
        acc.get( dst, 0, Array.getLength( dst ) );
    }

    /**
     * Generic relative bulk get method.
     * Transfers a given number of primitives from this buffer into 
     * the given destination array starting at a given offset into the array.
     *
     * @param   dst   an array of primitives matching the type of the
     *                nio Buffer
     * @param   offset  the offset within the array of the first primitive
     *                  to be written
     * @param   length  the number of primitives to be transferred
     * @see java.nio.DoubleBuffer#get(double[],int,int)
     */
    public void get( Object dst, int offset, int length ) {
        acc.get( dst, offset, length );
    }

    /**
     * Generic relative bulk put method.
     * Transfers the entire content of the given source array into this buffer.
     *
     * @param   src   an array of primitives matching the type of the 
     *                nio Buffer
     * @see java.nio.DoubleBuffer#put(double[])
     */
    public void put( Object src ) {
        acc.put( src, 0, Array.getLength( src ) );
    }

    /**
     * Generic relative bulk put method.
     * Transfers a given number of primitives from the given source 
     * array starting at a given point into this buffer.
     *
     * @param   src   an array of primitives matching the type of the 
     *                nio Buffer
     * @param   offset  the offset within the array of the first primitive
     *                  to be read
     * @param   length  the number of primitives to tranfer
     * @see java.nio.DoubleBuffer#put(double[],int,int)
     */
    public void put( Object src, int offset, int length ) {
        acc.put( src, offset, length );
    }

    /**
     * Creates a new buffer that shares this buffer's content.
     * 

* The content of the new buffer will be that of this buffer. * Changes to this buffer's content will be visible in the new * buffer, and vice versa; the two buffers' position, limit, and mark * values will be independent. *

* The new buffer's capacity, limit, position, and mark values will * be identical to those of this buffer. The new buffer will be direct * if, and only if, this buffer is direct, and it will be * read-only if, and only if, this buffer is read-only. * * @return the new buffer. Note it is a java.nio.Buffer and not * a copy of this GenericNioBuffer * @see java.nio.DoubleBuffer#duplicate */ public Buffer duplicate() { return acc.duplicate(); } /** * Tells whether or not this buffer is backed by an accessible * primitive array. If this method returns true then the * {@link #array} and {@link #arrayOffset} methods may safely be * invoked. * * @return true if, and only if, this buffer is backed by an array * and is not read-only * @see java.nio.DoubleBuffer#hasArray */ public boolean hasArray() { return acc.hasArray(); } /** * Returns the primitive array that backs this buffer * (optional operation). * Modifications to this buffer's content will cause the returned * array's content to be modified, and vice versa. *

* Invoke the {@link #hasArray} method before invoking this method in * order to ensure that this buffer has an accessible backing array. * * @return the array that backs this buffer * @throws ReadOnlyBufferException if this buffer is backed by an * array but is read-only * @throws UnsupportedOperationException if this buffer is not backed * by an accessible array */ public Object array() { return acc.array(); } /** * Returns the offset within this buffer's backing array of the first * element of the buffer (optional operation). * If this buffer is backed by an array then buffer position p * corresponds to array index p + arrayOffset(). *

* Invoke the {@link #hasArray} method before invoking this method in * order to ensure that this buffer has an accessible backing array. * * @return the offset within this buffer's array of the first * element of the buffer * @throws ReadOnlyBufferException if this buffer is backed by an * array but is read-only * @throws UnsupportedOperationException if this buffer is not backed * by an accessible array */ public int arrayOffset() { return acc.arrayOffset(); } /** * Returns the class object of the primitive type that the buffer * holds. Thus double.class is returned if the base buffer * is a DoubleBuffer etc. * * @return the class of the primitive elements that this buffer holds */ public Class getElementClass() { return acc.getElementClass(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy