Package org.jruby.ext.ffi.jna

Source Code of org.jruby.ext.ffi.jna.JNAMemoryIO$BufferIO

/***** BEGIN LICENSE BLOCK *****
* Version: CPL 1.0/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Common Public
* License Version 1.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.eclipse.org/legal/cpl-v10.html
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* Copyright (C) 2008 JRuby project
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the CPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the CPL, the GPL or the LGPL.
***** END LICENSE BLOCK *****/

package org.jruby.ext.ffi.jna;

import org.jruby.ext.ffi.*;
import com.sun.jna.Memory;
import com.sun.jna.NativeLong;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.LongByReference;
import com.sun.jna.ptr.PointerByReference;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import org.jruby.util.ByteList;

/**
* JNA implementation of memory I/O operations.
*/
public abstract class JNAMemoryIO implements MemoryIO {
    /**
     * The native memory pointer
     */
    final Object memory;

    /**
     * NULL Pointer MemoryIO
     */
    static final JNAMemoryIO NULL = new PointerIO(Pointer.NULL, 0);

    /**
     * Allocates a new block of java heap memory and wraps it in a {@link MemoryIO}
     * accessor.
     *
     * @param size The size in bytes of memory to allocate.
     *
     * @return A new <tt>MemoryIO</tt> instance that can access the memory.
     */
    static final JNAMemoryIO allocate(int size) {
        return new BufferIO(size);
    }
   
    /**
     * Allocates a new block of native memory and wraps it in a {@link MemoryIO}
     * accessor.
     *
     * @param size The size in bytes of memory to allocate.
     *
     * @return A new <tt>MemoryIO</tt> instance that can access the memory.
     */
    static final JNAMemoryIO allocateDirect(int size) {
        return new PointerIO(size);
    }
   
    /**
     * Creates a new JNA <tt>MemoryIO</tt> instance.
     *
     * @param memory The memory object to wrap.
     */
    JNAMemoryIO(Object memory) {
        this.memory = memory;
    }
   
    /**
     * Gets the underlying memory object this <tt>MemoryIO</tt> is wrapping.
     *
     * @return The native pointer or ByteBuffer.
     */
    Object getMemory() {
        return memory;
    }
   
    /**
     * Wraps a <tt>MemoryIO</tt> accessor around an existing native memory area.
     *
     * @param ptr The native pointer to wrap.
     * @return A new <tt>MemoryIO</tt> instance that can access the memory.
     */
    static final JNAMemoryIO wrap(Pointer ptr) {
        return ptr != null ? new PointerIO(ptr, 0) : NULL;
    }
   
    /**
     * Wraps a <tt>MemoryIO</tt> accessor around an existing <tt>ByteList</tt>
     *
     * @param buf The <tt>ByteList</tt> to wrap.
     * @return A new <tt>MemoryIO</tt> instance that can access the memory.
     */
    static JNAMemoryIO wrap(ByteList buf) {
        return new BufferIO(ByteBuffer.wrap(buf.unsafeBytes(), buf.begin(), buf.length()));
    }
    public abstract Pointer getAddress();
    public abstract Pointer getPointer(long offset);
    public abstract void putPointer(long offset, Pointer value);
    public abstract JNAMemoryIO slice(long offset);

    @Override
    public boolean equals(Object obj) {
        return (obj instanceof JNAMemoryIO) && ((JNAMemoryIO) obj).memory.equals(memory);
    }

    @Override
    public int hashCode() {
        return memory.hashCode();
    }
    public JNAMemoryIO getMemoryIO(long offset) {
        return JNAMemoryIO.wrap(getPointer(offset));
    }
    public void putMemoryIO(long offset, MemoryIO value) {
        putPointer(offset, ((JNAMemoryIO) value).getAddress());
    }
   
    /**
     * A <tt>MemoryIO</tt> accessor that wraps a native pointer.
     */
    static final class PointerIO extends JNAMemoryIO {
        /**
         * The native pointer.
         */
        final Pointer ptr;

        /**
         * The size of the memory area.
         */
        final long size;

       
        private PointerIO() {
            this(Pointer.NULL, 0);
        }
        /**
         * Allocates a new block of native memory and wraps it in a {@link MemoryIO}
         * accessor.
         *
         * @param size The size in bytes of memory to allocate.
         *
         */
        private PointerIO(long size) {
            this(new Memory(size), size);
        }
        private PointerIO(Pointer ptr, long size) {
            super(ptr);
            this.ptr = ptr;
            this.size = size;
        }
        public Pointer getAddress() {
            return ptr;
        }
        public boolean isNull() {
            return ptr == null;
        }
        public byte getByte(long offset) {
            return ptr.getByte(offset);
        }

        public short getShort(long offset) {
            return ptr.getShort(offset);
        }

        public int getInt(long offset) {
            return ptr.getInt(offset);
        }

        public long getLong(long offset) {
            return ptr.getLong(offset);
        }

        public long getNativeLong(long offset) {
            return ptr.getNativeLong(offset).longValue();
        }

        public float getFloat(long offset) {
            return ptr.getFloat(offset);
        }

        public double getDouble(long offset) {
            return ptr.getDouble(offset);
        }
        public Pointer getPointer(long offset) {
            return ptr.getPointer(offset);
        }
       
        public void putByte(long offset, byte value) {
            ptr.setByte(offset, value);
        }

        public void putShort(long offset, short value) {
            ptr.setShort(offset, value);
        }

        public void putInt(long offset, int value) {
            ptr.setInt(offset, value);
        }

        public void putLong(long offset, long value) {
            ptr.setLong(offset, value);
        }

        public void putNativeLong(long offset, long value) {
            ptr.setNativeLong(offset, new NativeLong(value));
        }

        public void putFloat(long offset, float value) {
            ptr.setFloat(offset, value);
        }

        public void putDouble(long offset, double value) {
            ptr.setDouble(offset, value);
        }
       
        public void putPointer(long offset, Pointer value) {
            ptr.setPointer(offset, value);
        }
        public void get(long offset, byte[] dst, int off, int len) {
            ptr.read(offset, dst, off, len);
        }

        public void put(long offset, byte[] dst, int off, int len) {
            ptr.write(offset, dst, off, len);
        }

        public void get(long offset, short[] dst, int off, int len) {
            ptr.read(offset, dst, off, len);
        }

        public void put(long offset, short[] dst, int off, int len) {
            ptr.write(offset, dst, off, len);
        }

        public void get(long offset, int[] dst, int off, int len) {
            ptr.read(offset, dst, off, len);
        }

        public void put(long offset, int[] dst, int off, int len) {
            ptr.write(offset, dst, off, len);
        }

        public void get(long offset, long[] dst, int off, int len) {
            ptr.read(offset, dst, off, len);
        }

        public void put(long offset, long[] dst, int off, int len) {
            ptr.write(offset, dst, off, len);
        }

        public void get(long offset, float[] dst, int off, int len) {
            ptr.read(offset, dst, off, len);
        }

        public void put(long offset, float[] dst, int off, int len) {
            ptr.write(offset, dst, off, len);
        }

        public void get(long offset, double[] dst, int off, int len) {
            ptr.read(offset, dst, off, len);
        }

        public void put(long offset, double[] dst, int off, int len) {
            ptr.write(offset, dst, off, len);
        }

        public int indexOf(long offset, byte value) {
            return (int) ptr.indexOf(offset, value);
        }

        public int indexOf(long offset, byte value, int maxlen) {
            return (int) ptr.indexOf(offset, value);
        }
        public void setMemory(long offset, long size, byte value) {
            ptr.setMemory(offset, size, value);
        }
        public void clear() {
            setMemory(0, size, (byte) 0);
        }
        public JNAMemoryIO slice(long offset) {
            return offset == 0 ? this : new PointerIO(ptr.share(offset), size - offset);
        }

        @Override
        public boolean equals(Object obj) {
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            final PointerIO other = (PointerIO) obj;
            if (this.ptr != other.ptr && (this.ptr == null || !this.ptr.equals(other.ptr))) {
                return false;
            }
            return true;
        }

        @Override
        public int hashCode() {
            return ptr == null ? 0 : ptr.hashCode();
        }

    }
    private static class BufferIO extends JNAMemoryIO {
        final ByteBuffer buffer;
        BufferIO(int size) {
            this(ByteBuffer.allocate(size).order(ByteOrder.nativeOrder()));
        }
        BufferIO(ByteBuffer buffer) {
            super(buffer);
            this.buffer = buffer;
            throw new RuntimeException("Not implemented");
        }
        public Pointer getAddress() {
            return Pointer.NULL;
        }
        public boolean isNull() {
            return false;
        }
        static ByteBuffer slice(ByteBuffer buffer, int position, int size) {
            ByteBuffer tmp = buffer.duplicate();
            tmp.position(position).limit(position + size);
            return tmp.slice();
        }
        @Override
        public Pointer getPointer(long offset) {
            if (Platform.getPlatform().longSize() == 32) {
                IntByReference ref = new IntByReference(getInt(offset));
                return ref.getPointer().getPointer(0);
            } else {
                LongByReference ref = new LongByReference(getLong(offset));
                return ref.getPointer().getPointer(0);
            }
        }

        @Override
        public void putPointer(long offset, Pointer value) {
            PointerByReference ref = new PointerByReference(value);
            if (Platform.getPlatform().longSize() == 32) {
                putInt(offset, ref.getPointer().getInt(0));
            } else {
                putLong(offset, ref.getPointer().getLong(0));
            }
        }

        public byte getByte(long offset) {
            return buffer.get((int) offset);
        }

        public short getShort(long offset) {
            return buffer.getShort((int) offset);
        }

        public int getInt(long offset) {
            return buffer.getInt((int) offset);
        }

        public long getLong(long offset) {
            return buffer.getLong((int) offset);
        }

        public long getNativeLong(long offset) {
            return NativeLong.SIZE == 4
                    ? buffer.getInt((int) offset)
                    : buffer.getLong((int) offset);
        }

        public float getFloat(long offset) {
            return buffer.getFloat((int) offset);
        }

        public double getDouble(long offset) {
            return buffer.getDouble((int) offset);
        }

        public void putByte(long offset, byte value) {
            buffer.put((int) offset, value);
        }

        public void putShort(long offset, short value) {
            buffer.putShort((int) offset, value);
        }

        public void putInt(long offset, int value) {
            buffer.putInt((int) offset, value);
        }

        public void putLong(long offset, long value) {
            buffer.putLong((int) offset, value);
        }

        public void putNativeLong(long offset, long value) {
            if (NativeLong.SIZE == 4) {
                putInt(offset, (int) value);
            } else {
                putLong(offset, value);
            }
        }

        public void putFloat(long offset, float value) {
            buffer.putFloat((int) offset, value);
        }

        public void putDouble(long offset, double value) {
            buffer.putDouble((int) offset, value);
        }

        public void get(long offset, byte[] dst, int off, int len) {
            slice(buffer, (int) offset, len).get(dst, off, len);
        }

        public void put(long offset, byte[] dst, int off, int len) {
            slice(buffer, (int) offset, len).put(dst, off, len);
        }

        public void get(long offset, short[] dst, int off, int len) {
            slice(buffer, (int) offset, len * 2).asShortBuffer().get(dst, off, len);
        }

        public void put(long offset, short[] dst, int off, int len) {
            slice(buffer, (int) offset, len * 2).asShortBuffer().put(dst, off, len);
        }

        public void get(long offset, int[] dst, int off, int len) {
            slice(buffer, (int) offset, len * 4).asIntBuffer().get(dst, off, len);
        }

        public void put(long offset, int[] dst, int off, int len) {
            slice(buffer, (int) offset, len * 4).asIntBuffer().put(dst, off, len);
        }

        public void get(long offset, long[] dst, int off, int len) {
            slice(buffer, (int) offset, len * 8).asLongBuffer().get(dst, off, len);
        }

        public void put(long offset, long[] dst, int off, int len) {
            slice(buffer, (int) offset, len * 8).asLongBuffer().put(dst, off, len);
        }

        public void get(long offset, float[] dst, int off, int len) {
            slice(buffer, (int) offset, len * 4).asFloatBuffer().get(dst, off, len);
        }

        public void put(long offset, float[] dst, int off, int len) {
            slice(buffer, (int) offset, len * 4).asFloatBuffer().put(dst, off, len);
        }

        public void get(long offset, double[] dst, int off, int len) {
            slice(buffer, (int) offset, len * 8).asDoubleBuffer().get(dst, off, len);
        }

        public void put(long offset, double[] dst, int off, int len) {
            slice(buffer, (int) offset, len * 8).asDoubleBuffer().put(dst, off, len);
        }

        public int indexOf(long offset, byte value) {
            return indexOf(offset, value, Integer.MAX_VALUE);
        }

        public int indexOf(long offset, byte value, int maxlen) {
            for (; offset > -1; ++offset) {
                if (buffer.get((int) offset) == value) {
                    return (int) offset;
                }
            }
            return -1;
        }
        public void setMemory(long offset, long size, byte value) {
            for (int i = 0; i < size; ++i) {
                buffer.put(i, value);
            }
        }
        public void clear() {
            setMemory(0, buffer.capacity(), (byte) 0);
        }

        @Override
        public JNAMemoryIO slice(long offset) {
            return offset == 0
                    ? this
                    : new BufferIO(slice(buffer, (int) offset, buffer.capacity() - (int) offset));
        }
    }
}
TOP

Related Classes of org.jruby.ext.ffi.jna.JNAMemoryIO$BufferIO

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.