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

org.robovm.rt.bro.BufferMarshalers Maven / Gradle / Ivy

/*
 * Copyright (C) 2013 Trillian Mobile AB
 *
 * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.robovm.rt.bro;

import java.lang.reflect.Field;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.LongBuffer;
import java.nio.ShortBuffer;

import org.robovm.rt.VM;
import org.robovm.rt.bro.annotation.MarshalsArray;
import org.robovm.rt.bro.annotation.MarshalsPointer;

/**
 * Contains marshalers for {@link Buffer} subclasses.
 */
public class BufferMarshalers {

    /**
     * Marshals to/from {@link ByteBuffer}, {@link ShortBuffer}, 
     * {@link CharBuffer}, {@link IntBuffer}, {@link LongBuffer}, 
     * {@link FloatBuffer} and {@link DoubleBuffer}.
     */
    public static class BufferMarshaler {
        private static final int EFFECTIVE_DIRECT_ADDRESS_OFFSET;
        private static final int _ELEMENT_SIZE_SHIFT_OFFSET;

        static {
            try {
                Field f1 = Buffer.class.getDeclaredField("effectiveDirectAddress");
                if (f1.getType() != long.class) {
                    throw new Error("java.nio.Buffer.effectiveDirectAddress should be a long");
                }
                EFFECTIVE_DIRECT_ADDRESS_OFFSET = VM.getInstanceFieldOffset(VM.getFieldAddress(f1));
                Field f2 = Buffer.class.getDeclaredField("_elementSizeShift");
                _ELEMENT_SIZE_SHIFT_OFFSET = VM.getInstanceFieldOffset(VM.getFieldAddress(f2));
            } catch (NoSuchFieldException e) {
                throw new Error(e);
            }
        }
        
        @MarshalsPointer(supportedCallTypes = MarshalerFlags.CALL_TYPE_BRIDGE)
        public static long toNative(Buffer buffer, long flags) {
            if (buffer == null) {
                return 0L;
            }

            if (!buffer.isDirect() && !buffer.hasArray()) {
                // Non-direct buffers must be backed by an array to be supported.
                // We could have made a copy of the buffer contents and returned
                // a pointer to that but then changes made to the contents by
                // native code wouldn't be visible in the original buffer and
                // the semantics would be different depending on the type of
                // the buffer.
                throw new IllegalArgumentException("Only direct and array-backed " 
                        + "java.nio.Buffers can be marshaled to pointers.");
            }

            if (buffer.isDirect()) {
                return VM.getLong(VM.getObjectAddress(buffer) + EFFECTIVE_DIRECT_ADDRESS_OFFSET);
            } else {
                Object array = buffer.array();
                int offset = buffer.arrayOffset();
                int shift = VM.getInt(VM.getObjectAddress(buffer) + _ELEMENT_SIZE_SHIFT_OFFSET);
                return VM.getArrayValuesAddress(array) + (offset << shift);
            }
        }
        
        private static void copyBuffer(Buffer buffer, long handle, long flags, int d1) {
            if (d1 != buffer.capacity()) {
                Class cls = null;
                if (buffer instanceof ByteBuffer) {
                    cls = ByteBuffer.class;
                } else if (buffer instanceof ShortBuffer) {
                    cls = ShortBuffer.class;
                } else if (buffer instanceof CharBuffer) {
                    cls = CharBuffer.class;
                } else if (buffer instanceof IntBuffer) {
                    cls = IntBuffer.class;
                } else if (buffer instanceof LongBuffer) {
                    cls = LongBuffer.class;
                } else if (buffer instanceof FloatBuffer) {
                    cls = FloatBuffer.class;
                } else if (buffer instanceof DoubleBuffer) {
                    cls = DoubleBuffer.class;
                }
                throw new IllegalArgumentException("Expected " + 
                        cls.getName() + " of capacity " + d1 
                        + ". Got " + cls.getName() + " of capacity " 
                        + buffer.capacity());
            }

            long src = 0L;
            Object array = null;
            int offset = 0;
            int shift = VM.getInt(VM.getObjectAddress(buffer) + _ELEMENT_SIZE_SHIFT_OFFSET);
            if (buffer.isDirect()) {
                src = VM.getLong(VM.getObjectAddress(buffer) + EFFECTIVE_DIRECT_ADDRESS_OFFSET);
            } else {
                if (buffer.hasArray()) {
                    array = buffer.array();
                    offset = buffer.arrayOffset();
                } else {
                    int pos = buffer.position();
                    int limit = buffer.limit();
                    buffer.position(0);
                    buffer.limit(buffer.capacity());
                    if (buffer instanceof ByteBuffer) {
                        array = new byte[d1];
                        ((ByteBuffer) buffer).get((byte[]) array);
                    } else if (buffer instanceof ShortBuffer) {
                        array = new short[d1];
                        ((ShortBuffer) buffer).get((short[]) array);
                    } else if (buffer instanceof CharBuffer) {
                        array = new char[d1];
                        ((CharBuffer) buffer).get((char[]) array);
                    } else if (buffer instanceof IntBuffer) {
                        array = new int[d1];
                        ((IntBuffer) buffer).get((int[]) array);
                    } else if (buffer instanceof LongBuffer) {
                        array = new long[d1];
                        ((LongBuffer) buffer).get((long[]) array);
                    } else if (buffer instanceof FloatBuffer) {
                        array = new float[d1];
                        ((FloatBuffer) buffer).get((float[]) array);
                    } else if (buffer instanceof DoubleBuffer) {
                        array = new double[d1];
                        ((DoubleBuffer) buffer).get((double[]) array);
                    }
                    buffer.position(pos);
                    buffer.limit(limit);
                }
                
                src = VM.getArrayValuesAddress(array);
            }
            
            VM.memcpy(handle, src + (offset << shift), d1 << shift);
        }
        
        @MarshalsArray
        public static ByteBuffer toByteBuffer(Class cls, long handle, long flags, int d1) {
            return VM.newDirectByteBuffer(handle, d1);
        }
        @MarshalsArray
        public static void toNative(ByteBuffer buffer, long handle, long flags, int d1) {
            copyBuffer(buffer, handle, flags, d1);
        }
        @MarshalsArray
        public static ByteBuffer toByteBuffer(Class cls, long handle, long flags, int d1, int d2) {
            return toByteBuffer(cls, handle, flags, d1 * d2);
        }
        @MarshalsArray
        public static void toNative(ByteBuffer buffer, long handle, long flags, int d1, int d2) {
            copyBuffer(buffer, handle, flags, d1 * d2);
        }
        @MarshalsArray
        public static ByteBuffer toByteBuffer(Class cls, long handle, long flags, int d1, int d2, int d3) {
            return toByteBuffer(cls, handle, flags, d1 * d2 * d3);
        }
        @MarshalsArray
        public static void toNative(ByteBuffer buffer, long handle, long flags, int d1, int d2, int d3) {
            copyBuffer(buffer, handle, flags, d1 * d2 * d3);
        }
        
        @MarshalsArray
        public static ShortBuffer toShortBuffer(Class cls, long handle, long flags, int d1) {
            return VM.newDirectByteBuffer(handle, d1 << 1).order(ByteOrder.nativeOrder()).asShortBuffer();
        }
        @MarshalsArray
        public static void toNative(ShortBuffer buffer, long handle, long flags, int d1) {
            copyBuffer(buffer, handle, flags, d1);
        }
        @MarshalsArray
        public static ShortBuffer toShortBuffer(Class cls, long handle, long flags, int d1, int d2) {
            return toShortBuffer(cls, handle, flags, d1 * d2);
        }
        @MarshalsArray
        public static void toNative(ShortBuffer buffer, long handle, long flags, int d1, int d2) {
            copyBuffer(buffer, handle, flags, d1 * d2);
        }
        @MarshalsArray
        public static ShortBuffer toShortBuffer(Class cls, long handle, long flags, int d1, int d2, int d3) {
            return toShortBuffer(cls, handle, flags, d1 * d2 * d3);
        }
        @MarshalsArray
        public static void toNative(ShortBuffer buffer, long handle, long flags, int d1, int d2, int d3) {
            copyBuffer(buffer, handle, flags, d1 * d2 * d3);
        }
        
        @MarshalsArray
        public static CharBuffer toCharBuffer(Class cls, long handle, long flags, int d1) {
            return VM.newDirectByteBuffer(handle, d1 << 1).order(ByteOrder.nativeOrder()).asCharBuffer();
        }
        @MarshalsArray
        public static void toNative(CharBuffer buffer, long handle, long flags, int d1) {
            copyBuffer(buffer, handle, flags, d1);
        }
        @MarshalsArray
        public static CharBuffer toCharBuffer(Class cls, long handle, long flags, int d1, int d2) {
            return toCharBuffer(cls, handle, flags, d1 * d2);
        }
        @MarshalsArray
        public static void toNative(CharBuffer buffer, long handle, long flags, int d1, int d2) {
            copyBuffer(buffer, handle, flags, d1 * d2);
        }
        @MarshalsArray
        public static CharBuffer toCharBuffer(Class cls, long handle, long flags, int d1, int d2, int d3) {
            return toCharBuffer(cls, handle, flags, d1 * d2 * d3);
        }
        @MarshalsArray
        public static void toNative(CharBuffer buffer, long handle, long flags, int d1, int d2, int d3) {
            copyBuffer(buffer, handle, flags, d1 * d2 * d3);
        }
        
        @MarshalsArray
        public static IntBuffer toIntBuffer(Class cls, long handle, long flags, int d1) {
            return VM.newDirectByteBuffer(handle, d1 << 2).order(ByteOrder.nativeOrder()).asIntBuffer();
        }
        @MarshalsArray
        public static void toNative(IntBuffer buffer, long handle, long flags, int d1) {
            copyBuffer(buffer, handle, flags, d1);
        }
        @MarshalsArray
        public static IntBuffer toIntBuffer(Class cls, long handle, long flags, int d1, int d2) {
            return toIntBuffer(cls, handle, flags, d1 * d2);
        }
        @MarshalsArray
        public static void toNative(IntBuffer buffer, long handle, long flags, int d1, int d2) {
            copyBuffer(buffer, handle, flags, d1 * d2);
        }
        @MarshalsArray
        public static IntBuffer toIntBuffer(Class cls, long handle, long flags, int d1, int d2, int d3) {
            return toIntBuffer(cls, handle, flags, d1 * d2 * d3);
        }
        @MarshalsArray
        public static void toNative(IntBuffer buffer, long handle, long flags, int d1, int d2, int d3) {
            copyBuffer(buffer, handle, flags, d1 * d2 * d3);
        }
        
        @MarshalsArray
        public static LongBuffer toLongBuffer(Class cls, long handle, long flags, int d1) {
            return VM.newDirectByteBuffer(handle, d1 << 3).order(ByteOrder.nativeOrder()).asLongBuffer();
        }
        @MarshalsArray
        public static void toNative(LongBuffer buffer, long handle, long flags, int d1) {
            copyBuffer(buffer, handle, flags, d1);
        }
        @MarshalsArray
        public static LongBuffer toLongBuffer(Class cls, long handle, long flags, int d1, int d2) {
            return toLongBuffer(cls, handle, flags, d1 * d2);
        }
        @MarshalsArray
        public static void toNative(LongBuffer buffer, long handle, long flags, int d1, int d2) {
            copyBuffer(buffer, handle, flags, d1 * d2);
        }
        @MarshalsArray
        public static LongBuffer toLongBuffer(Class cls, long handle, long flags, int d1, int d2, int d3) {
            return toLongBuffer(cls, handle, flags, d1 * d2 * d3);
        }
        @MarshalsArray
        public static void toNative(LongBuffer buffer, long handle, long flags, int d1, int d2, int d3) {
            copyBuffer(buffer, handle, flags, d1 * d2 * d3);
        }
        
        @MarshalsArray
        public static FloatBuffer toFloatBuffer(Class cls, long handle, long flags, int d1) {
            return VM.newDirectByteBuffer(handle, d1 << 2).order(ByteOrder.nativeOrder()).asFloatBuffer();
        }
        @MarshalsArray
        public static void toNative(FloatBuffer buffer, long handle, long flags, int d1) {
            copyBuffer(buffer, handle, flags, d1);
        }
        @MarshalsArray
        public static FloatBuffer toFloatBuffer(Class cls, long handle, long flags, int d1, int d2) {
            return toFloatBuffer(cls, handle, flags, d1 * d2);
        }
        @MarshalsArray
        public static void toNative(FloatBuffer buffer, long handle, long flags, int d1, int d2) {
            copyBuffer(buffer, handle, flags, d1 * d2);
        }
        @MarshalsArray
        public static FloatBuffer toFloatBuffer(Class cls, long handle, long flags, int d1, int d2, int d3) {
            return toFloatBuffer(cls, handle, flags, d1 * d2 * d3);
        }
        @MarshalsArray
        public static void toNative(FloatBuffer buffer, long handle, long flags, int d1, int d2, int d3) {
            copyBuffer(buffer, handle, flags, d1 * d2 * d3);
        }
        
        @MarshalsArray
        public static DoubleBuffer toDoubleBuffer(Class cls, long handle, long flags, int d1) {
            return VM.newDirectByteBuffer(handle, d1 << 3).order(ByteOrder.nativeOrder()).asDoubleBuffer();
        }
        @MarshalsArray
        public static void toNative(DoubleBuffer buffer, long handle, long flags, int d1) {
            copyBuffer(buffer, handle, flags, d1);
        }
        @MarshalsArray
        public static DoubleBuffer toDoubleBuffer(Class cls, long handle, long flags, int d1, int d2) {
            return toDoubleBuffer(cls, handle, flags, d1 * d2);
        }
        @MarshalsArray
        public static void toNative(DoubleBuffer buffer, long handle, long flags, int d1, int d2) {
            copyBuffer(buffer, handle, flags, d1 * d2);
        }
        @MarshalsArray
        public static DoubleBuffer toDoubleBuffer(Class cls, long handle, long flags, int d1, int d2, int d3) {
            return toDoubleBuffer(cls, handle, flags, d1 * d2 * d3);
        }
        @MarshalsArray
        public static void toNative(DoubleBuffer buffer, long handle, long flags, int d1, int d2, int d3) {
            copyBuffer(buffer, handle, flags, d1 * d2 * d3);
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy