BoundedNativeMemoryIO.java

  1. package org.jruby.ext.ffi.jffi;

  2. import java.nio.ByteOrder;
  3. import org.jruby.Ruby;
  4. import org.jruby.ext.ffi.*;

  5. class BoundedNativeMemoryIO extends MemoryIO {
  6.     protected static final com.kenai.jffi.MemoryIO IO = com.kenai.jffi.MemoryIO.getInstance();
  7.     protected static final int LONG_SIZE = Platform.getPlatform().longSize();
  8.     protected static final int ADDRESS_SIZE = Platform.getPlatform().addressSize();

  9.     private final Ruby runtime;
  10.     final long size;
  11.     final MemoryIO parent; // keep a reference to avoid the memory being freed

  12.     BoundedNativeMemoryIO(Ruby runtime, long address, int size) {
  13.         super(true, address);
  14.         this.runtime = runtime;
  15.         this.size = size;
  16.         this.parent = null;
  17.     }

  18.     BoundedNativeMemoryIO(BoundedNativeMemoryIO parent, long offset) {
  19.         super(true, parent.address() + offset);
  20.         this.runtime = parent.runtime;
  21.         this.size = parent.size - offset;
  22.         this.parent = parent;
  23.     }

  24.     BoundedNativeMemoryIO(Ruby runtime, MemoryIO parent, long offset, long size) {
  25.         super(true, parent.address() + offset);
  26.         this.runtime = runtime;
  27.         this.size = size;
  28.         this.parent = parent;
  29.         if (!parent.isDirect()) throw new IllegalArgumentException("non-direct memory");
  30.     }

  31.     private final void checkBounds(long off, long len) {
  32.         Util.checkBounds(runtime, size, off, len);
  33.     }

  34.     public Object array() {
  35.         throw runtime.newRuntimeError("no array");
  36.     }

  37.     public int arrayOffset() {
  38.         throw runtime.newRuntimeError("no array");
  39.     }

  40.     public int arrayLength() {
  41.         throw runtime.newRuntimeError("no array");
  42.     }

  43.     public BoundedNativeMemoryIO slice(long offset) {
  44.         checkBounds(offset, 0);
  45.         return offset == 0 ? this :new BoundedNativeMemoryIO(this, offset);
  46.     }

  47.     public BoundedNativeMemoryIO slice(long offset, long size) {
  48.         checkBounds(offset, size);
  49.         return offset == 0 && size == this.size ? this :new BoundedNativeMemoryIO(runtime, this, offset, size);
  50.     }
  51.    
  52.     public MemoryIO dup() {
  53.         AllocatedNativeMemoryIO tmp = AllocatedNativeMemoryIO.allocate(runtime, (int) size, false);
  54.        
  55.         IO.memcpy(tmp.address, address, size);
  56.        
  57.         return tmp;
  58.     }

  59.     public final java.nio.ByteBuffer asByteBuffer() {
  60.         return IO.newDirectByteBuffer(address, (int) size);
  61.     }

  62.     Ruby getRuntime() {
  63.         return this.runtime;
  64.     }

  65.     @Override
  66.     public final boolean equals(Object obj) {
  67.         return (obj instanceof MemoryIO) && ((MemoryIO) obj).address() == address;
  68.     }

  69.     @Override
  70.     public final int hashCode() {
  71.         int hash = 5;
  72.         hash = 53 * hash + (int) (this.address ^ (this.address >>> 32));
  73.         return hash;
  74.     }

  75.     public final ByteOrder order() {
  76.         return ByteOrder.nativeOrder();
  77.     }

  78.     public final byte getByte(long offset) {
  79.         checkBounds(offset, 1);
  80.         return IO.getByte(address + offset);
  81.     }

  82.     public final short getShort(long offset) {
  83.         checkBounds(offset, 2);
  84.         return IO.getShort(address + offset);
  85.     }

  86.     public final int getInt(long offset) {
  87.         checkBounds(offset, 4);
  88.         return IO.getInt(address + offset);
  89.     }

  90.     public final long getLong(long offset) {
  91.         checkBounds(offset, 8);
  92.         return IO.getLong(address + offset);
  93.     }

  94.     public final long getNativeLong(long offset) {
  95.         return LONG_SIZE == 32 ? getInt(offset) : getLong(offset);
  96.     }

  97.     public final float getFloat(long offset) {
  98.         checkBounds(offset, 4);
  99.         return IO.getFloat(address + offset);
  100.     }

  101.     public final double getDouble(long offset) {
  102.         checkBounds(offset, 8);
  103.         return IO.getDouble(address + offset);
  104.     }

  105.     public final long getAddress(long offset) {
  106.         checkBounds(offset, ADDRESS_SIZE >> 3);
  107.         return IO.getAddress(address + offset);
  108.     }

  109.     public final MemoryIO getMemoryIO(long offset) {
  110.         checkBounds(offset, ADDRESS_SIZE >> 3);
  111.         return NativeMemoryIO.wrap(runtime, IO.getAddress(address + offset));
  112.     }

  113.     public final void putByte(long offset, byte value) {
  114.         checkBounds(offset, 1);
  115.         IO.putByte(address + offset, value);
  116.     }

  117.     public final void putShort(long offset, short value) {
  118.         checkBounds(offset, 2);
  119.         IO.putShort(address + offset, value);
  120.     }

  121.     public final void putInt(long offset, int value) {
  122.         checkBounds(offset, 4);
  123.         IO.putInt(address + offset, value);
  124.     }

  125.     public final void putLong(long offset, long value) {
  126.         checkBounds(offset, 8);
  127.         IO.putLong(address + offset, value);
  128.     }

  129.     public final void putNativeLong(long offset, long value) {
  130.         if (LONG_SIZE == 32) {
  131.             putInt(offset, (int) value);
  132.         } else {
  133.             putLong(offset, value);
  134.         }
  135.     }
  136.     public final void putAddress(long offset, long value) {
  137.         checkBounds(offset, ADDRESS_SIZE >> 3);
  138.         IO.putAddress(address + offset, value);
  139.     }
  140.     public final void putFloat(long offset, float value) {
  141.         checkBounds(offset, 4);
  142.         IO.putFloat(address + offset, value);
  143.     }

  144.     public final void putDouble(long offset, double value) {
  145.         checkBounds(offset, 8);
  146.         IO.putDouble(address + offset, value);
  147.     }

  148.     public final void putMemoryIO(long offset, MemoryIO value) {
  149.         checkBounds(offset, ADDRESS_SIZE >> 3);
  150.         IO.putAddress(address + offset, value.address());
  151.     }

  152.     public final void get(long offset, byte[] dst, int off, int len) {
  153.         checkBounds(offset, len);
  154.         IO.getByteArray(address + offset, dst, off, len);
  155.     }

  156.     public final void put(long offset, byte[] src, int off, int len) {
  157.         checkBounds(offset, len);
  158.         IO.putByteArray(address + offset, src, off, len);
  159.     }

  160.     public final void get(long offset, short[] dst, int off, int len) {
  161.         checkBounds(offset, len << 1);
  162.         IO.getShortArray(address + offset, dst, off, len);
  163.     }

  164.     public final void put(long offset, short[] src, int off, int len) {
  165.         checkBounds(offset, len << 1);
  166.         IO.putShortArray(address + offset, src, off, len);
  167.     }

  168.     public final void get(long offset, int[] dst, int off, int len) {
  169.         checkBounds(offset, len << 2);
  170.         IO.getIntArray(address + offset, dst, off, len);
  171.     }

  172.     public final void put(long offset, int[] src, int off, int len) {
  173.         checkBounds(offset, len << 2);
  174.         IO.putIntArray(address + offset, src, off, len);
  175.     }

  176.     public final void get(long offset, long[] dst, int off, int len) {
  177.         checkBounds(offset, len << 3);
  178.         IO.getLongArray(address + offset, dst, off, len);
  179.     }

  180.     public final void put(long offset, long[] src, int off, int len) {
  181.         checkBounds(offset, len << 3);
  182.         IO.putLongArray(address + offset, src, off, len);
  183.     }

  184.     public final void get(long offset, float[] dst, int off, int len) {
  185.         checkBounds(offset, len << 2);
  186.         IO.getFloatArray(address + offset, dst, off, len);
  187.     }

  188.     public final void put(long offset, float[] src, int off, int len) {
  189.         checkBounds(offset, len << 2);
  190.         IO.putFloatArray(address + offset, src, off, len);
  191.     }

  192.     public final void get(long offset, double[] dst, int off, int len) {
  193.         checkBounds(offset, len << 3);
  194.         IO.getDoubleArray(address + offset, dst, off, len);
  195.     }

  196.     public final void put(long offset, double[] src, int off, int len) {
  197.         checkBounds(offset, len << 3);
  198.         IO.putDoubleArray(address + offset, src, off, len);
  199.     }

  200.     public final int indexOf(long offset, byte value) {
  201.         return value == 0
  202.                 ? (int) IO.getStringLength(address + offset)
  203.                 : (int) IO.indexOf(address + offset, value);
  204.     }

  205.     public final int indexOf(long offset, byte value, int maxlen) {
  206.         return (int) IO.indexOf(address, value, maxlen);
  207.     }

  208.     public final void setMemory(long offset, long size, byte value) {
  209.         checkBounds(offset, size);
  210.         IO.setMemory(address + offset, size, value);
  211.     }

  212.     public final byte[] getZeroTerminatedByteArray(long offset) {
  213.         checkBounds(offset, 1);
  214.         return IO.getZeroTerminatedByteArray(address + offset);
  215.     }

  216.     public final byte[] getZeroTerminatedByteArray(long offset, int maxlen) {
  217.         checkBounds(offset, 1);
  218.         return IO.getZeroTerminatedByteArray(address + offset,
  219.                 Math.min(maxlen, (int) (size - offset)));
  220.     }

  221.     public void putZeroTerminatedByteArray(long offset, byte[] bytes, int off, int len) {
  222.         // Ensure room for terminating zero byte
  223.         checkBounds(offset, len + 1);
  224.         IO.putZeroTerminatedByteArray(address + offset, bytes, off, len);
  225.     }

  226. }