io.qt.QNativePointer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of qtjambi Show documentation
Show all versions of qtjambi Show documentation
QtJambi base module containing QtCore, QtGui and QtWidgets.
/****************************************************************************
**
** Copyright (C) 1992-2009 Nokia. All rights reserved.
** Copyright (C) 2009-2024 Dr. Peter Droste, Omix Visualization GmbH & Co. KG. All rights reserved.
**
** This file is part of QtJambi.
**
** $BEGIN_LICENSE$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
** $END_LICENSE$
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
****************************************************************************/
package io.qt;
import java.lang.ref.WeakReference;
import java.nio.Buffer;
import java.nio.ByteBuffer;
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 java.util.ArrayList;
import java.util.List;
import io.qt.core.QIODevice;
/**
* Represents a native pointer.
*/
public final class QNativePointer {
static {
io.qt.QtUtilities.initializePackage("io.qt.internal");
}
/**
* The type of the pointer.
*/
public enum Type implements QtEnumerator{
/** representing bool*
*/ Boolean,
/** representing char*
*/ Byte,
/** representing char_16*
*/ Char,
/** representing short*
*/ Short,
/** representing int*
*/ Int,
/** representing long long*
*/ Long,
/** representing float*
*/ Float,
/** representing double*
*/ Double,
/** representing void* or any other typeed pointer
*/ Pointer,
/** representing char *const*
*/ String;
public static Type resolve(int type) {
switch (type) {
case 0:
return Type.Boolean;
case 1:
return Type.Byte;
case 2:
return Type.Char;
case 3:
return Type.Short;
case 4:
return Type.Int;
case 5:
return Type.Long;
case 6:
return Type.Float;
case 7:
return Type.Double;
case 8:
return Type.Pointer;
case 9:
return Type.String;
default:
throw new QNoSuchEnumValueException(type);
}
}
}
/**
* The AutoDeleteMode enum describes how garbage collection of the
* QNativePointer handles the deletion of the native pointer. By default,
* the mode is set to Delete or DeleteArray.
*/
public enum AutoDeleteMode implements QtEnumerator{
/**
* Use this deletion mode if you do not want to delete the c++ pointer
* when the QNativePointer object is garbage collected.
*/
None,
/**
* Free must be used if the pointer was allocated using c++ free()
.
* Currently, no pointers in QtJambi is allocated in this manner.
*/
Free,
/**
* The pointer is allocated with c++ new
.
* This should be used for all pointers in QtJambi
*/
Delete,
/**
* This must be the mode of deletion if the pointer is an array.
*/
DeleteArray;
public static AutoDeleteMode resolve(int type) {
switch (type) {
case 0:
return None;
case 1:
return Free;
case 2:
return Delete;
case 3:
return DeleteArray;
default:
throw new QNoSuchEnumValueException(type);
}
}
}
/**
* Creates a native pointer of the specified type
.
* The object has an indirection of 1 and the internal pointer
* will be deleted when the QNativePointer object is deleted.
*
* @param type the type of pointer to create.
*/
public QNativePointer(Type type) {
this(type, 1);
}
/**
* Creates a native pointer to an array with size
* length of the specified type
. The pointer will
* have an indirection of 1 and be deleted when the QNativePointer
* is garbage collected.
*
* @param type the type of pointer to create.
* @param size the size of the array.
*/
public QNativePointer(Type type, long size) {
this(type, size, 1);
}
/**
* Creates a native pointer of the specified type
.
* It will be an array if size
is larger than one and
* have an indirection of indirections
. For instance,
* the following Java statement will create a **char
* pointer with the first array dimension of length 5:
* QNativePointer ptr = new
* QNativePointer(QNativePointer.Type.Int, 5, 2);
*
* @param type the type of pointer to create.
* @param size the length of the array.
* @param indirections the number of indirections for the pointer.
*/
public QNativePointer(Type type, long size, int indirections) {
this(type, size, indirections, false);
}
private QNativePointer(Type type, long size, int indirections, boolean isReadOnly) {
data = new Data();
QtJambi_LibraryUtilities.internal.registerCleaner(this, this.data::dispose);
if (indirections < 1)
throw new IllegalArgumentException("level of indirection must be at least 1");
if (size == 0)
throw new IllegalArgumentException("size must be at least 1");
data.m_ptr = createPointer(type.ordinal(), size, indirections);
data.m_type = type;
data.m_knownSize = size;
data.m_indirections = indirections;
data.m_autodelete = size == 1 ? AutoDeleteMode.Delete : AutoDeleteMode.DeleteArray;
data.m_isReadonly = isReadOnly;
}
@NativeAccess
private QNativePointer(int type, long size, int indirections, long ptr, boolean isReadOnly) {
data = new Data();
QtJambi_LibraryUtilities.internal.registerCleaner(this, this.data::dispose);
data.m_ptr = ptr;
data.m_type = Type.resolve(type);
data.m_knownSize = size;
data.m_indirections = indirections;
data.m_autodelete = AutoDeleteMode.None;
data.m_isReadonly = isReadOnly;
}
@NativeAccess
private QNativePointer(int type, long size, int indirections, boolean isReadOnly) {
this(Type.resolve(type), size, indirections, isReadOnly);
}
@NativeAccess
private QNativePointer(Buffer buffer, long ptr, long bufferAccess) {
if(buffer.isDirect()) {
data = new Data();
}else {
data = new BufferData(bufferAccess, buffer);
}
QtJambi_LibraryUtilities.internal.registerCleaner(this, this.data::dispose);
data.m_ptr = ptr;
if(buffer instanceof ByteBuffer)
data.m_type = Type.Byte;
else if(buffer instanceof IntBuffer)
data.m_type = Type.Int;
else if(buffer instanceof ShortBuffer)
data.m_type = Type.Short;
else if(buffer instanceof LongBuffer)
data.m_type = Type.Long;
else if(buffer instanceof CharBuffer)
data.m_type = Type.Char;
else if(buffer instanceof FloatBuffer)
data.m_type = Type.Float;
else if(buffer instanceof DoubleBuffer)
data.m_type = Type.Double;
else
data.m_type = Type.Pointer;
data.m_knownSize = buffer.remaining();
data.m_indirections = 1;
data.m_isReadonly = buffer.isReadOnly();
if(buffer.isDirect()) {
QtJambi_LibraryUtilities.internal.registerCleaner(buffer, data::reset);
}
}
private QNativePointer() {
data = new Data();
QtJambi_LibraryUtilities.internal.registerCleaner(this, this.data::dispose);
data.m_knownSize = -1;
data.m_autodelete = AutoDeleteMode.None;
};
/**
* If the native pointer is of boolean type, this function returns
* its value. If it is an array of booleans, the first element is
* returned.
*
* @return the value of the pointer.
*/
public boolean booleanValue() {
return booleanAt(0);
}
/**
* If the native pointer is of byte type, this function returns
* its value. If it is an array of bytes, the first element is
* returned.
*
* @return the value of the pointer.
*/
public byte byteValue() {
return byteAt(0);
}
/**
* If the native pointer is of char type, this function returns
* its value. If it is an array of chars, the first element is
* returned.
*
* @return the value of the pointer.
*/
public char charValue() {
return charAt(0);
}
/**
* If the native pointer is of short type, this function returns
* its value. If it is an array of shorts, the first element is
* returned.
*
* @return the value of the pointer.
*/
public short shortValue() {
return shortAt(0);
}
/**
* If the native pointer is of int type, this function returns
* its value. If it is an array of ints, the first element is
* returned.
*
* @return the value of the pointer.
*/
public int intValue() {
return intAt(0);
}
/**
* If the native pointer is of long type, this function returns
* its value. If it is an array of longs, the first element is
* returned.
*
* @return the value of the pointer.
*/
public long longValue() {
return longAt(0);
}
/**
* If the native pointer is of float type, this function returns
* its value. If it is an array of floats, the first element is
* returned.
*
* @return the value of the pointer.
*/
public float floatValue() {
return floatAt(0);
}
/**
* If the native pointer is of double type, this function returns
* its value. If it is an array of doubles, the first element is
* returned.
*
* @return the value of the pointer.
*/
public double doubleValue() {
return doubleAt(0);
}
/**
* If the native pointer is of boolean type, this function returns
* its values as array.
*
* @return the values of the pointer.
*/
public boolean[] booleanArray() {
verifyAccess(Type.Boolean, 0);
if(this.data.m_knownSize>Integer.MAX_VALUE) {
throw new IndexOutOfBoundsException("The pointer's size exceeds allowed array size.");
}
boolean[] result = new boolean[(int)this.data.m_knownSize];
for (int i = 0; i < result.length; i++) {
result[i] = booleanAt(i);
}
return result;
}
/**
* If the native pointer is of byte type, this function returns
* its values as array.
*
* @return the values of the pointer.
*/
public byte[] byteArray() {
verifyAccess(Type.Byte, 0);
if(this.data.m_knownSize>Integer.MAX_VALUE) {
throw new IndexOutOfBoundsException("The pointer's size exceeds allowed array size.");
}
byte[] result = new byte[(int)this.data.m_knownSize];
copyBackB(data.m_ptr, result);
return result;
}
/**
* If the native pointer is of char type, this function returns
* its values as array.
*
* @return the values of the pointer.
*/
public char[] charArray() {
verifyAccess(Type.Char, 0);
if(this.data.m_knownSize>Integer.MAX_VALUE) {
throw new IndexOutOfBoundsException("The pointer's size exceeds allowed array size.");
}
char[] result = new char[(int)this.data.m_knownSize];
for (int i = 0; i < result.length; i++) {
result[i] = charAt(i);
}
return result;
}
/**
* If the native pointer is of short type, this function returns
* its values as array.
*
* @return the values of the pointer.
*/
public short[] shortArray() {
verifyAccess(Type.Short, 0);
if(this.data.m_knownSize>Integer.MAX_VALUE) {
throw new IndexOutOfBoundsException("The pointer's size exceeds allowed array size.");
}
short[] result = new short[(int)this.data.m_knownSize];
copyBackS(data.m_ptr, result);
return result;
}
/**
* If the native pointer is of int type, this function returns
* its values as array.
*
* @return the values of the pointer.
*/
public int[] intArray() {
verifyAccess(Type.Int, 0);
if(this.data.m_knownSize>Integer.MAX_VALUE) {
throw new IndexOutOfBoundsException("The pointer's size exceeds allowed array size.");
}
int[] result = new int[(int)this.data.m_knownSize];
copyBackI(data.m_ptr, result);
return result;
}
/**
* If the native pointer is of long type, this function returns
* its values as array.
*
* @return the values of the pointer.
*/
public long[] longArray() {
verifyAccess(Type.Long, 0);
if(this.data.m_knownSize>Integer.MAX_VALUE) {
throw new IndexOutOfBoundsException("The pointer's size exceeds allowed array size.");
}
long[] result = new long[(int)this.data.m_knownSize];
copyBackJ(data.m_ptr, result);
return result;
}
/**
* If the native pointer is of float type, this function returns
* its values as array.
*
* @return the values of the pointer.
*/
public float[] floatArray() {
verifyAccess(Type.Float, 0);
if(this.data.m_knownSize>Integer.MAX_VALUE) {
throw new IndexOutOfBoundsException("The pointer's size exceeds allowed array size.");
}
float[] result = new float[(int)this.data.m_knownSize];
copyBackF(data.m_ptr, result);
return result;
}
/**
* If the native pointer is of double type, this function returns
* its values as array.
*
* @return the values of the pointer.
*/
public double[] doubleArray() {
verifyAccess(Type.Double, 0);
if(this.data.m_knownSize>Integer.MAX_VALUE) {
throw new IndexOutOfBoundsException("The pointer's size exceeds allowed array size.");
}
double[] result = new double[(int)this.data.m_knownSize];
copyBackD(data.m_ptr, result);
return result;
}
/**
* If the native pointer is of pointer type, this function returns
* its value matching the given valueType.
* @param valueType the type of the value
*
* @return the value of the pointer.
*/
@SuppressWarnings("unchecked")
public T[] objectArray(Class valueType) {
if(data.m_knownSize>1) {
verifyAccess(Type.Byte, 0);
}else {
verifyAccess(Type.Pointer, 0);
}
if(this.data.m_knownSize>Integer.MAX_VALUE) {
throw new IndexOutOfBoundsException("The pointer's size exceeds allowed array size.");
}
Object[] array = (Object[])java.lang.reflect.Array.newInstance(valueType, (int)this.data.m_knownSize);
for (int i = 0; i < array.length; i++) {
array[i] = objectAt(valueType, i);
}
return (T[])array;
}
/**
* If the native pointer is of pointer type, this function returns
* its value. If it is an array of pointers, the first element is
* returned.
*
* @return the value of the pointer.
*/
public QNativePointer pointerValue() {
return pointerAt(0);
}
/**
* If the native pointer is of pointer type, this function returns
* its value matching the given valueType. If it is an array of pointers, the first element is
* returned.
* @param valueType the type of the value
*
* @return the value of the pointer.
*/
public T object(Class valueType) {
return objectAt(valueType, 0);
}
/**
* If the native pointer is of string type, this function returns
* its value. If it is an array of strings, the first element is
* returned.
*
* @return the value of the pointer.
*/
public @NonNull String stringValue() {
return stringAt(0);
}
/**
* If the native pointer is of string type, this function returns
* its values as array.
*
* @return the values of the pointer.
*/
public @NonNull String @NonNull[] stringArray() {
verifyAccess(Type.String, 0);
if(this.data.m_knownSize>Integer.MAX_VALUE) {
throw new IndexOutOfBoundsException("The pointer's size exceeds allowed array size.");
}
String[] result = new String[(int)this.data.m_knownSize];
for (int i = 0; i < result.length; i++) {
result[i] = stringAt(i);
}
return result;
}
/**
* Sets the value of this pointer to value
.
* The type of the pointer must be boolean.
*
* @param value the value to which the pointer is set.
*/
public void setBooleanValue(boolean value) {
setBooleanAt(0, value);
}
/**
* Sets the value of this pointer to value
.
* The type of the pointer must be byte.
*
* @param value the value to which the pointer is set.
*/
public void setByteValue(byte value) {
setByteAt(0, value);
}
/**
* Sets the value of this pointer to value
.
* The type of the pointer must be char.
*
* @param value the value to which the pointer is set.
*/
public void setCharValue(char value) {
setCharAt(0, value);
}
/**
* Sets the value of this pointer to value
.
* The type of the pointer must be short.
*
* @param value the value to which the pointer is set.
*/
public void setShortValue(short value) {
setShortAt(0, value);
}
/**
* Sets the value of this pointer to value
.
* The type of the pointer must be int.
*
* @param value the value to which the pointer is set.
*/
public void setIntValue(int value) {
setIntAt(0, value);
}
/**
* Sets the value of this pointer to value
.
* The type of the pointer must be long.
*
* @param value the value to which the pointer is set.
*/
public void setLongValue(long value) {
setLongAt(0, value);
}
/**
* Sets the value of this pointer to value
.
* The type of the pointer must be float.
*
* @param value the value to which the pointer is set.
*/
public void setFloatValue(float value) {
setFloatAt(0, value);
}
/**
* Sets the value of this pointer to value
.
* The type of the pointer must double.
*
* @param value the value to which the pointer is set.
*/
public void setDoubleValue(double value) {
setDoubleAt(0, value);
}
/**
* Sets the value of this pointer to value
.
* The pointer must be of pointer type.
*
* @param value the value to which the pointer is set.
*/
public void setPointerValue(@NonNull QNativePointer value) {
setPointerAt(0, value);
}
/**
* Sets the value of this pointer to value
.
* The pointer must be of pointer type.
*
* @param value the value to which the pointer is set.
*/
public void setObjectValue(T value) {
setObjectAt(0, value);
}
/**
* Sets the value of this pointer to value
.
* The pointer must point to a string.
*
* @param value the value to which the pointer is set.
*/
public void setStringValue(@NonNull String value) {
setStringAt(0, value);
}
/**
* Returns the value of the native pointer at the specified
* position. If pos
is larger than 1, QNativePointer
* will check that the position is within the array bounds.
*
* @param pos the array index
*/
public boolean booleanAt(long pos) {
verifyAccess(Type.Boolean, pos);
return readBoolean(data.m_ptr, pos);
}
/**
* Returns the value of the native pointer at the specified
* position. If pos
is larger than 1, QNativePointer
* will check that the position is within the array bounds.
*
* @param pos the array index
*/
public byte byteAt(long pos) {
verifyAccess(Type.Byte, pos);
return readByte(data.m_ptr, pos);
}
/**
* Returns the value of the native pointer at the specified
* position. If pos
is larger than 1, QNativePointer
* will check that the position is within the array bounds.
*
* @param pos the array index
*/
public char charAt(long pos) {
verifyAccess(Type.Char, pos);
return readChar(data.m_ptr, pos);
}
/**
* Returns the value of the native pointer at the specified
* position. If pos
is larger than 1, QNativePointer
* will check that the position is within the array bounds.
*
* @param pos the array index
*/
public short shortAt(long pos) {
verifyAccess(Type.Short, pos);
return readShort(data.m_ptr, pos);
}
/**
* Returns the value of the native pointer at the specified
* position. If pos
is larger than 1, QNativePointer
* will check that the position is within the array bounds.
*
* @param pos the array index
*/
public int intAt(long pos) {
verifyAccess(Type.Int, pos);
return readInt(data.m_ptr, pos);
}
/**
* Returns the value of the native pointer at the specified
* position. If pos
is larger than 1, QNativePointer
* will check that the position is within the array bounds.
*
* @param pos the array index
*/
public long longAt(long pos) {
verifyAccess(Type.Long, pos);
return readLong(data.m_ptr, pos);
}
/**
* Returns the value of the native pointer at the specified
* position. If pos
is larger than 1, QNativePointer
* will check that the position is within the array bounds.
*
* @param pos the array index
*/
public float floatAt(long pos) {
verifyAccess(Type.Float, pos);
return readFloat(data.m_ptr, pos);
}
/**
* Returns the value of the native pointer at the specified
* position. If pos
is larger than 1, QNativePointer
* will check that the position is within the array bounds.
*
* @param pos the array index
*/
public double doubleAt(long pos) {
verifyAccess(Type.Double, pos);
return readDouble(data.m_ptr, pos);
}
public @NonNull ByteBuffer byteBuffer() {
verifyAccess(Type.Byte, 0);
return toByteBuffer(data.m_ptr, data.m_knownSize, data.m_isReadonly);
}
public @NonNull CharBuffer charBuffer() {
verifyAccess(Type.Char, 0);
return toByteBuffer(data.m_ptr, data.m_knownSize, data.m_isReadonly).asCharBuffer();
}
public @NonNull ShortBuffer shortBuffer() {
verifyAccess(Type.Short, 0);
return toByteBuffer(data.m_ptr, data.m_knownSize, data.m_isReadonly).asShortBuffer();
}
public @NonNull IntBuffer intBuffer() {
verifyAccess(Type.Int, 0);
return toByteBuffer(data.m_ptr, data.m_knownSize, data.m_isReadonly).asIntBuffer();
}
public @NonNull LongBuffer longBuffer() {
verifyAccess(Type.Long, 0);
return toByteBuffer(data.m_ptr, data.m_knownSize, data.m_isReadonly).asLongBuffer();
}
public @NonNull FloatBuffer floatBuffer() {
verifyAccess(Type.Float, 0);
return toByteBuffer(data.m_ptr, data.m_knownSize, data.m_isReadonly).asFloatBuffer();
}
public @NonNull DoubleBuffer doubleBuffer() {
verifyAccess(Type.Double, 0);
return toByteBuffer(data.m_ptr, data.m_knownSize, data.m_isReadonly).asDoubleBuffer();
}
/**
* Returns the value of the native pointer at the specified
* position. If pos
is larger than 1, QNativePointer
* will check that the position is within the array bounds.
*
* @param pos the array index
*/
public @NonNull QNativePointer pointerAt(long pos) {
verifyAccess(Type.Pointer, pos);
long ptr = readPointer(data.m_ptr, pos);
return fromNative(ptr, data.m_type, -1, data.m_indirections - 1, data.m_isReadonly);
}
/**
* Returns the value of the native pointer matching the given valueType at the specified
* position. If pos
is larger than 1, QNativePointer
* will check that the position is within the array bounds.
* @param valueType the type of the value
* @param pos the array index
*
* @return the value of the pointer.
*/
public T objectAt(@NonNull Class valueType, long pos) {
if(data.m_knownSize>1 && pos>0) {
verifyAccess(Type.Byte, pos);
}else {
verifyAccess(Type.Pointer, pos);
}
T object = readObject(data.m_ptr, valueType, pos, data.m_isReadonly, data.m_type.value(), data.m_knownSize);
if(data.m_autodelete!=AutoDeleteMode.None) {
if(data.m_dependentObjects==null) {
data.m_dependentObjects = new ArrayList<>();
}
data.m_dependentObjects.add(new WeakReference(object));
}
return object;
}
/**
* Returns the value of the native pointer at the specified
* position. If pos
is larger than 1, QNativePointer
* will check that the position is within the array bounds.
*
* @param pos the array index
*/
public String stringAt(long pos) {
verifyAccess(Type.String, pos);
return readString(data.m_ptr, pos);
}
/**
* Sets the value of the array element at pos
to
* which this native pointer points.
*
* @param pos the array index
* @param value the value to set the index to
*/
public void setBooleanAt(long pos, boolean value) {
verifyWriteAccess(Type.Boolean, pos);
writeBoolean(data.m_ptr, pos, value);
}
/**
* Sets the value of the array element at pos
to
* which this native pointer points.
*
* @param pos the array index
* @param value the value to set the index to
*/
public void setByteAt(long pos, byte value) {
verifyWriteAccess(Type.Byte, pos);
writeByte(data.m_ptr, pos, value);
}
/**
* Sets the value of the array element at pos
to
* which this native pointer points.
*
* @param pos the array index
* @param value the value to set the index to
*/
public void setCharAt(long pos, char value) {
verifyWriteAccess(Type.Char, pos);
writeChar(data.m_ptr, pos, value);
}
/**
* Sets the value of the array element at pos
to
* which this native pointer points.
*
* @param pos the array index
* @param value the value to set the index to
*/
public void setShortAt(long pos, short value) {
verifyWriteAccess(Type.Short, pos);
writeShort(data.m_ptr, pos, value);
}
/**
* Sets the value of the array element at pos
to
* which this native pointer points.
*
* @param pos the array index
* @param value the value to set the index to
*/
public void setIntAt(long pos, int value) {
verifyWriteAccess(Type.Int, pos);
writeInt(data.m_ptr, pos, value);
}
/**
* Sets the value of the array element at pos
to
* which this native pointer points.
*
* @param pos the array index
* @param value the value to set the index to
*/
public void setLongAt(long pos, long value) {
verifyWriteAccess(Type.Long, pos);
writeLong(data.m_ptr, pos, value);
}
/**
* Sets the value of the array element at pos
to
* which this native pointer points.
*
* @param pos the array index
* @param value the value to set the index to
*/
public void setFloatAt(long pos, float value) {
verifyWriteAccess(Type.Float, pos);
writeFloat(data.m_ptr, pos, value);
}
/**
* Sets the value of the array element at pos
to
* which this native pointer points.
*
* @param pos the array index
* @param value the value to set the index to
*/
public void setDoubleAt(long pos, double value) {
verifyWriteAccess(Type.Double, pos);
writeDouble(data.m_ptr, pos, value);
}
/**
* Sets the value of the array element at pos
to
* which this native pointer points.
*
* @param pos the array index
* @param value the value to set the index to
*/
public void setPointerAt(long pos, @Nullable QNativePointer value) {
verifyWriteAccess(Type.Pointer, pos);
if(value != null)
value.setAutoDeleteMode(AutoDeleteMode.None);
writePointer(data.m_ptr, pos, value == null ? 0 : value.data.m_ptr);
}
/**
* Sets the value of the array element at pos
to
* which this native pointer points.
*
* @param pos the array index
* @param value the value to set the index to
*/
public void setObjectAt(long pos, T value) {
if(data.m_knownSize>1 && pos>0) {
verifyWriteAccess(Type.Byte, pos);
}else {
verifyWriteAccess(Type.Pointer, pos);
}
Class> valueType = QtJambi_LibraryUtilities.internal.getClass(value);
writeObject(data.m_ptr, data.m_knownSize, valueType, pos, value);
}
/**
* Sets the value of the array element at pos
to
* which this native pointer points.
*
* @param pos the array index
* @param value the value to set the index to
*/
public void setStringAt(long pos, @NonNull String value) {
verifyWriteAccess(Type.String, pos);
writeString(data.m_ptr, pos, value);
}
/**
* Returns the type of the native pointer.
*
* @return the data type of the native pointer
*/
public Type type() {
return data.m_type;
}
/**
* Returns the number of indirections of the pointer.
*
* @return the number of indirections of the pointer
*/
public int indirections() {
return data.m_indirections;
}
public long knownSize() {
return data.m_knownSize;
}
private native long pointerSize();
@NativeAccess
private long byteSize() {
if(data.m_type==Type.Pointer) {
if(data.m_knownSize<=0) {
return pointerSize();
}else {
return data.m_knownSize;
}
}
if(data.m_knownSize>0 && data.m_indirections==1) {
switch(data.m_type) {
case Boolean:
case Byte:
return data.m_knownSize;
case Short:
case Char:
return data.m_knownSize * 2;
case Float:
case Int:
return data.m_knownSize * 4;
case Double:
case Long:
case Pointer:
return data.m_knownSize * pointerSize();
case String:
return -1;
default:
break;
}
}
return -1;
}
/**
* Returns true if the native pointer is 0; otherwise false.
*
* @return true if the native pointer is 0.
*/
public boolean isNull() {
return data.isNull();
}
/**
* Returns the auto-delete mode of the pointer.
*
* @return the auto-delete mode of this QNativePointer
*/
public @NonNull AutoDeleteMode autoDeleteMode() {
return data.m_autodelete;
}
/**
* This function sets the auto delete mode of the QNativePointer.
*
* The internal pointer is deleted by default when the
* QNativePointer object is garbage collected, so you only need to
* call this function when you want to keep the pointer valid
* after the Java object is garbage collected.
*
* @param autodelete the new auto delete mode.
*/
public void setAutoDeleteMode(@NonNull AutoDeleteMode autodelete) {
data.m_autodelete = autodelete==null ? AutoDeleteMode.None : autodelete;
}
/**
* This function deletes the internal pointer.
*
* Currently, all QNativePointers should be deleted using the
* delete() function.
* After the pointer has been deleted, you cannot use the same
* QNativePointer to allocate further data. Note also that the
* pointer will by default be deleted upon garbage collection.
*/
public void free() {
data.free();
}
/**
* This function deletes the internal pointer.
*
* After the pointer has been deleted, you cannot allocate it
* again. The pointer is by default deleted when the
* QNativePointer object is garbage collected.
*/
public void delete() {
data.delete();
}
/**
* This function deletes elements in the array of this
* QNativePointer.
*
* After the pointer has been deleted, you cannot use this
* QNativePointer object again.
*/
public void deleteArray() {
data.deleteArray();
}
/**
* Returns the native pointer.
*
* The returned long is the void *
value in c++.
*
* @return the native pointer.
*/
public long pointer() {
return data.m_ptr;
}
/**
* This function creates a QNativePointer from an existing c++
* pointer of unknown type. The long is the void *
(i.e., address)
* value of the pointer.
*
* @param ptr the void * value of the pointer.
* @return a QNativePointer object with ptr as the native pointer
*/
public static @NonNull QNativePointer fromNative(long ptr) {
QNativePointer nativePointer = new QNativePointer();
nativePointer.data.m_ptr = ptr;
nativePointer.data.m_knownSize = -1;
nativePointer.data.m_type = Type.Pointer;
nativePointer.data.m_indirections = 1;
nativePointer.data.m_isReadonly = true;
return nativePointer;
}
/**
* This function creates a QNativePointer from an existing c++
* pointer. The long is the void *
(i.e., address)
* value of the pointer. There are several ways of acquiring a native pointer. For instance,
* QNativePointer internal pointer is returned by pointer(), and
* QtJambiObject.nativeId() returns the c++ pointer to its Qt object.
*
* @param ptr the void * value of the pointer.
* @param type the Type of the pointer
* @param indirections the number of pointer indirections
* @return a QNativePointer object with ptr as the native pointer
*/
public static @NonNull QNativePointer fromNative(long ptr, Type type, long size, int indirections, boolean readOnly) {
QNativePointer nativePointer = new QNativePointer();
nativePointer.data.m_ptr = ptr;
nativePointer.data.m_knownSize = size;
nativePointer.data.m_type = type;
nativePointer.data.m_indirections = indirections;
nativePointer.data.m_isReadonly = readOnly;
return nativePointer;
}
@SafeVarargs
public static @Nullable QNativePointer fromArray(T... array) {
Class> arrayClass = QtJambi_LibraryUtilities.internal.getClass(array);
Class> componentType = arrayClass.getComponentType();
return fromArray(componentType, array);
}
private static native QNativePointer fromArray(Class> valueType, T[] array);
public static native QNativePointer fromObject(T object);
public static native QNativePointer fromBuffer(Buffer buffer);
public static @NonNull QNativePointer fromArray(int data[]) {
QNativePointer np = new QNativePointer(QNativePointer.Type.Int, data.length);
copyFromI(np.data.m_ptr, data);
return np;
}
public static @NonNull QNativePointer fromArray(byte data[]) {
QNativePointer np = new QNativePointer(QNativePointer.Type.Byte, data.length);
copyFromB(np.data.m_ptr, data);
return np;
}
public static @NonNull QNativePointer fromArray(float data[]) {
QNativePointer np = new QNativePointer(QNativePointer.Type.Float, data.length);
copyFromF(np.data.m_ptr, data);
return np;
}
public static @NonNull QNativePointer fromArray(double data[]) {
QNativePointer np = new QNativePointer(QNativePointer.Type.Double, data.length);
copyFromD(np.data.m_ptr, data);
return np;
}
public static @NonNull QNativePointer fromArray(boolean data[]) {
QNativePointer np = new QNativePointer(QNativePointer.Type.Boolean, data.length);
for (int i=0; i= 0 && pos >= data.m_knownSize)
throw new IndexOutOfBoundsException("size: " + data.m_knownSize + ", access at: " + pos);
if (data.m_indirections > 1) {
if (type != Type.Pointer)
throw new ClassCastException("accessing pointer with " + data.m_indirections
+ " levels of indirection as " + type);
} else if (type != data.m_type) {
throw new ClassCastException("type: " + data.m_type + ", accessed as: " + type);
}
}
public @Nullable QIODevice openAsDevice(QIODevice.@NonNull OpenModeFlag @NonNull... openMode) {
return openAsDevice(new QIODevice.OpenMode(openMode));
}
public @Nullable QIODevice openAsDevice(QIODevice.@NonNull OpenMode openMode) {
if(data.m_isInvalid)
throw new IllegalStateException();
if (isNull())
throw new NullPointerException("native pointer is null");
if(openMode.testFlag(QIODevice.OpenModeFlag.WriteOnly)) {
if(data.m_isReadonly){
throw new ReadOnlyNativePointerException();
}
}
QIODevice ioDevice = ioDevice(data.m_indirections, byteSize(), data.m_ptr, data.m_isReadonly);
if(ioDevice.open(openMode)) {
return ioDevice;
}else {
return null;
}
}
private native QIODevice ioDevice(int indirections, long byteSize, long pointer, boolean readOnly);
private static native boolean readBoolean(long ptr, long pos);
private static native byte readByte(long ptr, long pos);
private static native char readChar(long ptr, long pos);
private static native short readShort(long ptr, long pos);
private static native int readInt(long ptr, long pos);
private static native long readLong(long ptr, long pos);
private static native float readFloat(long ptr, long pos);
private static native double readDouble(long ptr, long pos);
private static native ByteBuffer toByteBuffer(long ptr, long capacity, boolean readOnly);
private static native long readPointer(long ptr, long pos);
private static native T readObject(long ptr, Class valueType, long pos, boolean readOnly, int type, long size);
private static native String readString(long ptr, long pos);
private static native void writeBoolean(long ptr, long pos, boolean value);
private static native void writeByte(long ptr, long pos, byte value);
private static native void writeChar(long ptr, long pos, char value);
private static native void writeShort(long ptr, long pos, short value);
private static native void writeInt(long ptr, long pos, int value);
private static native void writeLong(long ptr, long pos, long value);
private static native void writeFloat(long ptr, long pos, float value);
private static native void writeDouble(long ptr, long pos, double value);
private static native void writePointer(long ptr, long pos, long value);
private static native void writeObject(long ptr, long knownSize, Class> valueType, long pos, QtObjectInterface value);
private static native void writeString(long ptr, long pos, String value);
private static native long createPointer(int type, long size, int indirections);
private static native void deletePointer(long ptr, int type, int deleteMode);
private static native void deleteBufferAccess(long ptr, boolean readOnly);
private final Data data;
public final void invalidate() {
data.dispose();
}
private static class Data{
long m_ptr = 0;
private Type m_type = Type.Pointer;
private long m_knownSize = 0;
AutoDeleteMode m_autodelete = AutoDeleteMode.None;
private int m_indirections = 0;
private boolean m_isReadonly = true;
boolean m_isInvalid = false;
private boolean m_verification_enabled = true;
private List> m_dependentObjects;
void invalidateDependentObjects() {
if(m_dependentObjects!=null) {
for(WeakReference extends QtObjectInterface> object : m_dependentObjects) {
QtJambi_LibraryUtilities.internal.invalidateObject(object.get());
}
m_dependentObjects = null;
}
}
void dispose() {
invalidateDependentObjects();
switch (m_autodelete) {
case Free:
free();
break;
case Delete:
delete();
break;
case DeleteArray:
deleteArray();
break;
case None:
break;
default:
break;
}
m_ptr = 0;
m_autodelete = AutoDeleteMode.None;
m_isInvalid = true;
}
private void free() {
if (isNull())
return;
deletePointer(m_ptr, m_type.ordinal(), 0);
m_ptr = 0;
}
private void delete() {
if (isNull())
return;
deletePointer(m_ptr, m_type.ordinal(), 1);
m_ptr = 0;
}
private void deleteArray() {
if (isNull())
return;
deletePointer(m_ptr, m_type.ordinal(), 2);
m_ptr = 0;
}
boolean isNull() {
return m_ptr == 0;
}
void reset() {
m_ptr = 0;
}
}
private static class BufferData extends Data{
private final long m_bufferAccess;
private final Buffer buffer;
BufferData(long m_bufferAccess, Buffer buffer) {
this.m_bufferAccess = m_bufferAccess;
this.buffer = buffer;
m_autodelete = AutoDeleteMode.Delete;
}
void dispose() {
if (isNull())
return;
invalidateDependentObjects();
deleteBufferAccess(m_bufferAccess, buffer.isReadOnly());
m_ptr = 0;
m_autodelete = AutoDeleteMode.None;
m_isInvalid = true;
}
}
/**
* This exception is thrown when trying to write on a read-only native pointer.
*/
public static class ReadOnlyNativePointerException extends UnsupportedOperationException{
private static final long serialVersionUID = -8238568644716457250L;
}
}