001 package org.bridj;
002 import org.bridj.util.*;
003 import java.lang.reflect.ParameterizedType;
004 import java.lang.reflect.Type;
005 import java.lang.reflect.Array;
006 import java.lang.reflect.Method;
007 import java.nio.*;
008 import java.lang.annotation.Annotation;
009 import java.util.*;
010 import java.io.UnsupportedEncodingException;
011 import java.nio.charset.Charset;
012 import static org.bridj.SizeT.safeIntCast;
013
014 /**
015 * Pointer to a native memory location.<br>
016 * Pointer is the entry point of any pointer-related operation in BridJ.
017 * <p>
018 * <u><b>Manipulating memory</b></u>
019 * <p>
020 * <ul>
021 * <li>Wrapping a memory address as a pointer : {@link Pointer#pointerToAddress(long)}
022 * </li>
023 * <li>Reading / writing a primitive from / to the pointed memory location :<br>
024 * {@link Pointer#getInt()} / {@link Pointer#setInt(int)} <br>
025 * {@link Pointer#getLong()} / {@link Pointer#setLong(long)} <br>
026 * {@link Pointer#getShort()} / {@link Pointer#setShort(short)} <br>
027 * {@link Pointer#getByte()} / {@link Pointer#setByte(byte)} <br>
028 * {@link Pointer#getChar()} / {@link Pointer#setChar(char)} <br>
029 * {@link Pointer#getFloat()} / {@link Pointer#setFloat(float)} <br>
030 * {@link Pointer#getDouble()} / {@link Pointer#setDouble(double)} <br>
031 * {@link Pointer#getBoolean()} / {@link Pointer#setBoolean(boolean)} <br>
032 * {@link Pointer#getSizeT()} / {@link Pointer#setSizeT(long)} <br>
033 * {@link Pointer#getCLong()} / {@link Pointer#setCLong(long)} <br>
034 *</li>
035 * <li>Reading / writing the nth contiguous primitive value from / to the pointed memory location :<br>
036 * {@link Pointer#getIntAtIndex(long)} / {@link Pointer#setIntAtIndex(long, int)} <br>
037 * {@link Pointer#getLongAtIndex(long)} / {@link Pointer#setLongAtIndex(long, long)} <br>
038 * {@link Pointer#getShortAtIndex(long)} / {@link Pointer#setShortAtIndex(long, short)} <br>
039 * {@link Pointer#getByteAtIndex(long)} / {@link Pointer#setByteAtIndex(long, byte)} <br>
040 * {@link Pointer#getCharAtIndex(long)} / {@link Pointer#setCharAtIndex(long, char)} <br>
041 * {@link Pointer#getFloatAtIndex(long)} / {@link Pointer#setFloatAtIndex(long, float)} <br>
042 * {@link Pointer#getDoubleAtIndex(long)} / {@link Pointer#setDoubleAtIndex(long, double)} <br>
043 * {@link Pointer#getBooleanAtIndex(long)} / {@link Pointer#setBooleanAtIndex(long, boolean)} <br>
044 * {@link Pointer#getSizeTAtIndex(long)} / {@link Pointer#setSizeTAtIndex(long, long)} <br>
045 * {@link Pointer#getCLongAtIndex(long)} / {@link Pointer#setCLongAtIndex(long, long)} <br>
046 *</li>
047 * <li>Reading / writing a primitive from / to the pointed memory location with a byte offset:<br>
048 * {@link Pointer#getIntAtOffset(long)} / {@link Pointer#setIntAtOffset(long, int)} <br>
049 * {@link Pointer#getLongAtOffset(long)} / {@link Pointer#setLongAtOffset(long, long)} <br>
050 * {@link Pointer#getShortAtOffset(long)} / {@link Pointer#setShortAtOffset(long, short)} <br>
051 * {@link Pointer#getByteAtOffset(long)} / {@link Pointer#setByteAtOffset(long, byte)} <br>
052 * {@link Pointer#getCharAtOffset(long)} / {@link Pointer#setCharAtOffset(long, char)} <br>
053 * {@link Pointer#getFloatAtOffset(long)} / {@link Pointer#setFloatAtOffset(long, float)} <br>
054 * {@link Pointer#getDoubleAtOffset(long)} / {@link Pointer#setDoubleAtOffset(long, double)} <br>
055 * {@link Pointer#getBooleanAtOffset(long)} / {@link Pointer#setBooleanAtOffset(long, boolean)} <br>
056 * {@link Pointer#getSizeTAtOffset(long)} / {@link Pointer#setSizeTAtOffset(long, long)} <br>
057 * {@link Pointer#getCLongAtOffset(long)} / {@link Pointer#setCLongAtOffset(long, long)} <br>
058 *</li>
059 * <li>Reading / writing an array of primitives from / to the pointed memory location :<br>
060 * {@link Pointer#getInts(int)} / {@link Pointer#setInts(int[])} ; With an offset : {@link Pointer#getIntsAtOffset(long, int)} / {@link Pointer#setIntsAtOffset(long, int[])}<br>
061 * {@link Pointer#getLongs(int)} / {@link Pointer#setLongs(long[])} ; With an offset : {@link Pointer#getLongsAtOffset(long, int)} / {@link Pointer#setLongsAtOffset(long, long[])}<br>
062 * {@link Pointer#getShorts(int)} / {@link Pointer#setShorts(short[])} ; With an offset : {@link Pointer#getShortsAtOffset(long, int)} / {@link Pointer#setShortsAtOffset(long, short[])}<br>
063 * {@link Pointer#getBytes(int)} / {@link Pointer#setBytes(byte[])} ; With an offset : {@link Pointer#getBytesAtOffset(long, int)} / {@link Pointer#setBytesAtOffset(long, byte[])}<br>
064 * {@link Pointer#getChars(int)} / {@link Pointer#setChars(char[])} ; With an offset : {@link Pointer#getCharsAtOffset(long, int)} / {@link Pointer#setCharsAtOffset(long, char[])}<br>
065 * {@link Pointer#getFloats(int)} / {@link Pointer#setFloats(float[])} ; With an offset : {@link Pointer#getFloatsAtOffset(long, int)} / {@link Pointer#setFloatsAtOffset(long, float[])}<br>
066 * {@link Pointer#getDoubles(int)} / {@link Pointer#setDoubles(double[])} ; With an offset : {@link Pointer#getDoublesAtOffset(long, int)} / {@link Pointer#setDoublesAtOffset(long, double[])}<br>
067 * {@link Pointer#getBooleans(int)} / {@link Pointer#setBooleans(boolean[])} ; With an offset : {@link Pointer#getBooleansAtOffset(long, int)} / {@link Pointer#setBooleansAtOffset(long, boolean[])}<br>
068 * {@link Pointer#getSizeTs(int)} / {@link Pointer#setSizeTs(long[])} ; With an offset : {@link Pointer#getSizeTsAtOffset(long, int)} / {@link Pointer#setSizeTsAtOffset(long, long[])}<br>
069 * {@link Pointer#getCLongs(int)} / {@link Pointer#setCLongs(long[])} ; With an offset : {@link Pointer#getCLongsAtOffset(long, int)} / {@link Pointer#setCLongsAtOffset(long, long[])}<br>
070 * </li>
071 * <li>Reading / writing an NIO buffer of primitives from / to the pointed memory location :<br>
072 * {@link Pointer#getIntBuffer(long)} (can be used for writing as well) / {@link Pointer#setInts(IntBuffer)}<br>
073 * {@link Pointer#getLongBuffer(long)} (can be used for writing as well) / {@link Pointer#setLongs(LongBuffer)}<br>
074 * {@link Pointer#getShortBuffer(long)} (can be used for writing as well) / {@link Pointer#setShorts(ShortBuffer)}<br>
075 * {@link Pointer#getByteBuffer(long)} (can be used for writing as well) / {@link Pointer#setBytes(ByteBuffer)}<br>
076 * {@link Pointer#getFloatBuffer(long)} (can be used for writing as well) / {@link Pointer#setFloats(FloatBuffer)}<br>
077 * {@link Pointer#getDoubleBuffer(long)} (can be used for writing as well) / {@link Pointer#setDoubles(DoubleBuffer)}<br>
078 * </li>
079 * <li>Reading / writing a String from / to the pointed memory location using the default charset :<br>
080 * {@link Pointer#getCString()} / {@link Pointer#setCString(String)} ; With an offset : {@link Pointer#getCStringAtOffset(long)} / {@link Pointer#setCStringAtOffset(long, String)}<br>
081 * {@link Pointer#getWideCString()} / {@link Pointer#setWideCString(String)} ; With an offset : {@link Pointer#getWideCStringAtOffset(long)} / {@link Pointer#setWideCStringAtOffset(long, String)}<br>
082 * </li>
083 * <li>Reading / writing a String with control on the charset :<br>
084 * {@link Pointer#getStringAtOffset(long, StringType, Charset)} / {@link Pointer#setStringAtOffset(long, String, StringType, Charset)}<br>
085 * </ul>
086 * <p>
087 * <u><b>Allocating memory</b></u>
088 * <p>
089 * <ul>
090 * <li>Getting the pointer to a struct / a C++ class / a COM object :
091 * {@link Pointer#pointerTo(NativeObject)}
092 * </li>
093 * <li>Allocating a dynamic callback (without a static {@link Callback} definition, which would be the preferred way) :<br>
094 * {@link Pointer#allocateDynamicCallback(DynamicCallback, org.bridj.ann.Convention.Style, Type, Type[])}
095 * </li>
096 * <li>Allocating a primitive with / without an initial value (zero-initialized) :<br>
097 * {@link Pointer#pointerToInt(int)} / {@link Pointer#allocateInt()}<br>
098 * {@link Pointer#pointerToLong(long)} / {@link Pointer#allocateLong()}<br>
099 * {@link Pointer#pointerToShort(short)} / {@link Pointer#allocateShort()}<br>
100 * {@link Pointer#pointerToByte(byte)} / {@link Pointer#allocateByte()}<br>
101 * {@link Pointer#pointerToChar(char)} / {@link Pointer#allocateChar()}<br>
102 * {@link Pointer#pointerToFloat(float)} / {@link Pointer#allocateFloat()}<br>
103 * {@link Pointer#pointerToDouble(double)} / {@link Pointer#allocateDouble()}<br>
104 * {@link Pointer#pointerToBoolean(boolean)} / {@link Pointer#allocateBoolean()}<br>
105 * {@link Pointer#pointerToSizeT(long)} / {@link Pointer#allocateSizeT()}<br>
106 * {@link Pointer#pointerToCLong(long)} / {@link Pointer#allocateCLong()}<br>
107 * </li>
108 * <li>Allocating an array of primitives with / without initial values (zero-initialized) :<br>
109 * {@link Pointer#pointerToInts(int[])} or {@link Pointer#pointerToInts(IntBuffer)} / {@link Pointer#allocateInts(long)}<br>
110 * {@link Pointer#pointerToLongs(long[])} or {@link Pointer#pointerToLongs(LongBuffer)} / {@link Pointer#allocateLongs(long)}<br>
111 * {@link Pointer#pointerToShorts(short[])} or {@link Pointer#pointerToShorts(ShortBuffer)} / {@link Pointer#allocateShorts(long)}<br>
112 * {@link Pointer#pointerToBytes(byte[])} or {@link Pointer#pointerToBytes(ByteBuffer)} / {@link Pointer#allocateBytes(long)}<br>
113 * {@link Pointer#pointerToChars(char[])} or {@link Pointer#pointerToChars(CharBuffer)} / {@link Pointer#allocateChars(long)}<br>
114 * {@link Pointer#pointerToFloats(float[])} or {@link Pointer#pointerToFloats(FloatBuffer)} / {@link Pointer#allocateFloats(long)}<br>
115 * {@link Pointer#pointerToDoubles(double[])} or {@link Pointer#pointerToDoubles(DoubleBuffer)} / {@link Pointer#allocateDoubles(long)}<br>
116 * {@link Pointer#pointerToSizeTs(long[])} / {@link Pointer#allocateSizeTs(long)}<br>
117 * {@link Pointer#pointerToCLongs(long[])} / {@link Pointer#allocateCLongs(long)}<br>
118 * {@link Pointer#pointerToBuffer(Buffer)} / n/a<br>
119 * </li>
120 * <li>Allocating a native String :<br>
121 * {@link Pointer#pointerToCString(String) } (default charset)<br>
122 * {@link Pointer#pointerToWideCString(String) } (default charset)<br>
123 * {@link Pointer#pointerToString(String, StringType, Charset) }<br>
124 * </li>
125 * <li>Allocating a {@link ListType#Dynamic} Java {@link java.util.List} that uses native memory storage (think of getting back the pointer with {@link NativeList#getPointer()} when you're done mutating the list):<br>
126 * {@link Pointer#allocateList(Class, long) }
127 * </li>
128 * <li>Transforming a pointer to a Java {@link java.util.List} that uses the pointer as storage (think of getting back the pointer with {@link NativeList#getPointer()} when you're done mutating the list, if it's {@link ListType#Dynamic}) :<br>
129 * {@link Pointer#asList(ListType) }<br>
130 * {@link Pointer#asList() }<br>
131 * </li>
132 * </ul>
133 * <p>
134 * <u><b>Casting pointers</b></u>
135 * <p>
136 * <ul>
137 * <li>Cast a pointer to a {@link DynamicFunction} :<br>
138 * {@link Pointer#asDynamicFunction(org.bridj.ann.Convention.Style, java.lang.reflect.Type, java.lang.reflect.Type[]) }
139 * </li>
140 * <li>Cast a pointer to a {@link StructObject} or a {@link Callback} (as the ones generated by <a href="http://code.google.com/p/jnaerator/">JNAerator</a>) <br>:
141 * {@link Pointer#as(Class) }
142 * </li>
143 * <li>Cast a pointer to a complex type pointer (use {@link org.bridj.cpp.CPPType#getCPPType(Object[])} to create a C++ template type, for instance) :<br>
144 * {@link Pointer#as(Type) }
145 * </li>
146 * <li>Get an untyped pointer :<br>
147 * {@link Pointer#asUntyped() }
148 * </li>
149 * </ul>
150 * <p>
151 * <u><b>Dealing with pointer bounds</b></u>
152 * <p>
153 * <ul>
154 * <li>Pointers to memory allocated through Pointer.pointerTo*, Pointer.allocate* have validity bounds that help prevent buffer overflows, at least when the Pointer API is used
155 * </li>
156 * <li>{@link Pointer#offset(long)}, {@link Pointer#next(long)} and other similar methods retain pointer bounds
157 * </li>
158 * <li>{@link Pointer#getValidBytes()} and {@link Pointer#getValidElements()} return the amount of valid memory readable from the pointer
159 * </li>
160 * <li>Bounds can be declared manually with {@link Pointer#validBytes(long)} (useful for memory allocated by native code)
161 * </li>
162 * </ul>
163 */
164 public abstract class Pointer<T> implements Comparable<Pointer<?>>, Iterable<T>
165 {
166
167
168
169
170
171 /** The NULL pointer is <b>always</b> Java's null value */
172 public static final Pointer NULL = null;
173
174 /**
175 * Size of a pointer in bytes. <br>
176 * This is 4 bytes in a 32 bits environment and 8 bytes in a 64 bits environment.<br>
177 * Note that some 64 bits environments allow for 32 bits JVM execution (using the -d32 command line argument for Sun's JVM, for instance). In that case, Java programs will believe they're executed in a 32 bits environment.
178 */
179 public static final int SIZE = Platform.POINTER_SIZE;
180
181 static {
182 Platform.initLibrary();
183 }
184
185
186 protected static long UNKNOWN_VALIDITY = -1;
187 protected static long NO_PARENT = 0/*-1*/;
188
189 /**
190 * Default alignment used to allocate memory from the static factory methods in Pointer class (any value lower or equal to 1 means no alignment)
191 */
192 public static final int defaultAlignment = Integer.parseInt(Platform.getenvOrProperty("BRIDJ_DEFAULT_ALIGNMENT", "bridj.defaultAlignment", "-1"));
193
194 protected final PointerIO<T> io;
195 protected final long peer, offsetInParent;
196 protected final Pointer<?> parent;
197 protected volatile Object sibling;
198 protected final long validStart, validEnd;
199
200 /**
201 * Object responsible for reclamation of some pointed memory when it's not used anymore.
202 */
203 public interface Releaser {
204 void release(Pointer<?> p);
205 }
206
207 Pointer(PointerIO<T> io, long peer, long validStart, long validEnd, Pointer<?> parent, long offsetInParent, Object sibling) {
208 this.io = io;
209 this.peer = peer;
210 this.validStart = validStart;
211 this.validEnd = validEnd;
212 this.parent = parent;
213 this.offsetInParent = offsetInParent;
214 this.sibling = sibling;
215 if (peer == 0)
216 throw new IllegalArgumentException("Pointer instance cannot have NULL peer ! (use null Pointer instead)");
217 if (BridJ.debugPointers)
218 creationTrace = new RuntimeException().fillInStackTrace();
219 }
220 Throwable creationTrace;
221
222
223 static class OrderedPointer<T> extends Pointer<T> {
224 OrderedPointer(PointerIO<T> io, long peer, long validStart, long validEnd, Pointer<?> parent, long offsetInParent, Object sibling) {
225 super(io, peer, validStart, validEnd, parent, offsetInParent, sibling);
226 }
227
228 @Override
229 public boolean isOrdered() {
230 return true;
231 }
232
233
234 @Override
235 public Pointer<T> setInt(int value) {
236
237 long checkedPeer = peer;
238 if (validStart != UNKNOWN_VALIDITY)
239 checkPeer(checkedPeer, 4);
240 JNI.set_int(checkedPeer, value);
241 return this;
242 }
243
244 @Override
245 public Pointer<T> setIntAtOffset(long byteOffset, int value) {
246 long checkedPeer = peer + byteOffset;
247 if (validStart != UNKNOWN_VALIDITY)
248 checkPeer(checkedPeer, 4);
249 JNI.set_int(checkedPeer, value);
250 return this;
251 }
252
253 @Override
254 public int getInt() {
255 long checkedPeer = peer;
256 if (validStart != UNKNOWN_VALIDITY)
257 checkPeer(checkedPeer, 4);
258 return JNI.get_int(checkedPeer);
259 }
260
261 @Override
262 public int getIntAtOffset(long byteOffset) {
263 long checkedPeer = peer + byteOffset;
264 if (validStart != UNKNOWN_VALIDITY)
265 checkPeer(checkedPeer, 4);
266 return JNI.get_int(checkedPeer);
267 }
268
269 @Override
270 public Pointer<T> setLong(long value) {
271
272 long checkedPeer = peer;
273 if (validStart != UNKNOWN_VALIDITY)
274 checkPeer(checkedPeer, 8);
275 JNI.set_long(checkedPeer, value);
276 return this;
277 }
278
279 @Override
280 public Pointer<T> setLongAtOffset(long byteOffset, long value) {
281 long checkedPeer = peer + byteOffset;
282 if (validStart != UNKNOWN_VALIDITY)
283 checkPeer(checkedPeer, 8);
284 JNI.set_long(checkedPeer, value);
285 return this;
286 }
287
288 @Override
289 public long getLong() {
290 long checkedPeer = peer;
291 if (validStart != UNKNOWN_VALIDITY)
292 checkPeer(checkedPeer, 8);
293 return JNI.get_long(checkedPeer);
294 }
295
296 @Override
297 public long getLongAtOffset(long byteOffset) {
298 long checkedPeer = peer + byteOffset;
299 if (validStart != UNKNOWN_VALIDITY)
300 checkPeer(checkedPeer, 8);
301 return JNI.get_long(checkedPeer);
302 }
303
304 @Override
305 public Pointer<T> setShort(short value) {
306
307 long checkedPeer = peer;
308 if (validStart != UNKNOWN_VALIDITY)
309 checkPeer(checkedPeer, 2);
310 JNI.set_short(checkedPeer, value);
311 return this;
312 }
313
314 @Override
315 public Pointer<T> setShortAtOffset(long byteOffset, short value) {
316 long checkedPeer = peer + byteOffset;
317 if (validStart != UNKNOWN_VALIDITY)
318 checkPeer(checkedPeer, 2);
319 JNI.set_short(checkedPeer, value);
320 return this;
321 }
322
323 @Override
324 public short getShort() {
325 long checkedPeer = peer;
326 if (validStart != UNKNOWN_VALIDITY)
327 checkPeer(checkedPeer, 2);
328 return JNI.get_short(checkedPeer);
329 }
330
331 @Override
332 public short getShortAtOffset(long byteOffset) {
333 long checkedPeer = peer + byteOffset;
334 if (validStart != UNKNOWN_VALIDITY)
335 checkPeer(checkedPeer, 2);
336 return JNI.get_short(checkedPeer);
337 }
338
339 @Override
340 public Pointer<T> setByte(byte value) {
341
342 long checkedPeer = peer;
343 if (validStart != UNKNOWN_VALIDITY)
344 checkPeer(checkedPeer, 1);
345 JNI.set_byte(checkedPeer, value);
346 return this;
347 }
348
349 @Override
350 public Pointer<T> setByteAtOffset(long byteOffset, byte value) {
351 long checkedPeer = peer + byteOffset;
352 if (validStart != UNKNOWN_VALIDITY)
353 checkPeer(checkedPeer, 1);
354 JNI.set_byte(checkedPeer, value);
355 return this;
356 }
357
358 @Override
359 public byte getByte() {
360 long checkedPeer = peer;
361 if (validStart != UNKNOWN_VALIDITY)
362 checkPeer(checkedPeer, 1);
363 return JNI.get_byte(checkedPeer);
364 }
365
366 @Override
367 public byte getByteAtOffset(long byteOffset) {
368 long checkedPeer = peer + byteOffset;
369 if (validStart != UNKNOWN_VALIDITY)
370 checkPeer(checkedPeer, 1);
371 return JNI.get_byte(checkedPeer);
372 }
373
374 @Override
375 public Pointer<T> setChar(char value) {
376 if (Platform.WCHAR_T_SIZE == 4)
377 return setInt((int)value);
378
379 long checkedPeer = peer;
380 if (validStart != UNKNOWN_VALIDITY)
381 checkPeer(checkedPeer, Platform.WCHAR_T_SIZE);
382 JNI.set_char(checkedPeer, value);
383 return this;
384 }
385
386 @Override
387 public Pointer<T> setCharAtOffset(long byteOffset, char value) {
388 if (Platform.WCHAR_T_SIZE == 4)
389 return setIntAtOffset(byteOffset, (int)value);
390 long checkedPeer = peer + byteOffset;
391 if (validStart != UNKNOWN_VALIDITY)
392 checkPeer(checkedPeer, Platform.WCHAR_T_SIZE);
393 JNI.set_char(checkedPeer, value);
394 return this;
395 }
396
397 @Override
398 public char getChar() {
399 if (Platform.WCHAR_T_SIZE == 4)
400 return (char)getInt();
401 long checkedPeer = peer;
402 if (validStart != UNKNOWN_VALIDITY)
403 checkPeer(checkedPeer, Platform.WCHAR_T_SIZE);
404 return JNI.get_char(checkedPeer);
405 }
406
407 @Override
408 public char getCharAtOffset(long byteOffset) {
409 if (Platform.WCHAR_T_SIZE == 4)
410 return (char)getIntAtOffset(byteOffset);
411 long checkedPeer = peer + byteOffset;
412 if (validStart != UNKNOWN_VALIDITY)
413 checkPeer(checkedPeer, Platform.WCHAR_T_SIZE);
414 return JNI.get_char(checkedPeer);
415 }
416
417 @Override
418 public Pointer<T> setFloat(float value) {
419
420 long checkedPeer = peer;
421 if (validStart != UNKNOWN_VALIDITY)
422 checkPeer(checkedPeer, 4);
423 JNI.set_float(checkedPeer, value);
424 return this;
425 }
426
427 @Override
428 public Pointer<T> setFloatAtOffset(long byteOffset, float value) {
429 long checkedPeer = peer + byteOffset;
430 if (validStart != UNKNOWN_VALIDITY)
431 checkPeer(checkedPeer, 4);
432 JNI.set_float(checkedPeer, value);
433 return this;
434 }
435
436 @Override
437 public float getFloat() {
438 long checkedPeer = peer;
439 if (validStart != UNKNOWN_VALIDITY)
440 checkPeer(checkedPeer, 4);
441 return JNI.get_float(checkedPeer);
442 }
443
444 @Override
445 public float getFloatAtOffset(long byteOffset) {
446 long checkedPeer = peer + byteOffset;
447 if (validStart != UNKNOWN_VALIDITY)
448 checkPeer(checkedPeer, 4);
449 return JNI.get_float(checkedPeer);
450 }
451
452 @Override
453 public Pointer<T> setDouble(double value) {
454
455 long checkedPeer = peer;
456 if (validStart != UNKNOWN_VALIDITY)
457 checkPeer(checkedPeer, 8);
458 JNI.set_double(checkedPeer, value);
459 return this;
460 }
461
462 @Override
463 public Pointer<T> setDoubleAtOffset(long byteOffset, double value) {
464 long checkedPeer = peer + byteOffset;
465 if (validStart != UNKNOWN_VALIDITY)
466 checkPeer(checkedPeer, 8);
467 JNI.set_double(checkedPeer, value);
468 return this;
469 }
470
471 @Override
472 public double getDouble() {
473 long checkedPeer = peer;
474 if (validStart != UNKNOWN_VALIDITY)
475 checkPeer(checkedPeer, 8);
476 return JNI.get_double(checkedPeer);
477 }
478
479 @Override
480 public double getDoubleAtOffset(long byteOffset) {
481 long checkedPeer = peer + byteOffset;
482 if (validStart != UNKNOWN_VALIDITY)
483 checkPeer(checkedPeer, 8);
484 return JNI.get_double(checkedPeer);
485 }
486
487 @Override
488 public Pointer<T> setBoolean(boolean value) {
489
490 long checkedPeer = peer;
491 if (validStart != UNKNOWN_VALIDITY)
492 checkPeer(checkedPeer, 1);
493 JNI.set_boolean(checkedPeer, value);
494 return this;
495 }
496
497 @Override
498 public Pointer<T> setBooleanAtOffset(long byteOffset, boolean value) {
499 long checkedPeer = peer + byteOffset;
500 if (validStart != UNKNOWN_VALIDITY)
501 checkPeer(checkedPeer, 1);
502 JNI.set_boolean(checkedPeer, value);
503 return this;
504 }
505
506 @Override
507 public boolean getBoolean() {
508 long checkedPeer = peer;
509 if (validStart != UNKNOWN_VALIDITY)
510 checkPeer(checkedPeer, 1);
511 return JNI.get_boolean(checkedPeer);
512 }
513
514 @Override
515 public boolean getBooleanAtOffset(long byteOffset) {
516 long checkedPeer = peer + byteOffset;
517 if (validStart != UNKNOWN_VALIDITY)
518 checkPeer(checkedPeer, 1);
519 return JNI.get_boolean(checkedPeer);
520 }
521
522
523
524
525 @Override
526 public Pointer<T> setSizeTsAtOffset(long byteOffset, long[] values, int valuesOffset, int length) {
527 if (values == null)
528 throw new IllegalArgumentException("Null values");
529 if (SizeT.SIZE == 8) {
530 setLongsAtOffset(byteOffset, values, valuesOffset, length);
531 } else {
532 int n = length;
533 long checkedPeer = peer + byteOffset;
534 if (validStart != UNKNOWN_VALIDITY)
535 checkPeer(checkedPeer, n * 4);
536
537 long peer = checkedPeer;
538 int valuesIndex = valuesOffset;
539 for (int i = 0; i < n; i++) {
540 int value = (int)values[valuesIndex];
541 JNI.set_int(peer, value);
542 peer += 4;
543 valuesIndex++;
544 }
545 }
546 return this;
547 }
548 /**
549 * Write an array of SizeT values to the pointed memory location shifted by a byte offset
550 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#setSizeTs(int[])} over this method.
551 */
552 public Pointer<T> setSizeTsAtOffset(long byteOffset, int[] values) {
553 if (SizeT.SIZE == 4) {
554 setIntsAtOffset(byteOffset, values);
555 } else {
556 int n = values.length;
557 long checkedPeer = peer + byteOffset;
558 if (validStart != UNKNOWN_VALIDITY)
559 checkPeer(checkedPeer, n * 8);
560
561 long peer = checkedPeer;
562 for (int i = 0; i < n; i++) {
563 int value = values[i];
564 JNI.set_long(peer, value);
565 peer += 8;
566 }
567 }
568 return this;
569 }
570
571
572 @Override
573 public Pointer<T> setCLongsAtOffset(long byteOffset, long[] values, int valuesOffset, int length) {
574 if (values == null)
575 throw new IllegalArgumentException("Null values");
576 if (CLong.SIZE == 8) {
577 setLongsAtOffset(byteOffset, values, valuesOffset, length);
578 } else {
579 int n = length;
580 long checkedPeer = peer + byteOffset;
581 if (validStart != UNKNOWN_VALIDITY)
582 checkPeer(checkedPeer, n * 4);
583
584 long peer = checkedPeer;
585 int valuesIndex = valuesOffset;
586 for (int i = 0; i < n; i++) {
587 int value = (int)values[valuesIndex];
588 JNI.set_int(peer, value);
589 peer += 4;
590 valuesIndex++;
591 }
592 }
593 return this;
594 }
595 /**
596 * Write an array of CLong values to the pointed memory location shifted by a byte offset
597 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#setCLongs(int[])} over this method.
598 */
599 public Pointer<T> setCLongsAtOffset(long byteOffset, int[] values) {
600 if (CLong.SIZE == 4) {
601 setIntsAtOffset(byteOffset, values);
602 } else {
603 int n = values.length;
604 long checkedPeer = peer + byteOffset;
605 if (validStart != UNKNOWN_VALIDITY)
606 checkPeer(checkedPeer, n * 8);
607
608 long peer = checkedPeer;
609 for (int i = 0; i < n; i++) {
610 int value = values[i];
611 JNI.set_long(peer, value);
612 peer += 8;
613 }
614 }
615 return this;
616 }
617 }
618
619 static class DisorderedPointer<T> extends Pointer<T> {
620 DisorderedPointer(PointerIO<T> io, long peer, long validStart, long validEnd, Pointer<?> parent, long offsetInParent, Object sibling) {
621 super(io, peer, validStart, validEnd, parent, offsetInParent, sibling);
622 }
623
624 @Override
625 public boolean isOrdered() {
626 return false;
627 }
628
629
630 @Override
631 public Pointer<T> setInt(int value) {
632
633 long checkedPeer = peer;
634 if (validStart != UNKNOWN_VALIDITY)
635 checkPeer(checkedPeer, 4);
636 JNI.set_int_disordered(checkedPeer, value);
637 return this;
638 }
639
640 @Override
641 public Pointer<T> setIntAtOffset(long byteOffset, int value) {
642 long checkedPeer = peer + byteOffset;
643 if (validStart != UNKNOWN_VALIDITY)
644 checkPeer(checkedPeer, 4);
645 JNI.set_int_disordered(checkedPeer, value);
646 return this;
647 }
648
649 @Override
650 public int getInt() {
651 long checkedPeer = peer;
652 if (validStart != UNKNOWN_VALIDITY)
653 checkPeer(checkedPeer, 4);
654 return JNI.get_int_disordered(checkedPeer);
655 }
656
657 @Override
658 public int getIntAtOffset(long byteOffset) {
659 long checkedPeer = peer + byteOffset;
660 if (validStart != UNKNOWN_VALIDITY)
661 checkPeer(checkedPeer, 4);
662 return JNI.get_int_disordered(checkedPeer);
663 }
664
665 @Override
666 public Pointer<T> setLong(long value) {
667
668 long checkedPeer = peer;
669 if (validStart != UNKNOWN_VALIDITY)
670 checkPeer(checkedPeer, 8);
671 JNI.set_long_disordered(checkedPeer, value);
672 return this;
673 }
674
675 @Override
676 public Pointer<T> setLongAtOffset(long byteOffset, long value) {
677 long checkedPeer = peer + byteOffset;
678 if (validStart != UNKNOWN_VALIDITY)
679 checkPeer(checkedPeer, 8);
680 JNI.set_long_disordered(checkedPeer, value);
681 return this;
682 }
683
684 @Override
685 public long getLong() {
686 long checkedPeer = peer;
687 if (validStart != UNKNOWN_VALIDITY)
688 checkPeer(checkedPeer, 8);
689 return JNI.get_long_disordered(checkedPeer);
690 }
691
692 @Override
693 public long getLongAtOffset(long byteOffset) {
694 long checkedPeer = peer + byteOffset;
695 if (validStart != UNKNOWN_VALIDITY)
696 checkPeer(checkedPeer, 8);
697 return JNI.get_long_disordered(checkedPeer);
698 }
699
700 @Override
701 public Pointer<T> setShort(short value) {
702
703 long checkedPeer = peer;
704 if (validStart != UNKNOWN_VALIDITY)
705 checkPeer(checkedPeer, 2);
706 JNI.set_short_disordered(checkedPeer, value);
707 return this;
708 }
709
710 @Override
711 public Pointer<T> setShortAtOffset(long byteOffset, short value) {
712 long checkedPeer = peer + byteOffset;
713 if (validStart != UNKNOWN_VALIDITY)
714 checkPeer(checkedPeer, 2);
715 JNI.set_short_disordered(checkedPeer, value);
716 return this;
717 }
718
719 @Override
720 public short getShort() {
721 long checkedPeer = peer;
722 if (validStart != UNKNOWN_VALIDITY)
723 checkPeer(checkedPeer, 2);
724 return JNI.get_short_disordered(checkedPeer);
725 }
726
727 @Override
728 public short getShortAtOffset(long byteOffset) {
729 long checkedPeer = peer + byteOffset;
730 if (validStart != UNKNOWN_VALIDITY)
731 checkPeer(checkedPeer, 2);
732 return JNI.get_short_disordered(checkedPeer);
733 }
734
735 @Override
736 public Pointer<T> setByte(byte value) {
737
738 long checkedPeer = peer;
739 if (validStart != UNKNOWN_VALIDITY)
740 checkPeer(checkedPeer, 1);
741 JNI.set_byte(checkedPeer, value);
742 return this;
743 }
744
745 @Override
746 public Pointer<T> setByteAtOffset(long byteOffset, byte value) {
747 long checkedPeer = peer + byteOffset;
748 if (validStart != UNKNOWN_VALIDITY)
749 checkPeer(checkedPeer, 1);
750 JNI.set_byte(checkedPeer, value);
751 return this;
752 }
753
754 @Override
755 public byte getByte() {
756 long checkedPeer = peer;
757 if (validStart != UNKNOWN_VALIDITY)
758 checkPeer(checkedPeer, 1);
759 return JNI.get_byte(checkedPeer);
760 }
761
762 @Override
763 public byte getByteAtOffset(long byteOffset) {
764 long checkedPeer = peer + byteOffset;
765 if (validStart != UNKNOWN_VALIDITY)
766 checkPeer(checkedPeer, 1);
767 return JNI.get_byte(checkedPeer);
768 }
769
770 @Override
771 public Pointer<T> setChar(char value) {
772 if (Platform.WCHAR_T_SIZE == 4)
773 return setInt((int)value);
774
775 long checkedPeer = peer;
776 if (validStart != UNKNOWN_VALIDITY)
777 checkPeer(checkedPeer, Platform.WCHAR_T_SIZE);
778 JNI.set_char_disordered(checkedPeer, value);
779 return this;
780 }
781
782 @Override
783 public Pointer<T> setCharAtOffset(long byteOffset, char value) {
784 if (Platform.WCHAR_T_SIZE == 4)
785 return setIntAtOffset(byteOffset, (int)value);
786 long checkedPeer = peer + byteOffset;
787 if (validStart != UNKNOWN_VALIDITY)
788 checkPeer(checkedPeer, Platform.WCHAR_T_SIZE);
789 JNI.set_char_disordered(checkedPeer, value);
790 return this;
791 }
792
793 @Override
794 public char getChar() {
795 if (Platform.WCHAR_T_SIZE == 4)
796 return (char)getInt();
797 long checkedPeer = peer;
798 if (validStart != UNKNOWN_VALIDITY)
799 checkPeer(checkedPeer, Platform.WCHAR_T_SIZE);
800 return JNI.get_char_disordered(checkedPeer);
801 }
802
803 @Override
804 public char getCharAtOffset(long byteOffset) {
805 if (Platform.WCHAR_T_SIZE == 4)
806 return (char)getIntAtOffset(byteOffset);
807 long checkedPeer = peer + byteOffset;
808 if (validStart != UNKNOWN_VALIDITY)
809 checkPeer(checkedPeer, Platform.WCHAR_T_SIZE);
810 return JNI.get_char_disordered(checkedPeer);
811 }
812
813 @Override
814 public Pointer<T> setFloat(float value) {
815
816 long checkedPeer = peer;
817 if (validStart != UNKNOWN_VALIDITY)
818 checkPeer(checkedPeer, 4);
819 JNI.set_float_disordered(checkedPeer, value);
820 return this;
821 }
822
823 @Override
824 public Pointer<T> setFloatAtOffset(long byteOffset, float value) {
825 long checkedPeer = peer + byteOffset;
826 if (validStart != UNKNOWN_VALIDITY)
827 checkPeer(checkedPeer, 4);
828 JNI.set_float_disordered(checkedPeer, value);
829 return this;
830 }
831
832 @Override
833 public float getFloat() {
834 long checkedPeer = peer;
835 if (validStart != UNKNOWN_VALIDITY)
836 checkPeer(checkedPeer, 4);
837 return JNI.get_float_disordered(checkedPeer);
838 }
839
840 @Override
841 public float getFloatAtOffset(long byteOffset) {
842 long checkedPeer = peer + byteOffset;
843 if (validStart != UNKNOWN_VALIDITY)
844 checkPeer(checkedPeer, 4);
845 return JNI.get_float_disordered(checkedPeer);
846 }
847
848 @Override
849 public Pointer<T> setDouble(double value) {
850
851 long checkedPeer = peer;
852 if (validStart != UNKNOWN_VALIDITY)
853 checkPeer(checkedPeer, 8);
854 JNI.set_double_disordered(checkedPeer, value);
855 return this;
856 }
857
858 @Override
859 public Pointer<T> setDoubleAtOffset(long byteOffset, double value) {
860 long checkedPeer = peer + byteOffset;
861 if (validStart != UNKNOWN_VALIDITY)
862 checkPeer(checkedPeer, 8);
863 JNI.set_double_disordered(checkedPeer, value);
864 return this;
865 }
866
867 @Override
868 public double getDouble() {
869 long checkedPeer = peer;
870 if (validStart != UNKNOWN_VALIDITY)
871 checkPeer(checkedPeer, 8);
872 return JNI.get_double_disordered(checkedPeer);
873 }
874
875 @Override
876 public double getDoubleAtOffset(long byteOffset) {
877 long checkedPeer = peer + byteOffset;
878 if (validStart != UNKNOWN_VALIDITY)
879 checkPeer(checkedPeer, 8);
880 return JNI.get_double_disordered(checkedPeer);
881 }
882
883 @Override
884 public Pointer<T> setBoolean(boolean value) {
885
886 long checkedPeer = peer;
887 if (validStart != UNKNOWN_VALIDITY)
888 checkPeer(checkedPeer, 1);
889 JNI.set_boolean(checkedPeer, value);
890 return this;
891 }
892
893 @Override
894 public Pointer<T> setBooleanAtOffset(long byteOffset, boolean value) {
895 long checkedPeer = peer + byteOffset;
896 if (validStart != UNKNOWN_VALIDITY)
897 checkPeer(checkedPeer, 1);
898 JNI.set_boolean(checkedPeer, value);
899 return this;
900 }
901
902 @Override
903 public boolean getBoolean() {
904 long checkedPeer = peer;
905 if (validStart != UNKNOWN_VALIDITY)
906 checkPeer(checkedPeer, 1);
907 return JNI.get_boolean(checkedPeer);
908 }
909
910 @Override
911 public boolean getBooleanAtOffset(long byteOffset) {
912 long checkedPeer = peer + byteOffset;
913 if (validStart != UNKNOWN_VALIDITY)
914 checkPeer(checkedPeer, 1);
915 return JNI.get_boolean(checkedPeer);
916 }
917
918
919
920
921 @Override
922 public Pointer<T> setSizeTsAtOffset(long byteOffset, long[] values, int valuesOffset, int length) {
923 if (values == null)
924 throw new IllegalArgumentException("Null values");
925 if (SizeT.SIZE == 8) {
926 setLongsAtOffset(byteOffset, values, valuesOffset, length);
927 } else {
928 int n = length;
929 long checkedPeer = peer + byteOffset;
930 if (validStart != UNKNOWN_VALIDITY)
931 checkPeer(checkedPeer, n * 4);
932
933 long peer = checkedPeer;
934 int valuesIndex = valuesOffset;
935 for (int i = 0; i < n; i++) {
936 int value = (int)values[valuesIndex];
937 JNI.set_int_disordered(peer, value);
938 peer += 4;
939 valuesIndex++;
940 }
941 }
942 return this;
943 }
944 /**
945 * Write an array of SizeT values to the pointed memory location shifted by a byte offset
946 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#setSizeTs(int[])} over this method.
947 */
948 public Pointer<T> setSizeTsAtOffset(long byteOffset, int[] values) {
949 if (SizeT.SIZE == 4) {
950 setIntsAtOffset(byteOffset, values);
951 } else {
952 int n = values.length;
953 long checkedPeer = peer + byteOffset;
954 if (validStart != UNKNOWN_VALIDITY)
955 checkPeer(checkedPeer, n * 8);
956
957 long peer = checkedPeer;
958 for (int i = 0; i < n; i++) {
959 int value = values[i];
960 JNI.set_long_disordered(peer, value);
961 peer += 8;
962 }
963 }
964 return this;
965 }
966
967
968 @Override
969 public Pointer<T> setCLongsAtOffset(long byteOffset, long[] values, int valuesOffset, int length) {
970 if (values == null)
971 throw new IllegalArgumentException("Null values");
972 if (CLong.SIZE == 8) {
973 setLongsAtOffset(byteOffset, values, valuesOffset, length);
974 } else {
975 int n = length;
976 long checkedPeer = peer + byteOffset;
977 if (validStart != UNKNOWN_VALIDITY)
978 checkPeer(checkedPeer, n * 4);
979
980 long peer = checkedPeer;
981 int valuesIndex = valuesOffset;
982 for (int i = 0; i < n; i++) {
983 int value = (int)values[valuesIndex];
984 JNI.set_int_disordered(peer, value);
985 peer += 4;
986 valuesIndex++;
987 }
988 }
989 return this;
990 }
991 /**
992 * Write an array of CLong values to the pointed memory location shifted by a byte offset
993 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#setCLongs(int[])} over this method.
994 */
995 public Pointer<T> setCLongsAtOffset(long byteOffset, int[] values) {
996 if (CLong.SIZE == 4) {
997 setIntsAtOffset(byteOffset, values);
998 } else {
999 int n = values.length;
1000 long checkedPeer = peer + byteOffset;
1001 if (validStart != UNKNOWN_VALIDITY)
1002 checkPeer(checkedPeer, n * 8);
1003
1004 long peer = checkedPeer;
1005 for (int i = 0; i < n; i++) {
1006 int value = values[i];
1007 JNI.set_long_disordered(peer, value);
1008 peer += 8;
1009 }
1010 }
1011 return this;
1012 }
1013 }
1014
1015 /**
1016 * Create a {@code Pointer<T>} type. <br>
1017 * For Instance, {@code Pointer.pointerType(Integer.class) } returns a type that represents {@code Pointer<Integer> }
1018 */
1019 public static Type pointerType(Type targetType) {
1020 return org.bridj.util.DefaultParameterizedType.paramType(Pointer.class, targetType);
1021 }
1022 /**
1023 * Create a {@code IntValuedEnum<T>} type. <br>
1024 * For Instance, {@code Pointer.intEnumType(SomeEnum.class) } returns a type that represents {@code IntValuedEnum<SomeEnum> }
1025 */
1026 public static <E extends Enum<E>> Type intEnumType(Class<? extends IntValuedEnum<E>> targetType) {
1027 return org.bridj.util.DefaultParameterizedType.paramType(IntValuedEnum.class, targetType);
1028 }
1029
1030 /**
1031 * Manually release the memory pointed by this pointer if it was allocated on the Java side.<br>
1032 * If the pointer is an offset version of another pointer (using {@link Pointer#offset(long)} or {@link Pointer#next(long)}, for instance), this method tries to release the original pointer.<br>
1033 * If the memory was not allocated from the Java side, this method does nothing either.<br>
1034 * If the memory was already successfully released, this throws a RuntimeException.
1035 * @throws RuntimeException if the pointer was already released
1036 */
1037 public synchronized void release() {
1038 Object sibling = this.sibling;
1039 this.sibling = null;
1040 if (sibling instanceof Pointer)
1041 ((Pointer)sibling).release();
1042 }
1043
1044 /**
1045 * Compare to another pointer based on pointed addresses.
1046 * @param p other pointer
1047 * @return 1 if this pointer's address is greater than p's (or if p is null), -1 if the opposite is true, 0 if this and p point to the same memory location.
1048 */
1049 //@Override
1050 public int compareTo(Pointer<?> p) {
1051 if (p == null)
1052 return 1;
1053
1054 long p1 = getPeer(), p2 = p.getPeer();
1055 return p1 == p2 ? 0 : p1 < p2 ? -1 : 1;
1056 }
1057
1058 /**
1059 * Compare the byteCount bytes at the memory location pointed by this pointer to the byteCount bytes at the memory location pointer by other using the C @see <a href="http://www.cplusplus.com/reference/clibrary/cstring/memcmp/">memcmp</a> function.<br>
1060 * @return 0 if the two memory blocks are equal, -1 if this pointer's memory is "less" than the other and 1 otherwise.
1061 */
1062 public int compareBytes(Pointer<?> other, long byteCount) {
1063 return compareBytesAtOffset(0, other, 0, byteCount);
1064 }
1065
1066 /**
1067 * Compare the byteCount bytes at the memory location pointed by this pointer shifted by byteOffset to the byteCount bytes at the memory location pointer by other shifted by otherByteOffset using the C @see <a href="http://www.cplusplus.com/reference/clibrary/cstring/memcmp/">memcmp</a> function.<br>
1068 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues)
1069 * @return 0 if the two memory blocks are equal, -1 if this pointer's memory is "less" than the other and 1 otherwise.
1070 */
1071 public int compareBytesAtOffset(long byteOffset, Pointer<?> other, long otherByteOffset, long byteCount) {
1072 long checkedPeer = peer + byteOffset;
1073 if (validStart != UNKNOWN_VALIDITY)
1074 checkPeer(checkedPeer, byteCount);
1075 return JNI.memcmp(checkedPeer, other.getCheckedPeer(otherByteOffset, byteCount), byteCount);
1076 }
1077
1078 /**
1079 * Compute a hash code based on pointed address.
1080 */
1081 @Override
1082 public int hashCode() {
1083 int hc = new Long(getPeer()).hashCode();
1084 return hc;
1085 }
1086
1087 @Override
1088 public String toString() {
1089 return "Pointer(peer = 0x" + Long.toHexString(getPeer()) + ", targetType = " + Utils.toString(getTargetType()) + ", order = " + order() + ")";
1090 }
1091
1092 protected final void checkPeer(long peer, long validityCheckLength) {
1093 if (peer < validStart || (peer + validityCheckLength) > validEnd) {
1094 throw new IndexOutOfBoundsException("Cannot access to memory data of length " + validityCheckLength + " at offset " + (peer - getPeer()) + " : valid memory start is " + validStart + ", valid memory size is " + (validEnd - validStart));
1095 }
1096 }
1097
1098 private final long getCheckedPeer(long byteOffset, long validityCheckLength) {
1099 long checkedPeer = peer + byteOffset;
1100 if (validStart != UNKNOWN_VALIDITY)
1101 checkPeer(checkedPeer, validityCheckLength);
1102 return checkedPeer;
1103 }
1104
1105 /**
1106 * Returns a pointer which address value was obtained by this pointer's by adding a byte offset.<br>
1107 * The returned pointer will prevent the memory associated to this pointer from being automatically reclaimed as long as it lives, unless Pointer.release() is called on the originally-allocated pointer.
1108 * @param byteOffset offset in bytes of the new pointer vs. this pointer. The expression {@code p.offset(byteOffset).getPeer() - p.getPeer() == byteOffset} is always true.
1109 */
1110 public Pointer<T> offset(long byteOffset) {
1111 return offset(byteOffset, getIO());
1112 }
1113
1114 <U> Pointer<U> offset(long byteOffset, PointerIO<U> pio) {
1115 if (byteOffset == 0)
1116 return pio == this.io ? (Pointer<U>)this : as(pio);
1117
1118 long newPeer = getPeer() + byteOffset;
1119
1120 Object newSibling = getSibling() != null ? getSibling() : this;
1121 if (validStart == UNKNOWN_VALIDITY)
1122 return newPointer(pio, newPeer, isOrdered(), UNKNOWN_VALIDITY, UNKNOWN_VALIDITY, null, NO_PARENT, null, newSibling);
1123 if (newPeer > validEnd || newPeer < validStart)
1124 throw new IndexOutOfBoundsException("Invalid pointer offset : " + byteOffset + " (validBytes = " + getValidBytes() + ") !");
1125
1126 return newPointer(pio, newPeer, isOrdered(), validStart, validEnd, null, NO_PARENT, null, newSibling);
1127 }
1128
1129 /**
1130 * Creates a pointer that has the given number of valid bytes ahead.<br>
1131 * If the pointer was already bound, the valid bytes must be lower or equal to the current getValidBytes() value.
1132 */
1133 public Pointer<T> validBytes(long byteCount) {
1134 long peer = getPeer();
1135 long newValidEnd = peer + byteCount;
1136 if (validStart == peer && validEnd == newValidEnd)
1137 return this;
1138
1139 if (validEnd != UNKNOWN_VALIDITY && newValidEnd > validEnd)
1140 throw new IndexOutOfBoundsException("Cannot extend validity of pointed memory from " + validEnd + " to " + newValidEnd);
1141
1142 Object newSibling = getSibling() != null ? getSibling() : this;
1143 return newPointer(getIO(), peer, isOrdered(), validStart, newValidEnd, parent, offsetInParent, null, newSibling);
1144 }
1145
1146 /**
1147 * Creates a pointer that forgot any memory validity information.<br>
1148 * Such pointers are typically faster than validity-aware pointers, since they perform less checks at each operation, but they're more prone to crashes if misused.
1149 * @deprecated Pointers obtained via this method are faster but unsafe and are likely to cause crashes hard to debug if your logic is wrong.
1150 */
1151 @Deprecated
1152 public Pointer<T> withoutValidityInformation() {
1153 long peer = getPeer();
1154 if (validStart == UNKNOWN_VALIDITY)
1155 return this;
1156
1157 Object newSibling = getSibling() != null ? getSibling() : this;
1158 return newPointer(getIO(), peer, isOrdered(), UNKNOWN_VALIDITY, UNKNOWN_VALIDITY, parent, offsetInParent, null, newSibling);
1159 }
1160
1161 /**
1162 * Creates a copy of the pointed memory location (allocates a new area of memory) and returns a pointer to it.<br>
1163 * The pointer's bounds must be known (see {@link Pointer#getValidBytes()}, {@link Pointer#validBytes(long)} or {@link Pointer#validElements(long)}).
1164 */
1165 public Pointer<T> clone() {
1166 long length = getValidElements();
1167 if (length < 0)
1168 throw new UnsupportedOperationException("Number of bytes unknown, unable to clone memory (use validBytes(long))");
1169
1170 Pointer<T> c = allocateArray(getIO(), length);
1171 copyTo(c);
1172 return c;
1173 }
1174
1175 /**
1176 * Creates a pointer that has the given number of valid elements ahead.<br>
1177 * If the pointer was already bound, elementCount must be lower or equal to the current getValidElements() value.
1178 */
1179 public Pointer<T> validElements(long elementCount) {
1180 return validBytes(elementCount * getIO("Cannot define elements validity").getTargetSize());
1181 }
1182
1183 /**
1184 * Returns a pointer to this pointer.<br>
1185 * It will only succeed if this pointer was dereferenced from another pointer.<br>
1186 * Let's take the following C++ code :
1187 * <pre>{@code
1188 int** pp = ...;
1189 int* p = pp[10];
1190 int** ref = &p;
1191 ASSERT(pp == ref);
1192 }</pre>
1193 * Here is its equivalent Java code :
1194 * <pre>{@code
1195 Pointer<Pointer<Integer>> pp = ...;
1196 Pointer<Integer> p = pp.get(10);
1197 Pointer<Pointer<Integer>> ref = p.getReference();
1198 assert pp.equals(ref);
1199 }</pre>
1200 */
1201 public Pointer<Pointer<T>> getReference() {
1202 if (parent == null)
1203 throw new UnsupportedOperationException("Cannot get reference to this pointer, it wasn't created from Pointer.getPointer(offset) or from a similar method.");
1204
1205 PointerIO io = getIO();
1206 return parent.offset(offsetInParent).as(io == null ? null : io.getReferenceIO());
1207 }
1208
1209 /**
1210 * Get the address of the memory pointed to by this pointer ("cast this pointer to long", in C jargon).<br>
1211 * This is equivalent to the C code {@code (size_t)&pointer}
1212 * @return Address of the memory pointed to by this pointer
1213 */
1214 public final long getPeer() {
1215 return peer;
1216 }
1217
1218 /**
1219 * Create a native callback which signature corresponds to the provided calling convention, return type and parameter types, and which redirects calls to the provided Java {@link org.bridj.DynamicCallback} handler.<br/>
1220 * For instance, a callback of C signature <code>double (*)(float, int)</code> that adds its two arguments can be created with :<br>
1221 * <code>{@code
1222 * Pointer callback = Pointer.allocateDynamicCallback(
1223 * new DynamicCallback<Integer>() {
1224 * public Double apply(Object... args) {
1225 * float a = (Float)args[0];
1226 * int b = (Integer)args[1];
1227 * return (double)(a + b);
1228 * }
1229 * },
1230 * null, // Use the platform's default calling convention
1231 * int.class, // return type
1232 * float.class, double.class // parameter types
1233 * );
1234 * }</code><br>
1235 * For the <code>void</code> return type, you can use {@link java.lang.Void} :<br>
1236 * <code>{@code
1237 * Pointer callback = Pointer.allocateDynamicCallback(
1238 * new DynamicCallback<Void>() {
1239 * public Void apply(Object... args) {
1240 * ...
1241 * return null; // Void cannot be instantiated anyway ;-)
1242 * }
1243 * },
1244 * null, // Use the platform's default calling convention
1245 * int.class, // return type
1246 * float.class, double.class // parameter types
1247 * );
1248 * }</code><br>
1249 * @return Pointer to a native callback that redirects calls to the provided Java callback instance, and that will be destroyed whenever the pointer is released (make sure you keep a reference to it !)
1250 */
1251 public static <R> Pointer<DynamicFunction<R>> allocateDynamicCallback(DynamicCallback<R> callback, org.bridj.ann.Convention.Style callingConvention, Type returnType, Type... parameterTypes) {
1252 if (callback == null)
1253 throw new IllegalArgumentException("Java callback handler cannot be null !");
1254 if (returnType == null)
1255 throw new IllegalArgumentException("Callback return type cannot be null !");
1256 if (parameterTypes == null)
1257 throw new IllegalArgumentException("Invalid (null) list of parameter types !");
1258 try {
1259 MethodCallInfo mci = new MethodCallInfo(returnType, parameterTypes, false);
1260 Method method = DynamicCallback.class.getMethod("apply", Object[].class);
1261 mci.setMethod(method);
1262 mci.setJavaSignature("([Ljava/lang/Object;)Ljava/lang/Object;");
1263 mci.setCallingConvention(callingConvention);
1264 mci.setGenericCallback(true);
1265 mci.setJavaCallback(callback);
1266
1267 //System.out.println("Java sig
1268
1269 return CRuntime.createCToJavaCallback(mci, DynamicCallback.class);
1270 } catch (Exception ex) {
1271 throw new RuntimeException("Failed to allocate dynamic callback for convention " + callingConvention + ", return type " + Utils.toString(returnType) + " and parameter types " + Arrays.asList(parameterTypes) + " : " + ex, ex);
1272 }
1273 }
1274
1275 /**
1276 * Cast this pointer to another pointer type
1277 * @param newIO
1278 */
1279 public <U> Pointer<U> as(PointerIO<U> newIO) {
1280 return viewAs(isOrdered(), newIO);
1281 }
1282 /**
1283 * Create a view of this pointer that has the byte order provided in argument, or return this if this pointer already uses the requested byte order.
1284 * @param order byte order (endianness) of the returned pointer
1285 */
1286 public Pointer<T> order(ByteOrder order) {
1287 if (order.equals(ByteOrder.nativeOrder()) == isOrdered())
1288 return this;
1289
1290 return viewAs(!isOrdered(), getIO());
1291 }
1292
1293 /**
1294 * Get the byte order (endianness) of this pointer.
1295 */
1296 public ByteOrder order() {
1297 ByteOrder order = isOrdered() ? ByteOrder.nativeOrder() : ByteOrder.nativeOrder() == ByteOrder.BIG_ENDIAN ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN;
1298 return order;
1299 }
1300
1301 <U> Pointer<U> viewAs(boolean ordered, PointerIO<U> newIO) {
1302 if (newIO == io && ordered == isOrdered())
1303 return (Pointer<U>)this;
1304 else
1305 return newPointer(newIO, getPeer(), ordered, getValidStart(), getValidEnd(), getParent(), getOffsetInParent(), null, getSibling() != null ? getSibling() : this);
1306 }
1307
1308 /**
1309 * Get the PointerIO instance used by this pointer to get and set pointed values.
1310 */
1311 public final PointerIO<T> getIO() {
1312 return io;
1313 }
1314
1315 /**
1316 * Whether this pointer reads data in the system's native byte order or not.
1317 * See {@link Pointer#order()}, {@link Pointer#order(ByteOrder)}
1318 */
1319 public abstract boolean isOrdered();
1320
1321 final long getOffsetInParent() {
1322 return offsetInParent;
1323 }
1324 final Pointer<?> getParent() {
1325 return parent;
1326 }
1327 final Object getSibling() {
1328 return sibling;
1329 }
1330
1331 final long getValidEnd() {
1332 return validEnd;
1333 }
1334 final long getValidStart() {
1335 return validStart;
1336 }
1337
1338 /**
1339 * Cast this pointer to another pointer type<br>
1340 * Synonym of {@link Pointer#as(Class)}<br>
1341 * The following C code :<br>
1342 * <code>{@code
1343 * T* pointerT = ...;
1344 * U* pointerU = (U*)pointerT;
1345 * }</code><br>
1346 * Can be translated to the following Java code :<br>
1347 * <code>{@code
1348 * Pointer<T> pointerT = ...;
1349 * Pointer<U> pointerU = pointerT.as(U.class);
1350 * }</code><br>
1351 * @param <U> type of the elements pointed by the returned pointer
1352 * @param type type of the elements pointed by the returned pointer
1353 * @return pointer to type U elements at the same address as this pointer
1354 */
1355 public <U> Pointer<U> as(Type type) {
1356 PointerIO<U> pio = PointerIO.getInstance(type);
1357 return as(pio);
1358 }
1359
1360 /**
1361 * Cast this pointer to another pointer type.<br>
1362 * Synonym of {@link Pointer#as(Type)}<br>
1363 * The following C code :<br>
1364 * <code>{@code
1365 * T* pointerT = ...;
1366 * U* pointerU = (U*)pointerT;
1367 * }</code><br>
1368 * Can be translated to the following Java code :<br>
1369 * <code>{@code
1370 * Pointer<T> pointerT = ...;
1371 * Pointer<U> pointerU = pointerT.as(U.class); // or pointerT.as(U.class);
1372 * }</code><br>
1373 * @param <U> type of the elements pointed by the returned pointer
1374 * @param type type of the elements pointed by the returned pointer
1375 * @return pointer to type U elements at the same address as this pointer
1376 */
1377 public <U> Pointer<U> as(Class<U> type) {
1378 return as((Type)type);
1379 }
1380
1381 /**
1382 * Cast this pointer as a function pointer to a function that returns the specified return type and takes the specified parameter types.<br>
1383 * See for instance the following C code that uses a function pointer :
1384 * <pre>{@code
1385 * double (*ptr)(int, const char*) = someAddress;
1386 * double result = ptr(10, "hello");
1387 * }</pre>
1388 * Its Java equivalent with BridJ is the following :
1389 * <pre>{@code
1390 * DynamicFunction ptr = someAddress.asDynamicFunction(null, double.class, int.class, Pointer.class);
1391 * double result = (Double)ptr.apply(10, pointerToCString("hello"));
1392 * }</pre>
1393 * Also see {@link CRuntime#getDynamicFunctionFactory(org.bridj.NativeLibrary, org.bridj.ann.Convention.Style, java.lang.reflect.Type, java.lang.reflect.Type[]) } for more options.
1394 * @param callingConvention calling convention used by the function (if null, default is typically {@link org.bridj.ann.Convention.Style#CDecl})
1395 * @param returnType return type of the function
1396 * @param parameterTypes parameter types of the function
1397 */
1398 public <R> DynamicFunction<R> asDynamicFunction(org.bridj.ann.Convention.Style callingConvention, Type returnType, Type... parameterTypes) {
1399 return CRuntime.getInstance().getDynamicFunctionFactory(null, callingConvention, returnType, parameterTypes).newInstance(this);
1400 }
1401
1402 /**
1403 * Cast this pointer to an untyped pointer.<br>
1404 * Synonym of {@code ptr.as((Class<?>)null)}.<br>
1405 * See {@link Pointer#as(Class)}<br>
1406 * The following C code :<br>
1407 * <code>{@code
1408 * T* pointerT = ...;
1409 * void* pointer = (void*)pointerT;
1410 * }</code><br>
1411 * Can be translated to the following Java code :<br>
1412 * <code>{@code
1413 * Pointer<T> pointerT = ...;
1414 * Pointer<?> pointer = pointerT.asUntyped(); // or pointerT.as((Class<?>)null);
1415 * }</code><br>
1416 * @return untyped pointer pointing to the same address as this pointer
1417 */
1418 public Pointer<?> asUntyped() {
1419 return as((Class<?>)null);
1420 }
1421
1422 /**
1423 * Get the amount of memory known to be valid from this pointer, or -1 if it is unknown.<br>
1424 * Memory validity information is available when the pointer was allocated by BridJ (with {@link Pointer#allocateBytes(long)}, for instance), created out of another pointer which memory validity information is available (with {@link Pointer#offset(long)}, {@link Pointer#next()}, {@link Pointer#next(long)}) or created from a direct NIO buffer ({@link Pointer#pointerToBuffer(Buffer)}, {@link Pointer#pointerToInts(IntBuffer)}...)
1425 * @return amount of bytes that can be safely read or written from this pointer, or -1 if this amount is unknown
1426 */
1427 public long getValidBytes() {
1428 long ve = getValidEnd();
1429 return ve == UNKNOWN_VALIDITY ? -1 : ve - getPeer();
1430 }
1431
1432 /**
1433 * Get the amount of memory known to be valid from this pointer (expressed in elements of the target type, see {@link Pointer#getTargetType()}) or -1 if it is unknown.<br>
1434 * Memory validity information is available when the pointer was allocated by BridJ (with {@link Pointer#allocateBytes(long)}, for instance), created out of another pointer which memory validity information is available (with {@link Pointer#offset(long)}, {@link Pointer#next()}, {@link Pointer#next(long)}) or created from a direct NIO buffer ({@link Pointer#pointerToBuffer(Buffer)}, {@link Pointer#pointerToInts(IntBuffer)}...)
1435 * @return amount of elements that can be safely read or written from this pointer, or -1 if this amount is unknown
1436 */
1437 public long getValidElements() {
1438 long bytes = getValidBytes();
1439 long elementSize = getTargetSize();
1440 if (bytes < 0 || elementSize <= 0)
1441 return -1;
1442 return bytes / elementSize;
1443 }
1444
1445 /**
1446 * Returns an iterator over the elements pointed by this pointer.<br>
1447 * If this pointer was allocated from Java with the allocateXXX, pointerToXXX methods (or is a view or a clone of such a pointer), the iteration is safely bounded.<br>
1448 * If this iterator is just a wrapper for a native-allocated pointer (or a view / clone of such a pointer), iteration will go forever (until illegal areas of memory are reached and cause a JVM crash).
1449 */
1450 public ListIterator<T> iterator() {
1451 return new ListIterator<T>() {
1452 Pointer<T> next = Pointer.this.getValidElements() != 0 ? Pointer.this : null;
1453 Pointer<T> previous;
1454 //@Override
1455 public T next() {
1456 if (next == null)
1457 throw new NoSuchElementException();
1458 T value = next.get();
1459 previous = next;
1460 long valid = next.getValidElements();
1461 next = valid < 0 || valid > 1 ? next.next(1) : null;
1462 return value;
1463 }
1464 //@Override
1465 public void remove() {
1466 throw new UnsupportedOperationException();
1467 }
1468 //@Override
1469 public boolean hasNext() {
1470 long rem;
1471 return next != null && ((rem = next.getValidBytes()) < 0 || rem > 0);
1472 }
1473 //@Override
1474 public void add(T o) {
1475 throw new UnsupportedOperationException();
1476 }
1477 //@Override
1478 public boolean hasPrevious() {
1479 return previous != null;
1480 }
1481 //@Override
1482 public int nextIndex() {
1483 throw new UnsupportedOperationException();
1484 }
1485 //@Override
1486 public T previous() {
1487 //TODO return previous;
1488 throw new UnsupportedOperationException();
1489 }
1490 //@Override
1491 public int previousIndex() {
1492 throw new UnsupportedOperationException();
1493 }
1494 //@Override
1495 public void set(T o) {
1496 if (previous == null)
1497 throw new NoSuchElementException("You haven't called next() prior to calling ListIterator.set(E)");
1498 previous.set(o);
1499 }
1500 };
1501 }
1502
1503
1504 /**
1505 * Get a pointer to a native object (C++ or ObjectiveC class, struct, union, callback...)
1506 */
1507 public static <N extends NativeObject> Pointer<N> pointerTo(N instance) {
1508 return pointerTo(instance, null);
1509 }
1510 /**
1511 * Get a pointer to a native object (C++ or ObjectiveC class, struct, union, callback...)
1512 */
1513 public static <N extends NativeObjectInterface> Pointer<N> pointerTo(N instance) {
1514 return (Pointer)pointerTo((NativeObject)instance);
1515 }
1516
1517 /**
1518 * Get a pointer to a native object, specifying the type of the pointer's target.<br>
1519 * In C++, the address of the pointer to an object as its canonical class is not always the same as the address of the pointer to the same object cast to one of its parent classes.
1520 */
1521 public static <R extends NativeObject> Pointer<R> pointerTo(NativeObject instance, Type targetType) {
1522 return instance == null ? null : (Pointer<R>)instance.peer;
1523 }
1524 /**
1525 * Get the address of a native object, specifying the type of the pointer's target (same as {@code pointerTo(instance, targetType).getPeer()}, see {@link Pointer#pointerTo(NativeObject, Type)}).<br>
1526 * In C++, the address of the pointer to an object as its canonical class is not always the same as the address of the pointer to the same object cast to one of its parent classes.
1527 */
1528 public static long getAddress(NativeObject instance, Class targetType) {
1529 return getPeer(pointerTo(instance, targetType));
1530 }
1531
1532 /**
1533 * Read a native object value from the pointed memory location shifted by a byte offset
1534 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#getNativeObject(Type)} over this method.
1535 */
1536 public <O extends NativeObject> O getNativeObjectAtOffset(long byteOffset, Type type) {
1537 return (O)BridJ.createNativeObjectFromPointer((Pointer<O>)(byteOffset == 0 ? this : offset(byteOffset)), type);
1538 }
1539 /**
1540 * Write a native object value to the pointed memory location
1541 */
1542 public <O extends NativeObject> Pointer<T> setNativeObject(O value, Type type) {
1543 BridJ.copyNativeObjectToAddress(value, type, (Pointer)this);
1544 return this;
1545 }
1546 /**
1547 * Read a native object value from the pointed memory location shifted by a byte offset
1548 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#getNativeObject(Class)} over this method.
1549 */
1550 public <O extends NativeObject> O getNativeObjectAtOffset(long byteOffset, Class<O> type) {
1551 return (O)getNativeObjectAtOffset(byteOffset, (Type)type);
1552 }
1553 /**
1554 * Read a native object value from the pointed memory location
1555 */
1556 public <O extends NativeObject> O getNativeObject(Class<O> type) {
1557 return (O)getNativeObject((Type)type);
1558 }
1559 /**
1560 * Read a native object value from the pointed memory location
1561 */
1562 public <O extends NativeObject> O getNativeObject(Type type) {
1563 O o = (O)getNativeObjectAtOffset(0, type);
1564 return o;
1565 }
1566
1567 /**
1568 * Check that the pointer's peer is aligned to the target type alignment.
1569 * @throws RuntimeException If the target type of this pointer is unknown
1570 * @return getPeer() % alignment == 0
1571 */
1572 public boolean isAligned() {
1573 return isAligned(getIO("Cannot check alignment").getTargetAlignment());
1574 }
1575
1576 /**
1577 * Check that the pointer's peer is aligned to the given alignment.
1578 * If the pointer has no peer, this method returns true.
1579 * @return getPeer() % alignment == 0
1580 */
1581 public boolean isAligned(long alignment) {
1582 return isAligned(getPeer(), alignment);
1583 }
1584
1585 /**
1586 * Check that the provided address is aligned to the given alignment.
1587 * @return address % alignment == 0
1588 */
1589 protected static boolean isAligned(long address, long alignment) {
1590 return computeRemainder(address, alignment) == 0;
1591 }
1592
1593 protected static int computeRemainder(long address, long alignment) {
1594 switch ((int)alignment) {
1595 case -1:
1596 case 0:
1597 case 1:
1598 return 0;
1599 case 2:
1600 return (int)(address & 1);
1601 case 4:
1602 return (int)(address & 3);
1603 case 8:
1604 return (int)(address & 7);
1605 case 16:
1606 return (int)(address & 15);
1607 case 32:
1608 return (int)(address & 31);
1609 case 64:
1610 return (int)(address & 63);
1611 default:
1612 if (alignment < 0)
1613 return 0;
1614 return (int)(address % alignment);
1615 }
1616 }
1617
1618 /**
1619 * Dereference this pointer (*ptr).<br>
1620 Take the following C++ code fragment :
1621 <pre>{@code
1622 int* array = new int[10];
1623 for (int index = 0; index < 10; index++, array++)
1624 printf("%i\n", *array);
1625 }</pre>
1626 Here is its equivalent in Java :
1627 <pre>{@code
1628 import static org.bridj.Pointer.*;
1629 ...
1630 Pointer<Integer> array = allocateInts(10);
1631 for (int index = 0; index < 10; index++) {
1632 System.out.println("%i\n".format(array.get()));
1633 array = array.next();
1634 }
1635 }</pre>
1636 Here is a simpler equivalent in Java :
1637 <pre>{@code
1638 import static org.bridj.Pointer.*;
1639 ...
1640 Pointer<Integer> array = allocateInts(10);
1641 for (int value : array) // array knows its size, so we can iterate on it
1642 System.out.println("%i\n".format(value));
1643 }</pre>
1644 @throws RuntimeException if called on an untyped {@code Pointer<?>} instance (see {@link Pointer#getTargetType()})
1645 */
1646 public T get() {
1647 return get(0);
1648 }
1649
1650 /**
1651 * Returns null if pointer is null, otherwise dereferences the pointer (calls pointer.get()).
1652 */
1653 public static <T> T get(Pointer<T> pointer) {
1654 return pointer == null ? null : pointer.get();
1655 }
1656
1657 /**
1658 Gets the n-th element from this pointer.<br>
1659 This is equivalent to the C/C++ square bracket syntax.<br>
1660 Take the following C++ code fragment :
1661 <pre>{@code
1662 int* array = new int[10];
1663 int index = 5;
1664 int value = array[index];
1665 }</pre>
1666 Here is its equivalent in Java :
1667 <pre>{@code
1668 import static org.bridj.Pointer.*;
1669 ...
1670 Pointer<Integer> array = allocateInts(10);
1671 int index = 5;
1672 int value = array.get(index);
1673 }</pre>
1674 @param index offset in pointed elements at which the value should be copied. Can be negative if the pointer was offset and the memory before it is valid.
1675 @throws RuntimeException if called on an untyped {@code Pointer<?>} instance ({@link Pointer#getTargetType()})
1676 */
1677 public T get(long index) {
1678 return getIO("Cannot get pointed value").get(this, index);
1679 }
1680
1681 /**
1682 Assign a value to the pointed memory location, and return it (different behaviour from {@link List#set(int, Object)} which returns the old value of that element !!!).<br>
1683 Take the following C++ code fragment :
1684 <pre>{@code
1685 int* array = new int[10];
1686 for (int index = 0; index < 10; index++, array++) {
1687 int value = index;
1688 *array = value;
1689 }
1690 }</pre>
1691 Here is its equivalent in Java :
1692 <pre>{@code
1693 import static org.bridj.Pointer.*;
1694 ...
1695 Pointer<Integer> array = allocateInts(10);
1696 for (int index = 0; index < 10; index++) {
1697 int value = index;
1698 array.set(value);
1699 array = array.next();
1700 }
1701 }</pre>
1702 @throws RuntimeException if called on a raw and untyped {@code Pointer} instance (see {@link Pointer#asUntyped()} and {@link Pointer#getTargetType()})
1703 @return The value that was given (not the old value as in {@link List#set(int, Object)} !!!)
1704 */
1705 public T set(T value) {
1706 return set(0, value);
1707 }
1708
1709 private static long getTargetSizeToAllocateArrayOrThrow(PointerIO<?> io) {
1710 long targetSize = -1;
1711 if (io == null || (targetSize = io.getTargetSize()) < 0)
1712 throwBecauseUntyped("Cannot allocate array ");
1713 return targetSize;
1714 }
1715
1716 private static void throwBecauseUntyped(String message) {
1717 throw new RuntimeException("Pointer is not typed (call Pointer.as(Type) to create a typed pointer) : " + message);
1718 }
1719 static void throwUnexpected(Throwable ex) {
1720 throw new RuntimeException("Unexpected error", ex);
1721 }
1722 /**
1723 Sets the n-th element from this pointer, and return it (different behaviour from {@link List#set(int, Object)} which returns the old value of that element !!!).<br>
1724 This is equivalent to the C/C++ square bracket assignment syntax.<br>
1725 Take the following C++ code fragment :
1726 <pre>{@code
1727 float* array = new float[10];
1728 int index = 5;
1729 float value = 12;
1730 array[index] = value;
1731 }</pre>
1732 Here is its equivalent in Java :
1733 <pre>{@code
1734 import static org.bridj.Pointer.*;
1735 ...
1736 Pointer<Float> array = allocateFloats(10);
1737 int index = 5;
1738 float value = 12;
1739 array.set(index, value);
1740 }</pre>
1741 @param index offset in pointed elements at which the value should be copied. Can be negative if the pointer was offset and the memory before it is valid.
1742 @param value value to set at pointed memory location
1743 @throws RuntimeException if called on a raw and untyped {@code Pointer} instance (see {@link Pointer#asUntyped()} and {@link Pointer#getTargetType()})
1744 @return The value that was given (not the old value as in {@link List#set(int, Object)} !!!)
1745 */
1746 public T set(long index, T value) {
1747 getIO("Cannot set pointed value").set(this, index, value);
1748 return value;
1749 }
1750
1751 /**
1752 * Get a pointer's peer (see {@link Pointer#getPeer}), or zero if the pointer is null.
1753 */
1754 public static long getPeer(Pointer<?> pointer) {
1755 return pointer == null ? 0 : pointer.getPeer();
1756 }
1757
1758 /**
1759 * Get the unitary size of the pointed elements in bytes.
1760 * @throws RuntimeException if the target type is unknown (see {@link Pointer#getTargetType()})
1761 */
1762 public long getTargetSize() {
1763 return getIO("Cannot compute target size").getTargetSize();
1764 }
1765
1766 /**
1767 * Returns a pointer to the next target.
1768 * Same as incrementing a C pointer of delta elements, but creates a new pointer instance.
1769 * @return next(1)
1770 */
1771 public Pointer<T> next() {
1772 return next(1);
1773 }
1774
1775 /**
1776 * Returns a pointer to the n-th next (or previous) target.
1777 * Same as incrementing a C pointer of delta elements, but creates a new pointer instance.
1778 * @return offset(getTargetSize() * delta)
1779 */
1780 public Pointer<T> next(long delta) {
1781 return offset(getIO("Cannot get pointers to next or previous targets").getTargetSize() * delta);
1782 }
1783
1784 /**
1785 * Release pointers, if they're not null (see {@link Pointer#release}).
1786 */
1787 public static void release(Pointer... pointers) {
1788 for (Pointer pointer : pointers)
1789 if (pointer != null)
1790 pointer.release();
1791 }
1792
1793 /**
1794 * Test equality of the pointer using the address.<br>
1795 * @return true if and only if obj is a Pointer instance and {@code obj.getPeer() == this.getPeer() }
1796 */
1797 @Override
1798 public boolean equals(Object obj) {
1799 if (obj == null || !(obj instanceof Pointer))
1800 return false;
1801
1802 Pointer p = (Pointer)obj;
1803 return getPeer() == p.getPeer();
1804 }
1805
1806 /**
1807 * Create a pointer out of a native memory address
1808 * @param peer native memory address that is to be converted to a pointer
1809 * @return a pointer with the provided address : {@code pointer.getPeer() == address }
1810 */
1811 @Deprecated
1812 public static Pointer<?> pointerToAddress(long peer) {
1813 return newPointer(null, peer, true, UNKNOWN_VALIDITY, UNKNOWN_VALIDITY, null, NO_PARENT, null, null);
1814 }
1815
1816 /**
1817 * Create a pointer out of a native memory address
1818 * @param size number of bytes known to be readable at the pointed address
1819 * @param peer native memory address that is to be converted to a pointer
1820 * @return a pointer with the provided address : {@code pointer.getPeer() == peer }
1821 */
1822 @Deprecated
1823 public static Pointer<?> pointerToAddress(long peer, long size) {
1824 return newPointer(null, peer, true, peer, peer + size, null, NO_PARENT, null, null);
1825 }
1826
1827 /**
1828 * Create a pointer out of a native memory address
1829 * @param targetClass type of the elements pointed by the resulting pointer
1830 * @param releaser object responsible for reclaiming the native memory once whenever the returned pointer is garbage-collected
1831 * @param peer native memory address that is to be converted to a pointer
1832 * @return a pointer with the provided address : {@code pointer.getPeer() == peer }
1833 */
1834 public static <P> Pointer<P> pointerToAddress(long peer, Class<P> targetClass, final Releaser releaser) {
1835 return pointerToAddress(peer, (Type)targetClass, releaser);
1836 }
1837 /**
1838 * Create a pointer out of a native memory address
1839 * @param targetType type of the elements pointed by the resulting pointer
1840 * @param releaser object responsible for reclaiming the native memory once whenever the returned pointer is garbage-collected
1841 * @param peer native memory address that is to be converted to a pointer
1842 * @return a pointer with the provided address : {@code pointer.getPeer() == peer }
1843 */
1844 public static <P> Pointer<P> pointerToAddress(long peer, Type targetType, final Releaser releaser) {
1845 PointerIO<P> pio = PointerIO.getInstance(targetType);
1846 return newPointer(pio, peer, true, UNKNOWN_VALIDITY, UNKNOWN_VALIDITY, null, -1, releaser, null);
1847 }
1848 /**
1849 * Create a pointer out of a native memory address
1850 * @param io PointerIO instance that knows how to read the elements pointed by the resulting pointer
1851 * @param peer native memory address that is to be converted to a pointer
1852 * @return a pointer with the provided address : {@code pointer.getPeer() == peer }
1853 */
1854 public static <P> Pointer<P> pointerToAddress(long peer, PointerIO<P> io) {
1855 return newPointer(io, peer, true, UNKNOWN_VALIDITY, UNKNOWN_VALIDITY, null, NO_PARENT, null, null);
1856 }
1857 /**
1858 * Create a pointer out of a native memory address
1859 * @param io PointerIO instance that knows how to read the elements pointed by the resulting pointer
1860 * @param releaser object responsible for reclaiming the native memory once whenever the returned pointer is garbage-collected
1861 * @param peer native memory address that is to be converted to a pointer
1862 * @return a pointer with the provided address : {@code pointer.getPeer() == peer }
1863 */
1864 static <P> Pointer<P> pointerToAddress(long peer, PointerIO<P> io, Releaser releaser) {
1865 return newPointer(io, peer, true, UNKNOWN_VALIDITY, UNKNOWN_VALIDITY, null, NO_PARENT, releaser, null);
1866 }
1867
1868 /**
1869 * Create a pointer out of a native memory address
1870 * @param releaser object responsible for reclaiming the native memory once whenever the returned pointer is garbage-collected
1871 * @param peer native memory address that is to be converted to a pointer
1872 * @return a pointer with the provided address : {@code pointer.getPeer() == peer }
1873 */
1874 @Deprecated
1875 public static Pointer<?> pointerToAddress(long peer, Releaser releaser) {
1876 return newPointer(null, peer, true, UNKNOWN_VALIDITY, UNKNOWN_VALIDITY, null, NO_PARENT, releaser, null);
1877 }
1878
1879 /**
1880 * Create a pointer out of a native memory address
1881 * @param releaser object responsible for reclaiming the native memory once whenever the returned pointer is garbage-collected
1882 * @param size number of bytes known to be readable at the pointed address
1883 * @param peer native memory address that is to be converted to a pointer
1884 * @return a pointer with the provided address : {@code pointer.getPeer() == peer }
1885 */
1886 public static Pointer<?> pointerToAddress(long peer, long size, Releaser releaser) {
1887 return newPointer(null, peer, true, peer, peer + size, null, NO_PARENT, releaser, null);
1888 }
1889
1890 /**
1891 * Create a pointer out of a native memory address
1892 * @param targetClass type of the elements pointed by the resulting pointer
1893 * @param peer native memory address that is to be converted to a pointer
1894 * @return a pointer with the provided address : {@code pointer.getPeer() == peer }
1895 */
1896 @Deprecated
1897 public static <P> Pointer<P> pointerToAddress(long peer, Class<P> targetClass) {
1898 return pointerToAddress(peer, (Type)targetClass);
1899 }
1900
1901 /**
1902 * Create a pointer out of a native memory address
1903 * @param targetType type of the elements pointed by the resulting pointer
1904 * @param peer native memory address that is to be converted to a pointer
1905 * @return a pointer with the provided address : {@code pointer.getPeer() == peer }
1906 */
1907 @Deprecated
1908 public static <P> Pointer<P> pointerToAddress(long peer, Type targetType) {
1909 return newPointer((PointerIO<P>)PointerIO.getInstance(targetType), peer, true, UNKNOWN_VALIDITY, UNKNOWN_VALIDITY, null, -1, null, null);
1910 }
1911
1912 /**
1913 * Create a pointer out of a native memory address
1914 * @param size number of bytes known to be readable at the pointed address
1915 * @param io PointerIO instance that knows how to read the elements pointed by the resulting pointer
1916 * @param peer native memory address that is to be converted to a pointer
1917 * @return a pointer with the provided address : {@code pointer.getPeer() == peer }
1918 */
1919 static <U> Pointer<U> pointerToAddress(long peer, long size, PointerIO<U> io) {
1920 return newPointer(io, peer, true, peer, peer + size, null, NO_PARENT, null, null);
1921 }
1922
1923 /**
1924 * Create a pointer out of a native memory address
1925 * @param releaser object responsible for reclaiming the native memory once whenever the returned pointer is garbage-collected
1926 * @param peer native memory address that is to be converted to a pointer
1927 * @return a pointer with the provided address : {@code pointer.getPeer() == peer }
1928 */
1929 static <U> Pointer<U> newPointer(
1930 PointerIO<U> io,
1931 long peer,
1932 boolean ordered,
1933 long validStart,
1934 long validEnd,
1935 Pointer<?> parent,
1936 long offsetInParent,
1937 final Releaser releaser,
1938 Object sibling)
1939 {
1940 if (peer == 0)
1941 return null;
1942
1943 if (validEnd != UNKNOWN_VALIDITY) {
1944 long size = validEnd - validStart;
1945 if (size <= 0)
1946 return null;
1947 }
1948
1949 if (releaser == null) {
1950 if (ordered) {
1951 return new OrderedPointer<U>(io, peer, validStart, validEnd, parent, offsetInParent, sibling);
1952 } else {
1953 return new DisorderedPointer<U>(io, peer, validStart, validEnd, parent, offsetInParent, sibling);
1954 }
1955 } else {
1956 assert sibling == null;
1957 if (ordered) {
1958 return new OrderedPointer<U>(io, peer, validStart, validEnd, parent, offsetInParent, sibling) {
1959 private volatile Releaser rel = releaser;
1960 //@Override
1961 public synchronized void release() {
1962 if (rel != null) {
1963 Releaser rel = this.rel;
1964 this.rel = null;
1965 rel.release(this);
1966 }
1967 }
1968 protected void finalize() {
1969 release();
1970 }
1971
1972 @Deprecated
1973 public synchronized Pointer<U> withReleaser(final Releaser beforeDeallocation) {
1974 final Releaser thisReleaser = rel;
1975 rel = null;
1976 return newPointer(getIO(), getPeer(), isOrdered(), getValidStart(), getValidEnd(), null, NO_PARENT, beforeDeallocation == null ? thisReleaser : new Releaser() {
1977 //@Override
1978 public void release(Pointer<?> p) {
1979 beforeDeallocation.release(p);
1980 if (thisReleaser != null)
1981 thisReleaser.release(p);
1982 }
1983 }, null);
1984 }
1985 };
1986 } else {
1987 return new DisorderedPointer<U>(io, peer, validStart, validEnd, parent, offsetInParent, sibling) {
1988 private volatile Releaser rel = releaser;
1989 //@Override
1990 public synchronized void release() {
1991 if (rel != null) {
1992 Releaser rel = this.rel;
1993 this.rel = null;
1994 rel.release(this);
1995 }
1996 }
1997 protected void finalize() {
1998 release();
1999 }
2000
2001 @Deprecated
2002 public synchronized Pointer<U> withReleaser(final Releaser beforeDeallocation) {
2003 final Releaser thisReleaser = rel;
2004 rel = null;
2005 return newPointer(getIO(), getPeer(), isOrdered(), getValidStart(), getValidEnd(), null, NO_PARENT, beforeDeallocation == null ? thisReleaser : new Releaser() {
2006 //@Override
2007 public void release(Pointer<?> p) {
2008 beforeDeallocation.release(p);
2009 if (thisReleaser != null)
2010 thisReleaser.release(p);
2011 }
2012 }, null);
2013 }
2014 };
2015 }
2016 }
2017 }
2018
2019 /**
2020 * Allocate enough memory for a typed pointer value and return a pointer to it.<br>
2021 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2022 * @return pointer to a single zero-initialized typed pointer value
2023 */
2024 public static <P extends TypedPointer> Pointer<P> allocateTypedPointer(Class<P> type) {
2025 return (Pointer<P>)(Pointer)allocate(PointerIO.getInstance(type));
2026 }
2027 /**
2028 * Allocate enough memory for arrayLength typed pointer values and return a pointer to that memory.<br>
2029 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2030 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2031 * The returned pointer is also an {@code Iterable<P extends TypedPointer>} instance that can be safely iterated upon.
2032 * @return pointer to arrayLength zero-initialized typed pointer consecutive values
2033 */
2034 public static <P extends TypedPointer> Pointer<P> allocateTypedPointers(Class<P> type, long arrayLength) {
2035 return (Pointer<P>)(Pointer)allocateArray(PointerIO.getInstance(type), arrayLength);
2036 }
2037 /**
2038 * Create a memory area large enough to hold a pointer.
2039 * @param targetType target type of the pointer values to be stored in the allocated memory
2040 * @return a pointer to a new memory area large enough to hold a single typed pointer
2041 */
2042 public static <P> Pointer<Pointer<P>> allocatePointer(Class<P> targetType) {
2043 return allocatePointer((Type)targetType);
2044 }
2045 /**
2046 * Create a memory area large enough to hold a pointer.
2047 * @param targetType target type of the pointer values to be stored in the allocated memory
2048 * @return a pointer to a new memory area large enough to hold a single typed pointer
2049 */
2050 public static <P> Pointer<Pointer<P>> allocatePointer(Type targetType) {
2051 return (Pointer<Pointer<P>>)(Pointer)allocate(PointerIO.getPointerInstance(targetType));
2052 }
2053 /**
2054 * Create a memory area large enough to hold a pointer to a pointer
2055 * @param targetType target type of the values pointed by the pointer values to be stored in the allocated memory
2056 * @return a pointer to a new memory area large enough to hold a single typed pointer
2057 */
2058 public static <P> Pointer<Pointer<Pointer<P>>> allocatePointerPointer(Type targetType) {
2059 return allocatePointer(pointerType(targetType));
2060 }/**
2061 * Create a memory area large enough to hold a pointer to a pointer
2062 * @param targetType target type of the values pointed by the pointer values to be stored in the allocated memory
2063 * @return a pointer to a new memory area large enough to hold a single typed pointer
2064 */
2065 public static <P> Pointer<Pointer<Pointer<P>>> allocatePointerPointer(Class<P> targetType) {
2066 return allocatePointerPointer((Type)targetType);
2067 }
2068 /**
2069 * Allocate enough memory for a untyped pointer value and return a pointer to it.<br>
2070 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2071 * @return pointer to a single zero-initialized untyped pointer value
2072 */
2073 /**
2074 * Create a memory area large enough to hold an untyped pointer.
2075 * @return a pointer to a new memory area large enough to hold a single untyped pointer
2076 */
2077 public static <V> Pointer<Pointer<?>> allocatePointer() {
2078 return (Pointer)allocate(PointerIO.getPointerInstance());
2079 }
2080 /**
2081 * Allocate enough memory for arrayLength untyped pointer values and return a pointer to that memory.<br>
2082 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2083 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2084 * The returned pointer is also an {@code Iterable<Pointer<?>>} instance that can be safely iterated upon.
2085 * @return pointer to arrayLength zero-initialized untyped pointer consecutive values
2086 */
2087 public static Pointer<Pointer<?>> allocatePointers(int arrayLength) {
2088 return (Pointer<Pointer<?>>)(Pointer)allocateArray(PointerIO.getPointerInstance(), arrayLength);
2089 }
2090
2091 /**
2092 * Create a memory area large enough to hold an array of arrayLength typed pointers.
2093 * @param targetType target type of element pointers in the resulting pointer array.
2094 * @param arrayLength size of the allocated array, in elements
2095 * @return a pointer to a new memory area large enough to hold an array of arrayLength typed pointers
2096 */
2097 public static <P> Pointer<Pointer<P>> allocatePointers(Class<P> targetType, int arrayLength) {
2098 return allocatePointers((Type)targetType, arrayLength);
2099 }
2100
2101 /**
2102 * Create a memory area large enough to hold an array of arrayLength typed pointers.
2103 * @param targetType target type of element pointers in the resulting pointer array.
2104 * @param arrayLength size of the allocated array, in elements
2105 * @return a pointer to a new memory area large enough to hold an array of arrayLength typed pointers
2106 */
2107 public static <P> Pointer<Pointer<P>> allocatePointers(Type targetType, int arrayLength) {
2108 return (Pointer<Pointer<P>>)(Pointer)allocateArray(PointerIO.getPointerInstance(targetType), arrayLength); // TODO
2109 }
2110
2111
2112 /**
2113 * Create a memory area large enough to a single items of type elementClass.
2114 * @param elementClass type of the array elements
2115 * @return a pointer to a new memory area large enough to hold a single item of type elementClass.
2116 */
2117 public static <V> Pointer<V> allocate(Class<V> elementClass) {
2118 return allocate((Type)elementClass);
2119 }
2120
2121 /**
2122 * Create a memory area large enough to a single items of type elementClass.
2123 * @param elementClass type of the array elements
2124 * @return a pointer to a new memory area large enough to hold a single item of type elementClass.
2125 */
2126 public static <V> Pointer<V> allocate(Type elementClass) {
2127 return allocateArray(elementClass, 1);
2128 }
2129
2130 /**
2131 * Create a memory area large enough to hold one item of the type associated to the provided PointerIO instance (see {@link PointerIO#getTargetType()})
2132 * @param io PointerIO instance able to store and retrieve the element
2133 * @return a pointer to a new memory area large enough to hold one item of the type associated to the provided PointerIO instance (see {@link PointerIO#getTargetType()})
2134 */
2135 public static <V> Pointer<V> allocate(PointerIO<V> io) {
2136 return allocateBytes(io, getTargetSizeToAllocateArrayOrThrow(io), null);
2137 }
2138 /**
2139 * Create a memory area large enough to hold arrayLength items of the type associated to the provided PointerIO instance (see {@link PointerIO#getTargetType()})
2140 * @param io PointerIO instance able to store and retrieve elements of the array
2141 * @param arrayLength length of the array in elements
2142 * @return a pointer to a new memory area large enough to hold arrayLength items of the type associated to the provided PointerIO instance (see {@link PointerIO#getTargetType()})
2143 */
2144 public static <V> Pointer<V> allocateArray(PointerIO<V> io, long arrayLength) {
2145 return allocateBytes(io, getTargetSizeToAllocateArrayOrThrow(io) * arrayLength, null);
2146 }
2147 /**
2148 * Create a memory area large enough to hold arrayLength items of the type associated to the provided PointerIO instance (see {@link PointerIO#getTargetType()})
2149 * @param io PointerIO instance able to store and retrieve elements of the array
2150 * @param arrayLength length of the array in elements
2151 * @param beforeDeallocation fake releaser that should be run just before the memory is actually released, for instance in order to call some object destructor
2152 * @return a pointer to a new memory area large enough to hold arrayLength items of the type associated to the provided PointerIO instance (see {@link PointerIO#getTargetType()})
2153 */
2154 public static <V> Pointer<V> allocateArray(PointerIO<V> io, long arrayLength, final Releaser beforeDeallocation) {
2155 return allocateBytes(io, getTargetSizeToAllocateArrayOrThrow(io) * arrayLength, beforeDeallocation);
2156 }
2157 /**
2158 * Create a memory area large enough to hold byteSize consecutive bytes and return a pointer to elements of the type associated to the provided PointerIO instance (see {@link PointerIO#getTargetType()})
2159 * @param io PointerIO instance able to store and retrieve elements of the array
2160 * @param byteSize length of the array in bytes
2161 * @param beforeDeallocation fake releaser that should be run just before the memory is actually released, for instance in order to call some object destructor
2162 * @return a pointer to a new memory area large enough to hold byteSize consecutive bytes
2163 */
2164 public static <V> Pointer<V> allocateBytes(PointerIO<V> io, long byteSize, final Releaser beforeDeallocation) {
2165 return allocateAlignedBytes(io, byteSize, defaultAlignment, beforeDeallocation);
2166 }
2167
2168 /**
2169 * Create a memory area large enough to hold byteSize consecutive bytes and return a pointer to elements of the type associated to the provided PointerIO instance (see {@link PointerIO#getTargetType()}), ensuring the pointer to the memory is aligned to the provided boundary.
2170 * @param io PointerIO instance able to store and retrieve elements of the array
2171 * @param byteSize length of the array in bytes
2172 * @param alignment boundary to which the returned pointer should be aligned
2173 * @param beforeDeallocation fake releaser that should be run just before the memory is actually released, for instance in order to call some object destructor
2174 * @return a pointer to a new memory area large enough to hold byteSize consecutive bytes
2175 */
2176 public static <V> Pointer<V> allocateAlignedBytes(PointerIO<V> io, long byteSize, int alignment, final Releaser beforeDeallocation) {
2177 if (byteSize == 0)
2178 return null;
2179 if (byteSize < 0)
2180 throw new IllegalArgumentException("Cannot allocate a negative amount of memory !");
2181
2182 long address, offset = 0;
2183 if (alignment <= 1)
2184 address = JNI.mallocNulled(byteSize);
2185 else {
2186 //address = JNI.mallocNulledAligned(byteSize, alignment);
2187 //if (address == 0)
2188 {
2189 // invalid alignment (< sizeof(void*) or not a power of 2
2190 address = JNI.mallocNulled(byteSize + alignment - 1);
2191 long remainder = address % alignment;
2192 if (remainder > 0)
2193 offset = alignment - remainder;
2194 }
2195 }
2196
2197 if (address == 0)
2198 throw new RuntimeException("Failed to allocate " + byteSize);
2199
2200 Pointer<V> ptr = newPointer(io, address, true, address, address + byteSize + offset, null, NO_PARENT, beforeDeallocation == null ? freeReleaser : new Releaser() {
2201 //@Override
2202 public void release(Pointer<?> p) {
2203 beforeDeallocation.release(p);
2204 freeReleaser.release(p);
2205 }
2206 }, null);
2207
2208 if (offset > 0)
2209 ptr = ptr.offset(offset);
2210
2211 return ptr;
2212 }
2213
2214 /**
2215 * Create a pointer that depends on this pointer and will call a releaser prior to release this pointer, when it is GC'd.<br>
2216 * This pointer MUST NOT be used anymore.
2217 * @deprecated This method can easily be misused and is reserved to advanced users.
2218 * @param beforeDeallocation releaser that should be run before this pointer's releaser (if any).
2219 * @return a new pointer to the same memory location as this pointer
2220 */
2221 @Deprecated
2222 public synchronized Pointer<T> withReleaser(final Releaser beforeDeallocation) {
2223 return newPointer(getIO(), getPeer(), isOrdered(), getValidStart(), getValidEnd(), null, NO_PARENT, beforeDeallocation, null);
2224 }
2225 static Releaser freeReleaser = new FreeReleaser();
2226 static class FreeReleaser implements Releaser {
2227 //@Override
2228 public void release(Pointer<?> p) {
2229 assert p.getSibling() == null;
2230 assert p.validStart == p.getPeer();
2231
2232 if (BridJ.debugPointers)
2233 BridJ.info("Freeing pointer " + p + "\n(Creation trace = \n\t" + Utils.toString(p.creationTrace).replaceAll("\n", "\n\t") + "\n)", new RuntimeException().fillInStackTrace());
2234
2235 if (!BridJ.debugNeverFree)
2236 JNI.free(p.getPeer());
2237 }
2238 }
2239
2240 /**
2241 * Create a memory area large enough to hold arrayLength items of type elementClass.
2242 * @param elementClass type of the array elements
2243 * @param arrayLength length of the array in elements
2244 * @return a pointer to a new memory area large enough to hold arrayLength items of type elementClass.
2245 */
2246 public static <V> Pointer<V> allocateArray(Class<V> elementClass, long arrayLength) {
2247 return allocateArray((Type)elementClass, arrayLength);
2248 }
2249 /**
2250 * Create a memory area large enough to hold arrayLength items of type elementClass.
2251 * @param elementClass type of the array elements
2252 * @param arrayLength length of the array in elements
2253 * @return a pointer to a new memory area large enough to hold arrayLength items of type elementClass.
2254 */
2255 public static <V> Pointer<V> allocateArray(Type elementClass, long arrayLength) {
2256 if (arrayLength == 0)
2257 return null;
2258
2259 PointerIO pio = PointerIO.getInstance(elementClass);
2260 if (pio == null)
2261 throw new UnsupportedOperationException("Cannot allocate memory for type " + (elementClass instanceof Class ? ((Class)elementClass).getName() : elementClass.toString()));
2262 return (Pointer<V>)allocateArray(pio, arrayLength);
2263 }
2264
2265
2266 /**
2267 * Create a memory area large enough to hold arrayLength items of type elementClass, ensuring the pointer to the memory is aligned to the provided boundary.
2268 * @param elementClass type of the array elements
2269 * @param arrayLength length of the array in elements
2270 * @param alignment boundary to which the returned pointer should be aligned
2271 * @return a pointer to a new memory area large enough to hold arrayLength items of type elementClass.
2272 */
2273 public static <V> Pointer<V> allocateAlignedArray(Class<V> elementClass, long arrayLength, int alignment) {
2274 return allocateAlignedArray((Type)elementClass, arrayLength, alignment);
2275 }
2276
2277 /**
2278 * Create a memory area large enough to hold arrayLength items of type elementClass, ensuring the pointer to the memory is aligned to the provided boundary.
2279 * @param elementClass type of the array elements
2280 * @param arrayLength length of the array in elements
2281 * @param alignment boundary to which the returned pointer should be aligned
2282 * @return a pointer to a new memory area large enough to hold arrayLength items of type elementClass.
2283 */
2284 public static <V> Pointer<V> allocateAlignedArray(Type elementClass, long arrayLength, int alignment) {
2285 PointerIO io = PointerIO.getInstance(elementClass);
2286 if (io == null)
2287 throw new UnsupportedOperationException("Cannot allocate memory for type " + (elementClass instanceof Class ? ((Class)elementClass).getName() : elementClass.toString()));
2288 return allocateAlignedBytes(io, getTargetSizeToAllocateArrayOrThrow(io) * arrayLength, alignment, null);
2289 }
2290
2291 /**
2292 * Create a pointer to the memory location used by a direct NIO buffer.<br>
2293 * If the NIO buffer is not direct, then its backing Java array is copied to some native memory and will never be updated by changes to the native memory (calls {@link Pointer#pointerToArray(Object)}), unless a call to {@link Pointer#updateBuffer(Buffer)} is made manually.<br>
2294 * The returned pointer (and its subsequent views returned by {@link Pointer#offset(long)} or {@link Pointer#next(long)}) can be used safely : it retains a reference to the original NIO buffer, so that this latter cannot be garbage collected before the pointer.
2295 */
2296 public static Pointer<?> pointerToBuffer(Buffer buffer) {
2297 if (buffer == null)
2298 return null;
2299
2300 if (buffer instanceof IntBuffer)
2301 return (Pointer)pointerToInts((IntBuffer)buffer);
2302 if (buffer instanceof LongBuffer)
2303 return (Pointer)pointerToLongs((LongBuffer)buffer);
2304 if (buffer instanceof ShortBuffer)
2305 return (Pointer)pointerToShorts((ShortBuffer)buffer);
2306 if (buffer instanceof ByteBuffer)
2307 return (Pointer)pointerToBytes((ByteBuffer)buffer);
2308 if (buffer instanceof CharBuffer)
2309 return (Pointer)pointerToChars((CharBuffer)buffer);
2310 if (buffer instanceof FloatBuffer)
2311 return (Pointer)pointerToFloats((FloatBuffer)buffer);
2312 if (buffer instanceof DoubleBuffer)
2313 return (Pointer)pointerToDoubles((DoubleBuffer)buffer);
2314 throw new UnsupportedOperationException("Unhandled buffer type : " + buffer.getClass().getName());
2315 }
2316
2317 /**
2318 * When a pointer was created with {@link Pointer#pointerToBuffer(Buffer)} on a non-direct buffer, a native copy of the buffer data was made.
2319 * This method updates the original buffer with the native memory, and does nothing if the buffer is direct <b>and</b> points to the same memory location as this pointer.<br>
2320 * @throws IllegalArgumentException if buffer is direct and does not point to the exact same location as this Pointer instance
2321 */
2322 public void updateBuffer(Buffer buffer) {
2323 if (buffer == null)
2324 throw new IllegalArgumentException("Cannot update a null Buffer !");
2325
2326 if (Utils.isDirect(buffer)) {
2327 long address = JNI.getDirectBufferAddress(buffer);
2328 if (address != getPeer()) {
2329 throw new IllegalArgumentException("Direct buffer does not point to the same location as this Pointer instance, updating it makes no sense !");
2330 }
2331 } else {
2332 if (buffer instanceof IntBuffer) {
2333 ((IntBuffer)buffer).duplicate().put(getIntBuffer());
2334 return;
2335 }
2336 if (buffer instanceof LongBuffer) {
2337 ((LongBuffer)buffer).duplicate().put(getLongBuffer());
2338 return;
2339 }
2340 if (buffer instanceof ShortBuffer) {
2341 ((ShortBuffer)buffer).duplicate().put(getShortBuffer());
2342 return;
2343 }
2344 if (buffer instanceof ByteBuffer) {
2345 ((ByteBuffer)buffer).duplicate().put(getByteBuffer());
2346 return;
2347 }
2348 if (buffer instanceof FloatBuffer) {
2349 ((FloatBuffer)buffer).duplicate().put(getFloatBuffer());
2350 return;
2351 }
2352 if (buffer instanceof DoubleBuffer) {
2353 ((DoubleBuffer)buffer).duplicate().put(getDoubleBuffer());
2354 return;
2355 }
2356 throw new UnsupportedOperationException("Unhandled buffer type : " + buffer.getClass().getName());
2357 }
2358 }
2359
2360
2361 //-- primitive: int --
2362
2363 /**
2364 * Allocate enough memory for a single int value, copy the value provided in argument into it and return a pointer to that memory.<br>
2365 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2366 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2367 * @param value initial value for the created memory location
2368 * @return pointer to a new memory location that initially contains the int value given in argument
2369 */
2370 public static Pointer<Integer> pointerToInt(int value) {
2371 Pointer<Integer> mem = allocate(PointerIO.getIntInstance());
2372 mem.setInt(value);
2373 return mem;
2374 }
2375
2376 /**
2377 * Allocate enough memory for values.length int values, copy the values provided as argument into it and return a pointer to that memory.<br>
2378 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2379 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2380 * The returned pointer is also an {@code Iterable<Integer>} instance that can be safely iterated upon :
2381 <pre>{@code
2382 for (float f : pointerTo(1f, 2f, 3.3f))
2383 System.out.println(f); }</pre>
2384 * @param values initial values for the created memory location
2385 * @return pointer to a new memory location that initially contains the int consecutive values provided in argument
2386 */
2387 public static Pointer<Integer> pointerToInts(int... values) {
2388 if (values == null)
2389 return null;
2390 Pointer<Integer> mem = allocateArray(PointerIO.getIntInstance(), values.length);
2391 mem.setIntsAtOffset(0, values, 0, values.length);
2392 return mem;
2393 }
2394
2395 /**
2396 * Allocate enough memory for all the values in the 2D int array, copy the values provided as argument into it as packed multi-dimensional C array and return a pointer to that memory.<br>
2397 * Assumes that all of the subarrays of the provided array are non null and have the same size.<br>
2398 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2399 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2400 * @param values initial values for the created memory location
2401 * @return pointer to a new memory location that initially contains the int values provided in argument packed as a 2D C array would be
2402 */
2403 public static Pointer<Pointer<Integer>> pointerToInts(int[][] values) {
2404 if (values == null)
2405 return null;
2406 int dim1 = values.length, dim2 = values[0].length;
2407 Pointer<Pointer<Integer>> mem = allocateInts(dim1, dim2);
2408 for (int i1 = 0; i1 < dim1; i1++)
2409 mem.setIntsAtOffset(i1 * dim2 * 4, values[i1], 0, dim2);
2410 return mem;
2411 }
2412
2413 /**
2414 * Allocate enough memory for all the values in the 3D int array, copy the values provided as argument into it as packed multi-dimensional C array and return a pointer to that memory.<br>
2415 * Assumes that all of the subarrays of the provided array are non null and have the same size.<br>
2416 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2417 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2418 * @param values initial values for the created memory location
2419 * @return pointer to a new memory location that initially contains the int values provided in argument packed as a 3D C array would be
2420 */
2421 public static Pointer<Pointer<Pointer<Integer>>> pointerToInts(int[][][] values) {
2422 if (values == null)
2423 return null;
2424 int dim1 = values.length, dim2 = values[0].length, dim3 = values[0][0].length;
2425 Pointer<Pointer<Pointer<Integer>>> mem = allocateInts(dim1, dim2, dim3);
2426 for (int i1 = 0; i1 < dim1; i1++) {
2427 int offset1 = i1 * dim2;
2428 for (int i2 = 0; i2 < dim2; i2++) {
2429 int offset2 = (offset1 + i2) * dim3;
2430 mem.setIntsAtOffset(offset2 * 4, values[i1][i2], 0, dim3);
2431 }
2432 }
2433 return mem;
2434 }
2435
2436 /**
2437 * Allocate enough memory for a int value and return a pointer to it.<br>
2438 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2439 * @return pointer to a single zero-initialized int value
2440 */
2441 public static Pointer<Integer> allocateInt() {
2442 return allocate(PointerIO.getIntInstance());
2443 }
2444 /**
2445 * Allocate enough memory for arrayLength int values and return a pointer to that memory.<br>
2446 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2447 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2448 * The returned pointer is also an {@code Iterable<Integer>} instance that can be safely iterated upon.
2449 * @return pointer to arrayLength zero-initialized int consecutive values
2450 */
2451 public static Pointer<Integer> allocateInts(long arrayLength) {
2452 return allocateArray(PointerIO.getIntInstance(), arrayLength);
2453 }
2454
2455 /**
2456 * Allocate enough memory for dim1 * dim2 int values in a packed multi-dimensional C array and return a pointer to that memory.<br>
2457 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2458 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2459 * @return pointer to dim1 * dim2 zero-initialized int consecutive values
2460 */
2461 public static Pointer<Pointer<Integer>> allocateInts(long dim1, long dim2) {
2462 return allocateArray(PointerIO.getArrayInstance(PointerIO.getIntInstance(), new long[] { dim1, dim2 }, 0), dim1);
2463
2464 }
2465 /**
2466 * Allocate enough memory for dim1 * dim2 * dim3 int values in a packed multi-dimensional C array and return a pointer to that memory.<br>
2467 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2468 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2469 * @return pointer to dim1 * dim2 * dim3 zero-initialized int consecutive values
2470 */
2471 public static Pointer<Pointer<Pointer<Integer>>> allocateInts(long dim1, long dim2, long dim3) {
2472 long[] dims = new long[] { dim1, dim2, dim3 };
2473 return
2474 allocateArray(
2475 PointerIO.getArrayInstance(
2476 //PointerIO.getIntInstance(),
2477 PointerIO.getArrayInstance(
2478 PointerIO.getIntInstance(),
2479 dims,
2480 1
2481 ),
2482 dims,
2483 0
2484 ),
2485 dim1
2486 )
2487 ;
2488 }
2489
2490
2491 //-- primitive: long --
2492
2493 /**
2494 * Allocate enough memory for a single long value, copy the value provided in argument into it and return a pointer to that memory.<br>
2495 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2496 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2497 * @param value initial value for the created memory location
2498 * @return pointer to a new memory location that initially contains the long value given in argument
2499 */
2500 public static Pointer<Long> pointerToLong(long value) {
2501 Pointer<Long> mem = allocate(PointerIO.getLongInstance());
2502 mem.setLong(value);
2503 return mem;
2504 }
2505
2506 /**
2507 * Allocate enough memory for values.length long values, copy the values provided as argument into it and return a pointer to that memory.<br>
2508 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2509 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2510 * The returned pointer is also an {@code Iterable<Long>} instance that can be safely iterated upon :
2511 <pre>{@code
2512 for (float f : pointerTo(1f, 2f, 3.3f))
2513 System.out.println(f); }</pre>
2514 * @param values initial values for the created memory location
2515 * @return pointer to a new memory location that initially contains the long consecutive values provided in argument
2516 */
2517 public static Pointer<Long> pointerToLongs(long... values) {
2518 if (values == null)
2519 return null;
2520 Pointer<Long> mem = allocateArray(PointerIO.getLongInstance(), values.length);
2521 mem.setLongsAtOffset(0, values, 0, values.length);
2522 return mem;
2523 }
2524
2525 /**
2526 * Allocate enough memory for all the values in the 2D long array, copy the values provided as argument into it as packed multi-dimensional C array and return a pointer to that memory.<br>
2527 * Assumes that all of the subarrays of the provided array are non null and have the same size.<br>
2528 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2529 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2530 * @param values initial values for the created memory location
2531 * @return pointer to a new memory location that initially contains the long values provided in argument packed as a 2D C array would be
2532 */
2533 public static Pointer<Pointer<Long>> pointerToLongs(long[][] values) {
2534 if (values == null)
2535 return null;
2536 int dim1 = values.length, dim2 = values[0].length;
2537 Pointer<Pointer<Long>> mem = allocateLongs(dim1, dim2);
2538 for (int i1 = 0; i1 < dim1; i1++)
2539 mem.setLongsAtOffset(i1 * dim2 * 8, values[i1], 0, dim2);
2540 return mem;
2541 }
2542
2543 /**
2544 * Allocate enough memory for all the values in the 3D long array, copy the values provided as argument into it as packed multi-dimensional C array and return a pointer to that memory.<br>
2545 * Assumes that all of the subarrays of the provided array are non null and have the same size.<br>
2546 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2547 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2548 * @param values initial values for the created memory location
2549 * @return pointer to a new memory location that initially contains the long values provided in argument packed as a 3D C array would be
2550 */
2551 public static Pointer<Pointer<Pointer<Long>>> pointerToLongs(long[][][] values) {
2552 if (values == null)
2553 return null;
2554 int dim1 = values.length, dim2 = values[0].length, dim3 = values[0][0].length;
2555 Pointer<Pointer<Pointer<Long>>> mem = allocateLongs(dim1, dim2, dim3);
2556 for (int i1 = 0; i1 < dim1; i1++) {
2557 int offset1 = i1 * dim2;
2558 for (int i2 = 0; i2 < dim2; i2++) {
2559 int offset2 = (offset1 + i2) * dim3;
2560 mem.setLongsAtOffset(offset2 * 8, values[i1][i2], 0, dim3);
2561 }
2562 }
2563 return mem;
2564 }
2565
2566 /**
2567 * Allocate enough memory for a long value and return a pointer to it.<br>
2568 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2569 * @return pointer to a single zero-initialized long value
2570 */
2571 public static Pointer<Long> allocateLong() {
2572 return allocate(PointerIO.getLongInstance());
2573 }
2574 /**
2575 * Allocate enough memory for arrayLength long values and return a pointer to that memory.<br>
2576 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2577 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2578 * The returned pointer is also an {@code Iterable<Long>} instance that can be safely iterated upon.
2579 * @return pointer to arrayLength zero-initialized long consecutive values
2580 */
2581 public static Pointer<Long> allocateLongs(long arrayLength) {
2582 return allocateArray(PointerIO.getLongInstance(), arrayLength);
2583 }
2584
2585 /**
2586 * Allocate enough memory for dim1 * dim2 long values in a packed multi-dimensional C array and return a pointer to that memory.<br>
2587 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2588 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2589 * @return pointer to dim1 * dim2 zero-initialized long consecutive values
2590 */
2591 public static Pointer<Pointer<Long>> allocateLongs(long dim1, long dim2) {
2592 return allocateArray(PointerIO.getArrayInstance(PointerIO.getLongInstance(), new long[] { dim1, dim2 }, 0), dim1);
2593
2594 }
2595 /**
2596 * Allocate enough memory for dim1 * dim2 * dim3 long values in a packed multi-dimensional C array and return a pointer to that memory.<br>
2597 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2598 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2599 * @return pointer to dim1 * dim2 * dim3 zero-initialized long consecutive values
2600 */
2601 public static Pointer<Pointer<Pointer<Long>>> allocateLongs(long dim1, long dim2, long dim3) {
2602 long[] dims = new long[] { dim1, dim2, dim3 };
2603 return
2604 allocateArray(
2605 PointerIO.getArrayInstance(
2606 //PointerIO.getLongInstance(),
2607 PointerIO.getArrayInstance(
2608 PointerIO.getLongInstance(),
2609 dims,
2610 1
2611 ),
2612 dims,
2613 0
2614 ),
2615 dim1
2616 )
2617 ;
2618 }
2619
2620
2621 //-- primitive: short --
2622
2623 /**
2624 * Allocate enough memory for a single short value, copy the value provided in argument into it and return a pointer to that memory.<br>
2625 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2626 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2627 * @param value initial value for the created memory location
2628 * @return pointer to a new memory location that initially contains the short value given in argument
2629 */
2630 public static Pointer<Short> pointerToShort(short value) {
2631 Pointer<Short> mem = allocate(PointerIO.getShortInstance());
2632 mem.setShort(value);
2633 return mem;
2634 }
2635
2636 /**
2637 * Allocate enough memory for values.length short values, copy the values provided as argument into it and return a pointer to that memory.<br>
2638 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2639 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2640 * The returned pointer is also an {@code Iterable<Short>} instance that can be safely iterated upon :
2641 <pre>{@code
2642 for (float f : pointerTo(1f, 2f, 3.3f))
2643 System.out.println(f); }</pre>
2644 * @param values initial values for the created memory location
2645 * @return pointer to a new memory location that initially contains the short consecutive values provided in argument
2646 */
2647 public static Pointer<Short> pointerToShorts(short... values) {
2648 if (values == null)
2649 return null;
2650 Pointer<Short> mem = allocateArray(PointerIO.getShortInstance(), values.length);
2651 mem.setShortsAtOffset(0, values, 0, values.length);
2652 return mem;
2653 }
2654
2655 /**
2656 * Allocate enough memory for all the values in the 2D short array, copy the values provided as argument into it as packed multi-dimensional C array and return a pointer to that memory.<br>
2657 * Assumes that all of the subarrays of the provided array are non null and have the same size.<br>
2658 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2659 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2660 * @param values initial values for the created memory location
2661 * @return pointer to a new memory location that initially contains the short values provided in argument packed as a 2D C array would be
2662 */
2663 public static Pointer<Pointer<Short>> pointerToShorts(short[][] values) {
2664 if (values == null)
2665 return null;
2666 int dim1 = values.length, dim2 = values[0].length;
2667 Pointer<Pointer<Short>> mem = allocateShorts(dim1, dim2);
2668 for (int i1 = 0; i1 < dim1; i1++)
2669 mem.setShortsAtOffset(i1 * dim2 * 2, values[i1], 0, dim2);
2670 return mem;
2671 }
2672
2673 /**
2674 * Allocate enough memory for all the values in the 3D short array, copy the values provided as argument into it as packed multi-dimensional C array and return a pointer to that memory.<br>
2675 * Assumes that all of the subarrays of the provided array are non null and have the same size.<br>
2676 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2677 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2678 * @param values initial values for the created memory location
2679 * @return pointer to a new memory location that initially contains the short values provided in argument packed as a 3D C array would be
2680 */
2681 public static Pointer<Pointer<Pointer<Short>>> pointerToShorts(short[][][] values) {
2682 if (values == null)
2683 return null;
2684 int dim1 = values.length, dim2 = values[0].length, dim3 = values[0][0].length;
2685 Pointer<Pointer<Pointer<Short>>> mem = allocateShorts(dim1, dim2, dim3);
2686 for (int i1 = 0; i1 < dim1; i1++) {
2687 int offset1 = i1 * dim2;
2688 for (int i2 = 0; i2 < dim2; i2++) {
2689 int offset2 = (offset1 + i2) * dim3;
2690 mem.setShortsAtOffset(offset2 * 2, values[i1][i2], 0, dim3);
2691 }
2692 }
2693 return mem;
2694 }
2695
2696 /**
2697 * Allocate enough memory for a short value and return a pointer to it.<br>
2698 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2699 * @return pointer to a single zero-initialized short value
2700 */
2701 public static Pointer<Short> allocateShort() {
2702 return allocate(PointerIO.getShortInstance());
2703 }
2704 /**
2705 * Allocate enough memory for arrayLength short values and return a pointer to that memory.<br>
2706 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2707 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2708 * The returned pointer is also an {@code Iterable<Short>} instance that can be safely iterated upon.
2709 * @return pointer to arrayLength zero-initialized short consecutive values
2710 */
2711 public static Pointer<Short> allocateShorts(long arrayLength) {
2712 return allocateArray(PointerIO.getShortInstance(), arrayLength);
2713 }
2714
2715 /**
2716 * Allocate enough memory for dim1 * dim2 short values in a packed multi-dimensional C array and return a pointer to that memory.<br>
2717 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2718 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2719 * @return pointer to dim1 * dim2 zero-initialized short consecutive values
2720 */
2721 public static Pointer<Pointer<Short>> allocateShorts(long dim1, long dim2) {
2722 return allocateArray(PointerIO.getArrayInstance(PointerIO.getShortInstance(), new long[] { dim1, dim2 }, 0), dim1);
2723
2724 }
2725 /**
2726 * Allocate enough memory for dim1 * dim2 * dim3 short values in a packed multi-dimensional C array and return a pointer to that memory.<br>
2727 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2728 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2729 * @return pointer to dim1 * dim2 * dim3 zero-initialized short consecutive values
2730 */
2731 public static Pointer<Pointer<Pointer<Short>>> allocateShorts(long dim1, long dim2, long dim3) {
2732 long[] dims = new long[] { dim1, dim2, dim3 };
2733 return
2734 allocateArray(
2735 PointerIO.getArrayInstance(
2736 //PointerIO.getShortInstance(),
2737 PointerIO.getArrayInstance(
2738 PointerIO.getShortInstance(),
2739 dims,
2740 1
2741 ),
2742 dims,
2743 0
2744 ),
2745 dim1
2746 )
2747 ;
2748 }
2749
2750
2751 //-- primitive: byte --
2752
2753 /**
2754 * Allocate enough memory for a single byte value, copy the value provided in argument into it and return a pointer to that memory.<br>
2755 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2756 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2757 * @param value initial value for the created memory location
2758 * @return pointer to a new memory location that initially contains the byte value given in argument
2759 */
2760 public static Pointer<Byte> pointerToByte(byte value) {
2761 Pointer<Byte> mem = allocate(PointerIO.getByteInstance());
2762 mem.setByte(value);
2763 return mem;
2764 }
2765
2766 /**
2767 * Allocate enough memory for values.length byte values, copy the values provided as argument into it and return a pointer to that memory.<br>
2768 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2769 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2770 * The returned pointer is also an {@code Iterable<Byte>} instance that can be safely iterated upon :
2771 <pre>{@code
2772 for (float f : pointerTo(1f, 2f, 3.3f))
2773 System.out.println(f); }</pre>
2774 * @param values initial values for the created memory location
2775 * @return pointer to a new memory location that initially contains the byte consecutive values provided in argument
2776 */
2777 public static Pointer<Byte> pointerToBytes(byte... values) {
2778 if (values == null)
2779 return null;
2780 Pointer<Byte> mem = allocateArray(PointerIO.getByteInstance(), values.length);
2781 mem.setBytesAtOffset(0, values, 0, values.length);
2782 return mem;
2783 }
2784
2785 /**
2786 * Allocate enough memory for all the values in the 2D byte array, copy the values provided as argument into it as packed multi-dimensional C array and return a pointer to that memory.<br>
2787 * Assumes that all of the subarrays of the provided array are non null and have the same size.<br>
2788 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2789 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2790 * @param values initial values for the created memory location
2791 * @return pointer to a new memory location that initially contains the byte values provided in argument packed as a 2D C array would be
2792 */
2793 public static Pointer<Pointer<Byte>> pointerToBytes(byte[][] values) {
2794 if (values == null)
2795 return null;
2796 int dim1 = values.length, dim2 = values[0].length;
2797 Pointer<Pointer<Byte>> mem = allocateBytes(dim1, dim2);
2798 for (int i1 = 0; i1 < dim1; i1++)
2799 mem.setBytesAtOffset(i1 * dim2 * 1, values[i1], 0, dim2);
2800 return mem;
2801 }
2802
2803 /**
2804 * Allocate enough memory for all the values in the 3D byte array, copy the values provided as argument into it as packed multi-dimensional C array and return a pointer to that memory.<br>
2805 * Assumes that all of the subarrays of the provided array are non null and have the same size.<br>
2806 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2807 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2808 * @param values initial values for the created memory location
2809 * @return pointer to a new memory location that initially contains the byte values provided in argument packed as a 3D C array would be
2810 */
2811 public static Pointer<Pointer<Pointer<Byte>>> pointerToBytes(byte[][][] values) {
2812 if (values == null)
2813 return null;
2814 int dim1 = values.length, dim2 = values[0].length, dim3 = values[0][0].length;
2815 Pointer<Pointer<Pointer<Byte>>> mem = allocateBytes(dim1, dim2, dim3);
2816 for (int i1 = 0; i1 < dim1; i1++) {
2817 int offset1 = i1 * dim2;
2818 for (int i2 = 0; i2 < dim2; i2++) {
2819 int offset2 = (offset1 + i2) * dim3;
2820 mem.setBytesAtOffset(offset2 * 1, values[i1][i2], 0, dim3);
2821 }
2822 }
2823 return mem;
2824 }
2825
2826 /**
2827 * Allocate enough memory for a byte value and return a pointer to it.<br>
2828 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2829 * @return pointer to a single zero-initialized byte value
2830 */
2831 public static Pointer<Byte> allocateByte() {
2832 return allocate(PointerIO.getByteInstance());
2833 }
2834 /**
2835 * Allocate enough memory for arrayLength byte values and return a pointer to that memory.<br>
2836 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2837 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2838 * The returned pointer is also an {@code Iterable<Byte>} instance that can be safely iterated upon.
2839 * @return pointer to arrayLength zero-initialized byte consecutive values
2840 */
2841 public static Pointer<Byte> allocateBytes(long arrayLength) {
2842 return allocateArray(PointerIO.getByteInstance(), arrayLength);
2843 }
2844
2845 /**
2846 * Allocate enough memory for dim1 * dim2 byte values in a packed multi-dimensional C array and return a pointer to that memory.<br>
2847 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2848 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2849 * @return pointer to dim1 * dim2 zero-initialized byte consecutive values
2850 */
2851 public static Pointer<Pointer<Byte>> allocateBytes(long dim1, long dim2) {
2852 return allocateArray(PointerIO.getArrayInstance(PointerIO.getByteInstance(), new long[] { dim1, dim2 }, 0), dim1);
2853
2854 }
2855 /**
2856 * Allocate enough memory for dim1 * dim2 * dim3 byte values in a packed multi-dimensional C array and return a pointer to that memory.<br>
2857 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2858 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2859 * @return pointer to dim1 * dim2 * dim3 zero-initialized byte consecutive values
2860 */
2861 public static Pointer<Pointer<Pointer<Byte>>> allocateBytes(long dim1, long dim2, long dim3) {
2862 long[] dims = new long[] { dim1, dim2, dim3 };
2863 return
2864 allocateArray(
2865 PointerIO.getArrayInstance(
2866 //PointerIO.getByteInstance(),
2867 PointerIO.getArrayInstance(
2868 PointerIO.getByteInstance(),
2869 dims,
2870 1
2871 ),
2872 dims,
2873 0
2874 ),
2875 dim1
2876 )
2877 ;
2878 }
2879
2880
2881 //-- primitive: char --
2882
2883 /**
2884 * Allocate enough memory for a single char value, copy the value provided in argument into it and return a pointer to that memory.<br>
2885 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2886 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2887 * @param value initial value for the created memory location
2888 * @return pointer to a new memory location that initially contains the char value given in argument
2889 */
2890 public static Pointer<Character> pointerToChar(char value) {
2891 Pointer<Character> mem = allocate(PointerIO.getCharInstance());
2892 mem.setChar(value);
2893 return mem;
2894 }
2895
2896 /**
2897 * Allocate enough memory for values.length char values, copy the values provided as argument into it and return a pointer to that memory.<br>
2898 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2899 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2900 * The returned pointer is also an {@code Iterable<Character>} instance that can be safely iterated upon :
2901 <pre>{@code
2902 for (float f : pointerTo(1f, 2f, 3.3f))
2903 System.out.println(f); }</pre>
2904 * @param values initial values for the created memory location
2905 * @return pointer to a new memory location that initially contains the char consecutive values provided in argument
2906 */
2907 public static Pointer<Character> pointerToChars(char... values) {
2908 if (values == null)
2909 return null;
2910 Pointer<Character> mem = allocateArray(PointerIO.getCharInstance(), values.length);
2911 mem.setCharsAtOffset(0, values, 0, values.length);
2912 return mem;
2913 }
2914
2915 /**
2916 * Allocate enough memory for all the values in the 2D char array, copy the values provided as argument into it as packed multi-dimensional C array and return a pointer to that memory.<br>
2917 * Assumes that all of the subarrays of the provided array are non null and have the same size.<br>
2918 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2919 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2920 * @param values initial values for the created memory location
2921 * @return pointer to a new memory location that initially contains the char values provided in argument packed as a 2D C array would be
2922 */
2923 public static Pointer<Pointer<Character>> pointerToChars(char[][] values) {
2924 if (values == null)
2925 return null;
2926 int dim1 = values.length, dim2 = values[0].length;
2927 Pointer<Pointer<Character>> mem = allocateChars(dim1, dim2);
2928 for (int i1 = 0; i1 < dim1; i1++)
2929 mem.setCharsAtOffset(i1 * dim2 * Platform.WCHAR_T_SIZE, values[i1], 0, dim2);
2930 return mem;
2931 }
2932
2933 /**
2934 * Allocate enough memory for all the values in the 3D char array, copy the values provided as argument into it as packed multi-dimensional C array and return a pointer to that memory.<br>
2935 * Assumes that all of the subarrays of the provided array are non null and have the same size.<br>
2936 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2937 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2938 * @param values initial values for the created memory location
2939 * @return pointer to a new memory location that initially contains the char values provided in argument packed as a 3D C array would be
2940 */
2941 public static Pointer<Pointer<Pointer<Character>>> pointerToChars(char[][][] values) {
2942 if (values == null)
2943 return null;
2944 int dim1 = values.length, dim2 = values[0].length, dim3 = values[0][0].length;
2945 Pointer<Pointer<Pointer<Character>>> mem = allocateChars(dim1, dim2, dim3);
2946 for (int i1 = 0; i1 < dim1; i1++) {
2947 int offset1 = i1 * dim2;
2948 for (int i2 = 0; i2 < dim2; i2++) {
2949 int offset2 = (offset1 + i2) * dim3;
2950 mem.setCharsAtOffset(offset2 * Platform.WCHAR_T_SIZE, values[i1][i2], 0, dim3);
2951 }
2952 }
2953 return mem;
2954 }
2955
2956 /**
2957 * Allocate enough memory for a char value and return a pointer to it.<br>
2958 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2959 * @return pointer to a single zero-initialized char value
2960 */
2961 public static Pointer<Character> allocateChar() {
2962 return allocate(PointerIO.getCharInstance());
2963 }
2964 /**
2965 * Allocate enough memory for arrayLength char values and return a pointer to that memory.<br>
2966 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2967 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2968 * The returned pointer is also an {@code Iterable<Character>} instance that can be safely iterated upon.
2969 * @return pointer to arrayLength zero-initialized char consecutive values
2970 */
2971 public static Pointer<Character> allocateChars(long arrayLength) {
2972 return allocateArray(PointerIO.getCharInstance(), arrayLength);
2973 }
2974
2975 /**
2976 * Allocate enough memory for dim1 * dim2 char values in a packed multi-dimensional C array and return a pointer to that memory.<br>
2977 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2978 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2979 * @return pointer to dim1 * dim2 zero-initialized char consecutive values
2980 */
2981 public static Pointer<Pointer<Character>> allocateChars(long dim1, long dim2) {
2982 return allocateArray(PointerIO.getArrayInstance(PointerIO.getCharInstance(), new long[] { dim1, dim2 }, 0), dim1);
2983
2984 }
2985 /**
2986 * Allocate enough memory for dim1 * dim2 * dim3 char values in a packed multi-dimensional C array and return a pointer to that memory.<br>
2987 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
2988 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
2989 * @return pointer to dim1 * dim2 * dim3 zero-initialized char consecutive values
2990 */
2991 public static Pointer<Pointer<Pointer<Character>>> allocateChars(long dim1, long dim2, long dim3) {
2992 long[] dims = new long[] { dim1, dim2, dim3 };
2993 return
2994 allocateArray(
2995 PointerIO.getArrayInstance(
2996 //PointerIO.getCharInstance(),
2997 PointerIO.getArrayInstance(
2998 PointerIO.getCharInstance(),
2999 dims,
3000 1
3001 ),
3002 dims,
3003 0
3004 ),
3005 dim1
3006 )
3007 ;
3008 }
3009
3010
3011 //-- primitive: float --
3012
3013 /**
3014 * Allocate enough memory for a single float value, copy the value provided in argument into it and return a pointer to that memory.<br>
3015 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3016 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3017 * @param value initial value for the created memory location
3018 * @return pointer to a new memory location that initially contains the float value given in argument
3019 */
3020 public static Pointer<Float> pointerToFloat(float value) {
3021 Pointer<Float> mem = allocate(PointerIO.getFloatInstance());
3022 mem.setFloat(value);
3023 return mem;
3024 }
3025
3026 /**
3027 * Allocate enough memory for values.length float values, copy the values provided as argument into it and return a pointer to that memory.<br>
3028 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3029 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3030 * The returned pointer is also an {@code Iterable<Float>} instance that can be safely iterated upon :
3031 <pre>{@code
3032 for (float f : pointerTo(1f, 2f, 3.3f))
3033 System.out.println(f); }</pre>
3034 * @param values initial values for the created memory location
3035 * @return pointer to a new memory location that initially contains the float consecutive values provided in argument
3036 */
3037 public static Pointer<Float> pointerToFloats(float... values) {
3038 if (values == null)
3039 return null;
3040 Pointer<Float> mem = allocateArray(PointerIO.getFloatInstance(), values.length);
3041 mem.setFloatsAtOffset(0, values, 0, values.length);
3042 return mem;
3043 }
3044
3045 /**
3046 * Allocate enough memory for all the values in the 2D float array, copy the values provided as argument into it as packed multi-dimensional C array and return a pointer to that memory.<br>
3047 * Assumes that all of the subarrays of the provided array are non null and have the same size.<br>
3048 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3049 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3050 * @param values initial values for the created memory location
3051 * @return pointer to a new memory location that initially contains the float values provided in argument packed as a 2D C array would be
3052 */
3053 public static Pointer<Pointer<Float>> pointerToFloats(float[][] values) {
3054 if (values == null)
3055 return null;
3056 int dim1 = values.length, dim2 = values[0].length;
3057 Pointer<Pointer<Float>> mem = allocateFloats(dim1, dim2);
3058 for (int i1 = 0; i1 < dim1; i1++)
3059 mem.setFloatsAtOffset(i1 * dim2 * 4, values[i1], 0, dim2);
3060 return mem;
3061 }
3062
3063 /**
3064 * Allocate enough memory for all the values in the 3D float array, copy the values provided as argument into it as packed multi-dimensional C array and return a pointer to that memory.<br>
3065 * Assumes that all of the subarrays of the provided array are non null and have the same size.<br>
3066 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3067 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3068 * @param values initial values for the created memory location
3069 * @return pointer to a new memory location that initially contains the float values provided in argument packed as a 3D C array would be
3070 */
3071 public static Pointer<Pointer<Pointer<Float>>> pointerToFloats(float[][][] values) {
3072 if (values == null)
3073 return null;
3074 int dim1 = values.length, dim2 = values[0].length, dim3 = values[0][0].length;
3075 Pointer<Pointer<Pointer<Float>>> mem = allocateFloats(dim1, dim2, dim3);
3076 for (int i1 = 0; i1 < dim1; i1++) {
3077 int offset1 = i1 * dim2;
3078 for (int i2 = 0; i2 < dim2; i2++) {
3079 int offset2 = (offset1 + i2) * dim3;
3080 mem.setFloatsAtOffset(offset2 * 4, values[i1][i2], 0, dim3);
3081 }
3082 }
3083 return mem;
3084 }
3085
3086 /**
3087 * Allocate enough memory for a float value and return a pointer to it.<br>
3088 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3089 * @return pointer to a single zero-initialized float value
3090 */
3091 public static Pointer<Float> allocateFloat() {
3092 return allocate(PointerIO.getFloatInstance());
3093 }
3094 /**
3095 * Allocate enough memory for arrayLength float values and return a pointer to that memory.<br>
3096 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3097 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3098 * The returned pointer is also an {@code Iterable<Float>} instance that can be safely iterated upon.
3099 * @return pointer to arrayLength zero-initialized float consecutive values
3100 */
3101 public static Pointer<Float> allocateFloats(long arrayLength) {
3102 return allocateArray(PointerIO.getFloatInstance(), arrayLength);
3103 }
3104
3105 /**
3106 * Allocate enough memory for dim1 * dim2 float values in a packed multi-dimensional C array and return a pointer to that memory.<br>
3107 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3108 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3109 * @return pointer to dim1 * dim2 zero-initialized float consecutive values
3110 */
3111 public static Pointer<Pointer<Float>> allocateFloats(long dim1, long dim2) {
3112 return allocateArray(PointerIO.getArrayInstance(PointerIO.getFloatInstance(), new long[] { dim1, dim2 }, 0), dim1);
3113
3114 }
3115 /**
3116 * Allocate enough memory for dim1 * dim2 * dim3 float values in a packed multi-dimensional C array and return a pointer to that memory.<br>
3117 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3118 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3119 * @return pointer to dim1 * dim2 * dim3 zero-initialized float consecutive values
3120 */
3121 public static Pointer<Pointer<Pointer<Float>>> allocateFloats(long dim1, long dim2, long dim3) {
3122 long[] dims = new long[] { dim1, dim2, dim3 };
3123 return
3124 allocateArray(
3125 PointerIO.getArrayInstance(
3126 //PointerIO.getFloatInstance(),
3127 PointerIO.getArrayInstance(
3128 PointerIO.getFloatInstance(),
3129 dims,
3130 1
3131 ),
3132 dims,
3133 0
3134 ),
3135 dim1
3136 )
3137 ;
3138 }
3139
3140
3141 //-- primitive: double --
3142
3143 /**
3144 * Allocate enough memory for a single double value, copy the value provided in argument into it and return a pointer to that memory.<br>
3145 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3146 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3147 * @param value initial value for the created memory location
3148 * @return pointer to a new memory location that initially contains the double value given in argument
3149 */
3150 public static Pointer<Double> pointerToDouble(double value) {
3151 Pointer<Double> mem = allocate(PointerIO.getDoubleInstance());
3152 mem.setDouble(value);
3153 return mem;
3154 }
3155
3156 /**
3157 * Allocate enough memory for values.length double values, copy the values provided as argument into it and return a pointer to that memory.<br>
3158 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3159 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3160 * The returned pointer is also an {@code Iterable<Double>} instance that can be safely iterated upon :
3161 <pre>{@code
3162 for (float f : pointerTo(1f, 2f, 3.3f))
3163 System.out.println(f); }</pre>
3164 * @param values initial values for the created memory location
3165 * @return pointer to a new memory location that initially contains the double consecutive values provided in argument
3166 */
3167 public static Pointer<Double> pointerToDoubles(double... values) {
3168 if (values == null)
3169 return null;
3170 Pointer<Double> mem = allocateArray(PointerIO.getDoubleInstance(), values.length);
3171 mem.setDoublesAtOffset(0, values, 0, values.length);
3172 return mem;
3173 }
3174
3175 /**
3176 * Allocate enough memory for all the values in the 2D double array, copy the values provided as argument into it as packed multi-dimensional C array and return a pointer to that memory.<br>
3177 * Assumes that all of the subarrays of the provided array are non null and have the same size.<br>
3178 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3179 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3180 * @param values initial values for the created memory location
3181 * @return pointer to a new memory location that initially contains the double values provided in argument packed as a 2D C array would be
3182 */
3183 public static Pointer<Pointer<Double>> pointerToDoubles(double[][] values) {
3184 if (values == null)
3185 return null;
3186 int dim1 = values.length, dim2 = values[0].length;
3187 Pointer<Pointer<Double>> mem = allocateDoubles(dim1, dim2);
3188 for (int i1 = 0; i1 < dim1; i1++)
3189 mem.setDoublesAtOffset(i1 * dim2 * 8, values[i1], 0, dim2);
3190 return mem;
3191 }
3192
3193 /**
3194 * Allocate enough memory for all the values in the 3D double array, copy the values provided as argument into it as packed multi-dimensional C array and return a pointer to that memory.<br>
3195 * Assumes that all of the subarrays of the provided array are non null and have the same size.<br>
3196 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3197 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3198 * @param values initial values for the created memory location
3199 * @return pointer to a new memory location that initially contains the double values provided in argument packed as a 3D C array would be
3200 */
3201 public static Pointer<Pointer<Pointer<Double>>> pointerToDoubles(double[][][] values) {
3202 if (values == null)
3203 return null;
3204 int dim1 = values.length, dim2 = values[0].length, dim3 = values[0][0].length;
3205 Pointer<Pointer<Pointer<Double>>> mem = allocateDoubles(dim1, dim2, dim3);
3206 for (int i1 = 0; i1 < dim1; i1++) {
3207 int offset1 = i1 * dim2;
3208 for (int i2 = 0; i2 < dim2; i2++) {
3209 int offset2 = (offset1 + i2) * dim3;
3210 mem.setDoublesAtOffset(offset2 * 8, values[i1][i2], 0, dim3);
3211 }
3212 }
3213 return mem;
3214 }
3215
3216 /**
3217 * Allocate enough memory for a double value and return a pointer to it.<br>
3218 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3219 * @return pointer to a single zero-initialized double value
3220 */
3221 public static Pointer<Double> allocateDouble() {
3222 return allocate(PointerIO.getDoubleInstance());
3223 }
3224 /**
3225 * Allocate enough memory for arrayLength double values and return a pointer to that memory.<br>
3226 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3227 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3228 * The returned pointer is also an {@code Iterable<Double>} instance that can be safely iterated upon.
3229 * @return pointer to arrayLength zero-initialized double consecutive values
3230 */
3231 public static Pointer<Double> allocateDoubles(long arrayLength) {
3232 return allocateArray(PointerIO.getDoubleInstance(), arrayLength);
3233 }
3234
3235 /**
3236 * Allocate enough memory for dim1 * dim2 double values in a packed multi-dimensional C array and return a pointer to that memory.<br>
3237 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3238 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3239 * @return pointer to dim1 * dim2 zero-initialized double consecutive values
3240 */
3241 public static Pointer<Pointer<Double>> allocateDoubles(long dim1, long dim2) {
3242 return allocateArray(PointerIO.getArrayInstance(PointerIO.getDoubleInstance(), new long[] { dim1, dim2 }, 0), dim1);
3243
3244 }
3245 /**
3246 * Allocate enough memory for dim1 * dim2 * dim3 double values in a packed multi-dimensional C array and return a pointer to that memory.<br>
3247 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3248 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3249 * @return pointer to dim1 * dim2 * dim3 zero-initialized double consecutive values
3250 */
3251 public static Pointer<Pointer<Pointer<Double>>> allocateDoubles(long dim1, long dim2, long dim3) {
3252 long[] dims = new long[] { dim1, dim2, dim3 };
3253 return
3254 allocateArray(
3255 PointerIO.getArrayInstance(
3256 //PointerIO.getDoubleInstance(),
3257 PointerIO.getArrayInstance(
3258 PointerIO.getDoubleInstance(),
3259 dims,
3260 1
3261 ),
3262 dims,
3263 0
3264 ),
3265 dim1
3266 )
3267 ;
3268 }
3269
3270
3271 //-- primitive: boolean --
3272
3273 /**
3274 * Allocate enough memory for a single boolean value, copy the value provided in argument into it and return a pointer to that memory.<br>
3275 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3276 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3277 * @param value initial value for the created memory location
3278 * @return pointer to a new memory location that initially contains the boolean value given in argument
3279 */
3280 public static Pointer<Boolean> pointerToBoolean(boolean value) {
3281 Pointer<Boolean> mem = allocate(PointerIO.getBooleanInstance());
3282 mem.setBoolean(value);
3283 return mem;
3284 }
3285
3286 /**
3287 * Allocate enough memory for values.length boolean values, copy the values provided as argument into it and return a pointer to that memory.<br>
3288 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3289 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3290 * The returned pointer is also an {@code Iterable<Boolean>} instance that can be safely iterated upon :
3291 <pre>{@code
3292 for (float f : pointerTo(1f, 2f, 3.3f))
3293 System.out.println(f); }</pre>
3294 * @param values initial values for the created memory location
3295 * @return pointer to a new memory location that initially contains the boolean consecutive values provided in argument
3296 */
3297 public static Pointer<Boolean> pointerToBooleans(boolean... values) {
3298 if (values == null)
3299 return null;
3300 Pointer<Boolean> mem = allocateArray(PointerIO.getBooleanInstance(), values.length);
3301 mem.setBooleansAtOffset(0, values, 0, values.length);
3302 return mem;
3303 }
3304
3305 /**
3306 * Allocate enough memory for all the values in the 2D boolean array, copy the values provided as argument into it as packed multi-dimensional C array and return a pointer to that memory.<br>
3307 * Assumes that all of the subarrays of the provided array are non null and have the same size.<br>
3308 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3309 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3310 * @param values initial values for the created memory location
3311 * @return pointer to a new memory location that initially contains the boolean values provided in argument packed as a 2D C array would be
3312 */
3313 public static Pointer<Pointer<Boolean>> pointerToBooleans(boolean[][] values) {
3314 if (values == null)
3315 return null;
3316 int dim1 = values.length, dim2 = values[0].length;
3317 Pointer<Pointer<Boolean>> mem = allocateBooleans(dim1, dim2);
3318 for (int i1 = 0; i1 < dim1; i1++)
3319 mem.setBooleansAtOffset(i1 * dim2 * 1, values[i1], 0, dim2);
3320 return mem;
3321 }
3322
3323 /**
3324 * Allocate enough memory for all the values in the 3D boolean array, copy the values provided as argument into it as packed multi-dimensional C array and return a pointer to that memory.<br>
3325 * Assumes that all of the subarrays of the provided array are non null and have the same size.<br>
3326 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3327 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3328 * @param values initial values for the created memory location
3329 * @return pointer to a new memory location that initially contains the boolean values provided in argument packed as a 3D C array would be
3330 */
3331 public static Pointer<Pointer<Pointer<Boolean>>> pointerToBooleans(boolean[][][] values) {
3332 if (values == null)
3333 return null;
3334 int dim1 = values.length, dim2 = values[0].length, dim3 = values[0][0].length;
3335 Pointer<Pointer<Pointer<Boolean>>> mem = allocateBooleans(dim1, dim2, dim3);
3336 for (int i1 = 0; i1 < dim1; i1++) {
3337 int offset1 = i1 * dim2;
3338 for (int i2 = 0; i2 < dim2; i2++) {
3339 int offset2 = (offset1 + i2) * dim3;
3340 mem.setBooleansAtOffset(offset2 * 1, values[i1][i2], 0, dim3);
3341 }
3342 }
3343 return mem;
3344 }
3345
3346 /**
3347 * Allocate enough memory for a boolean value and return a pointer to it.<br>
3348 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3349 * @return pointer to a single zero-initialized boolean value
3350 */
3351 public static Pointer<Boolean> allocateBoolean() {
3352 return allocate(PointerIO.getBooleanInstance());
3353 }
3354 /**
3355 * Allocate enough memory for arrayLength boolean values and return a pointer to that memory.<br>
3356 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3357 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3358 * The returned pointer is also an {@code Iterable<Boolean>} instance that can be safely iterated upon.
3359 * @return pointer to arrayLength zero-initialized boolean consecutive values
3360 */
3361 public static Pointer<Boolean> allocateBooleans(long arrayLength) {
3362 return allocateArray(PointerIO.getBooleanInstance(), arrayLength);
3363 }
3364
3365 /**
3366 * Allocate enough memory for dim1 * dim2 boolean values in a packed multi-dimensional C array and return a pointer to that memory.<br>
3367 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3368 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3369 * @return pointer to dim1 * dim2 zero-initialized boolean consecutive values
3370 */
3371 public static Pointer<Pointer<Boolean>> allocateBooleans(long dim1, long dim2) {
3372 return allocateArray(PointerIO.getArrayInstance(PointerIO.getBooleanInstance(), new long[] { dim1, dim2 }, 0), dim1);
3373
3374 }
3375 /**
3376 * Allocate enough memory for dim1 * dim2 * dim3 boolean values in a packed multi-dimensional C array and return a pointer to that memory.<br>
3377 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3378 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3379 * @return pointer to dim1 * dim2 * dim3 zero-initialized boolean consecutive values
3380 */
3381 public static Pointer<Pointer<Pointer<Boolean>>> allocateBooleans(long dim1, long dim2, long dim3) {
3382 long[] dims = new long[] { dim1, dim2, dim3 };
3383 return
3384 allocateArray(
3385 PointerIO.getArrayInstance(
3386 //PointerIO.getBooleanInstance(),
3387 PointerIO.getArrayInstance(
3388 PointerIO.getBooleanInstance(),
3389 dims,
3390 1
3391 ),
3392 dims,
3393 0
3394 ),
3395 dim1
3396 )
3397 ;
3398 }
3399
3400 //-- primitive (no bool): int --
3401
3402 /**
3403 * Create a pointer to the memory location used by a direct NIO IntBuffer.<br>
3404 * If the NIO IntBuffer is not direct, then its backing Java array is copied to some native memory and will never be updated by changes to the native memory (calls {@link Pointer#pointerToInts(int[])}), unless a call to {@link Pointer#updateBuffer(Buffer)} is made manually.<br>
3405 * The returned pointer (and its subsequent views returned by {@link Pointer#offset(long)} or {@link Pointer#next(long)}) can be used safely : it retains a reference to the original NIO buffer, so that this latter cannot be garbage collected before the pointer.</br>
3406 */
3407 public static Pointer<Integer> pointerToInts(IntBuffer buffer) {
3408 if (buffer == null)
3409 return null;
3410
3411 if (!buffer.isDirect()) {
3412 return pointerToInts(buffer.array());
3413 //throw new UnsupportedOperationException("Cannot create pointers to indirect IntBuffer buffers");
3414 }
3415
3416 long address = JNI.getDirectBufferAddress(buffer);
3417 long size = JNI.getDirectBufferCapacity(buffer);
3418
3419 // HACK (TODO?) the JNI spec says size is in bytes, but in practice on mac os x it's in elements !!!
3420 size *= 4;
3421 //System.out.println("Buffer capacity = " + size);
3422
3423 if (address == 0 || size == 0)
3424 return null;
3425
3426 PointerIO<Integer> io = CommonPointerIOs.intIO;
3427 boolean ordered = buffer.order().equals(ByteOrder.nativeOrder());
3428 return newPointer(io, address, ordered, address, address + size, null, NO_PARENT, null, buffer);
3429 }
3430
3431 //-- primitive (no bool): long --
3432
3433 /**
3434 * Create a pointer to the memory location used by a direct NIO LongBuffer.<br>
3435 * If the NIO LongBuffer is not direct, then its backing Java array is copied to some native memory and will never be updated by changes to the native memory (calls {@link Pointer#pointerToLongs(long[])}), unless a call to {@link Pointer#updateBuffer(Buffer)} is made manually.<br>
3436 * The returned pointer (and its subsequent views returned by {@link Pointer#offset(long)} or {@link Pointer#next(long)}) can be used safely : it retains a reference to the original NIO buffer, so that this latter cannot be garbage collected before the pointer.</br>
3437 */
3438 public static Pointer<Long> pointerToLongs(LongBuffer buffer) {
3439 if (buffer == null)
3440 return null;
3441
3442 if (!buffer.isDirect()) {
3443 return pointerToLongs(buffer.array());
3444 //throw new UnsupportedOperationException("Cannot create pointers to indirect LongBuffer buffers");
3445 }
3446
3447 long address = JNI.getDirectBufferAddress(buffer);
3448 long size = JNI.getDirectBufferCapacity(buffer);
3449
3450 // HACK (TODO?) the JNI spec says size is in bytes, but in practice on mac os x it's in elements !!!
3451 size *= 8;
3452 //System.out.println("Buffer capacity = " + size);
3453
3454 if (address == 0 || size == 0)
3455 return null;
3456
3457 PointerIO<Long> io = CommonPointerIOs.longIO;
3458 boolean ordered = buffer.order().equals(ByteOrder.nativeOrder());
3459 return newPointer(io, address, ordered, address, address + size, null, NO_PARENT, null, buffer);
3460 }
3461
3462 //-- primitive (no bool): short --
3463
3464 /**
3465 * Create a pointer to the memory location used by a direct NIO ShortBuffer.<br>
3466 * If the NIO ShortBuffer is not direct, then its backing Java array is copied to some native memory and will never be updated by changes to the native memory (calls {@link Pointer#pointerToShorts(short[])}), unless a call to {@link Pointer#updateBuffer(Buffer)} is made manually.<br>
3467 * The returned pointer (and its subsequent views returned by {@link Pointer#offset(long)} or {@link Pointer#next(long)}) can be used safely : it retains a reference to the original NIO buffer, so that this latter cannot be garbage collected before the pointer.</br>
3468 */
3469 public static Pointer<Short> pointerToShorts(ShortBuffer buffer) {
3470 if (buffer == null)
3471 return null;
3472
3473 if (!buffer.isDirect()) {
3474 return pointerToShorts(buffer.array());
3475 //throw new UnsupportedOperationException("Cannot create pointers to indirect ShortBuffer buffers");
3476 }
3477
3478 long address = JNI.getDirectBufferAddress(buffer);
3479 long size = JNI.getDirectBufferCapacity(buffer);
3480
3481 // HACK (TODO?) the JNI spec says size is in bytes, but in practice on mac os x it's in elements !!!
3482 size *= 2;
3483 //System.out.println("Buffer capacity = " + size);
3484
3485 if (address == 0 || size == 0)
3486 return null;
3487
3488 PointerIO<Short> io = CommonPointerIOs.shortIO;
3489 boolean ordered = buffer.order().equals(ByteOrder.nativeOrder());
3490 return newPointer(io, address, ordered, address, address + size, null, NO_PARENT, null, buffer);
3491 }
3492
3493 //-- primitive (no bool): byte --
3494
3495 /**
3496 * Create a pointer to the memory location used by a direct NIO ByteBuffer.<br>
3497 * If the NIO ByteBuffer is not direct, then its backing Java array is copied to some native memory and will never be updated by changes to the native memory (calls {@link Pointer#pointerToBytes(byte[])}), unless a call to {@link Pointer#updateBuffer(Buffer)} is made manually.<br>
3498 * The returned pointer (and its subsequent views returned by {@link Pointer#offset(long)} or {@link Pointer#next(long)}) can be used safely : it retains a reference to the original NIO buffer, so that this latter cannot be garbage collected before the pointer.</br>
3499 */
3500 public static Pointer<Byte> pointerToBytes(ByteBuffer buffer) {
3501 if (buffer == null)
3502 return null;
3503
3504 if (!buffer.isDirect()) {
3505 return pointerToBytes(buffer.array());
3506 //throw new UnsupportedOperationException("Cannot create pointers to indirect ByteBuffer buffers");
3507 }
3508
3509 long address = JNI.getDirectBufferAddress(buffer);
3510 long size = JNI.getDirectBufferCapacity(buffer);
3511
3512 // HACK (TODO?) the JNI spec says size is in bytes, but in practice on mac os x it's in elements !!!
3513 size *= 1;
3514 //System.out.println("Buffer capacity = " + size);
3515
3516 if (address == 0 || size == 0)
3517 return null;
3518
3519 PointerIO<Byte> io = CommonPointerIOs.byteIO;
3520 boolean ordered = buffer.order().equals(ByteOrder.nativeOrder());
3521 return newPointer(io, address, ordered, address, address + size, null, NO_PARENT, null, buffer);
3522 }
3523
3524 //-- primitive (no bool): char --
3525
3526 /**
3527 * Create a pointer to the memory location used by a direct NIO CharBuffer.<br>
3528 * If the NIO CharBuffer is not direct, then its backing Java array is copied to some native memory and will never be updated by changes to the native memory (calls {@link Pointer#pointerToChars(char[])}), unless a call to {@link Pointer#updateBuffer(Buffer)} is made manually.<br>
3529 * The returned pointer (and its subsequent views returned by {@link Pointer#offset(long)} or {@link Pointer#next(long)}) can be used safely : it retains a reference to the original NIO buffer, so that this latter cannot be garbage collected before the pointer.</br>
3530 */
3531 public static Pointer<Character> pointerToChars(CharBuffer buffer) {
3532 if (buffer == null)
3533 return null;
3534
3535 if (!buffer.isDirect()) {
3536 return pointerToChars(buffer.array());
3537 //throw new UnsupportedOperationException("Cannot create pointers to indirect CharBuffer buffers");
3538 }
3539
3540 long address = JNI.getDirectBufferAddress(buffer);
3541 long size = JNI.getDirectBufferCapacity(buffer);
3542
3543 // HACK (TODO?) the JNI spec says size is in bytes, but in practice on mac os x it's in elements !!!
3544 size *= Platform.WCHAR_T_SIZE;
3545 //System.out.println("Buffer capacity = " + size);
3546
3547 if (address == 0 || size == 0)
3548 return null;
3549
3550 PointerIO<Character> io = CommonPointerIOs.charIO;
3551 boolean ordered = buffer.order().equals(ByteOrder.nativeOrder());
3552 return newPointer(io, address, ordered, address, address + size, null, NO_PARENT, null, buffer);
3553 }
3554
3555 //-- primitive (no bool): float --
3556
3557 /**
3558 * Create a pointer to the memory location used by a direct NIO FloatBuffer.<br>
3559 * If the NIO FloatBuffer is not direct, then its backing Java array is copied to some native memory and will never be updated by changes to the native memory (calls {@link Pointer#pointerToFloats(float[])}), unless a call to {@link Pointer#updateBuffer(Buffer)} is made manually.<br>
3560 * The returned pointer (and its subsequent views returned by {@link Pointer#offset(long)} or {@link Pointer#next(long)}) can be used safely : it retains a reference to the original NIO buffer, so that this latter cannot be garbage collected before the pointer.</br>
3561 */
3562 public static Pointer<Float> pointerToFloats(FloatBuffer buffer) {
3563 if (buffer == null)
3564 return null;
3565
3566 if (!buffer.isDirect()) {
3567 return pointerToFloats(buffer.array());
3568 //throw new UnsupportedOperationException("Cannot create pointers to indirect FloatBuffer buffers");
3569 }
3570
3571 long address = JNI.getDirectBufferAddress(buffer);
3572 long size = JNI.getDirectBufferCapacity(buffer);
3573
3574 // HACK (TODO?) the JNI spec says size is in bytes, but in practice on mac os x it's in elements !!!
3575 size *= 4;
3576 //System.out.println("Buffer capacity = " + size);
3577
3578 if (address == 0 || size == 0)
3579 return null;
3580
3581 PointerIO<Float> io = CommonPointerIOs.floatIO;
3582 boolean ordered = buffer.order().equals(ByteOrder.nativeOrder());
3583 return newPointer(io, address, ordered, address, address + size, null, NO_PARENT, null, buffer);
3584 }
3585
3586 //-- primitive (no bool): double --
3587
3588 /**
3589 * Create a pointer to the memory location used by a direct NIO DoubleBuffer.<br>
3590 * If the NIO DoubleBuffer is not direct, then its backing Java array is copied to some native memory and will never be updated by changes to the native memory (calls {@link Pointer#pointerToDoubles(double[])}), unless a call to {@link Pointer#updateBuffer(Buffer)} is made manually.<br>
3591 * The returned pointer (and its subsequent views returned by {@link Pointer#offset(long)} or {@link Pointer#next(long)}) can be used safely : it retains a reference to the original NIO buffer, so that this latter cannot be garbage collected before the pointer.</br>
3592 */
3593 public static Pointer<Double> pointerToDoubles(DoubleBuffer buffer) {
3594 if (buffer == null)
3595 return null;
3596
3597 if (!buffer.isDirect()) {
3598 return pointerToDoubles(buffer.array());
3599 //throw new UnsupportedOperationException("Cannot create pointers to indirect DoubleBuffer buffers");
3600 }
3601
3602 long address = JNI.getDirectBufferAddress(buffer);
3603 long size = JNI.getDirectBufferCapacity(buffer);
3604
3605 // HACK (TODO?) the JNI spec says size is in bytes, but in practice on mac os x it's in elements !!!
3606 size *= 8;
3607 //System.out.println("Buffer capacity = " + size);
3608
3609 if (address == 0 || size == 0)
3610 return null;
3611
3612 PointerIO<Double> io = CommonPointerIOs.doubleIO;
3613 boolean ordered = buffer.order().equals(ByteOrder.nativeOrder());
3614 return newPointer(io, address, ordered, address, address + size, null, NO_PARENT, null, buffer);
3615 }
3616
3617
3618 /**
3619 * Get the type of pointed elements.
3620 */
3621 public Type getTargetType() {
3622 PointerIO<T> io = getIO();
3623 return io == null ? null : io.getTargetType();
3624 }
3625
3626 /**
3627 * Read an untyped pointer value from the pointed memory location
3628 * @deprecated Avoid using untyped pointers, if possible.
3629 */
3630 @Deprecated
3631 public Pointer<?> getPointer() {
3632 return getPointerAtOffset(0, (PointerIO)null);
3633 }
3634
3635 /**
3636 * Read a pointer value from the pointed memory location shifted by a byte offset
3637 */
3638 public Pointer<?> getPointerAtOffset(long byteOffset) {
3639 return getPointerAtOffset(byteOffset, (PointerIO)null);
3640 }
3641
3642 /**
3643 * Read the nth contiguous pointer value from the pointed memory location.<br>
3644 * Equivalent to <code>getPointerAtOffset(valueIndex * Pointer.SIZE)</code>.
3645 * @param valueIndex index of the value to read
3646 */
3647 public Pointer<?> getPointerAtIndex(long valueIndex) {
3648 return getPointerAtOffset(valueIndex * Pointer.SIZE);
3649 }
3650
3651 /**
3652 * Read a pointer value from the pointed memory location.<br>
3653 * @param c class of the elements pointed by the resulting pointer
3654 */
3655 public <U> Pointer<U> getPointer(Class<U> c) {
3656 return getPointerAtOffset(0, (PointerIO<U>)PointerIO.getInstance(c));
3657 }
3658
3659 /**
3660 * Read a pointer value from the pointed memory location
3661 * @param pio PointerIO instance that knows how to read the elements pointed by the resulting pointer
3662 */
3663 public <U> Pointer<U> getPointer(PointerIO<U> pio) {
3664 return getPointerAtOffset(0, pio);
3665 }
3666
3667 /**
3668 * Read a pointer value from the pointed memory location shifted by a byte offset
3669 * @param c class of the elements pointed by the resulting pointer
3670 */
3671 public <U> Pointer<U> getPointerAtOffset(long byteOffset, Class<U> c) {
3672 return getPointerAtOffset(byteOffset, (Type)c);
3673 }
3674
3675 /**
3676 * Read a pointer value from the pointed memory location shifted by a byte offset
3677 * @param t type of the elements pointed by the resulting pointer
3678 */
3679 public <U> Pointer<U> getPointerAtOffset(long byteOffset, Type t) {
3680 return getPointerAtOffset(byteOffset, t == null ? null : (PointerIO<U>)PointerIO.getInstance(t));
3681 }
3682
3683 /**
3684 * Read a pointer value from the pointed memory location shifted by a byte offset
3685 * @param pio PointerIO instance that knows how to read the elements pointed by the resulting pointer
3686 */
3687 public <U> Pointer<U> getPointerAtOffset(long byteOffset, PointerIO<U> pio) {
3688 long value = getSizeTAtOffset(byteOffset);
3689 if (value == 0)
3690 return null;
3691 return newPointer(pio, value, isOrdered(), UNKNOWN_VALIDITY, UNKNOWN_VALIDITY, this, byteOffset, null, null);
3692 }
3693
3694 /**
3695 * Write a pointer value to the pointed memory location
3696 */
3697 public Pointer<T> setPointer(Pointer<?> value) {
3698 return setPointerAtOffset(0, value);
3699 }
3700
3701 /**
3702 * Write a pointer value to the pointed memory location shifted by a byte offset
3703 */
3704 public Pointer<T> setPointerAtOffset(long byteOffset, Pointer<?> value) {
3705 setSizeTAtOffset(byteOffset, value == null ? 0 : value.getPeer());
3706 return this;
3707 }
3708
3709 /**
3710 * Write the nth contiguous pointer value to the pointed memory location.<br>
3711 * Equivalent to <code>setPointerAtOffset(valueIndex * Pointer.SIZE, value)</code>.
3712 * @param valueIndex index of the value to write
3713 * @param value pointer value to write
3714 */
3715 public Pointer<T> setPointerAtIndex(long valueIndex, Pointer<?> value) {
3716 setPointerAtOffset(valueIndex * Pointer.SIZE, value);
3717 return this;
3718 }
3719
3720 /**
3721 * Read an array of untyped pointer values from the pointed memory location shifted by a byte offset
3722 * @deprecated Use a typed version instead : {@link Pointer#getPointersAtOffset(long, int, Type)}, {@link Pointer#getPointersAtOffset(long, int, Class)} or {@link Pointer#getPointersAtOffset(long, int, PointerIO)}
3723 */
3724 public Pointer<?>[] getPointersAtOffset(long byteOffset, int arrayLength) {
3725 return getPointersAtOffset(byteOffset, arrayLength, (PointerIO)null);
3726 }
3727 /**
3728 * Read the array of remaining untyped pointer values from the pointed memory location
3729 * @deprecated Use a typed version instead : {@link Pointer#getPointersAtOffset(long, int, Type)}, {@link Pointer#getPointersAtOffset(long, int, Class)} or {@link Pointer#getPointersAtOffset(long, int, PointerIO)}
3730 */
3731 @Deprecated
3732 public Pointer<?>[] getPointers() {
3733 long rem = getValidElements("Cannot create array if remaining length is not known. Please use getPointers(int length) instead.");
3734 return getPointersAtOffset(0L, (int)rem);
3735 }
3736 /**
3737 * Read an array of untyped pointer values from the pointed memory location
3738 * @deprecated Use a typed version instead : {@link Pointer#getPointersAtOffset(long, int, Type)}, {@link Pointer#getPointersAtOffset(long, int, Class)} or {@link Pointer#getPointersAtOffset(long, int, PointerIO)}
3739 */
3740 @Deprecated
3741 public Pointer<?>[] getPointers(int arrayLength) {
3742 return getPointersAtOffset(0, arrayLength);
3743 }
3744 /**
3745 * Read an array of pointer values from the pointed memory location shifted by a byte offset
3746 * @param t type of the elements pointed by the resulting pointer
3747 */
3748 public <U> Pointer<U>[] getPointersAtOffset(long byteOffset, int arrayLength, Type t) {
3749 return getPointersAtOffset(byteOffset, arrayLength, t == null ? null : (PointerIO<U>)PointerIO.getInstance(t));
3750 }
3751 /**
3752 * Read an array of pointer values from the pointed memory location shifted by a byte offset
3753 * @param t class of the elements pointed by the resulting pointer
3754 */
3755 public <U> Pointer<U>[] getPointersAtOffset(long byteOffset, int arrayLength, Class<U> t) {
3756 return getPointersAtOffset(byteOffset, arrayLength, (Type)t);
3757 }
3758
3759 /**
3760 * Read an array of pointer values from the pointed memory location shifted by a byte offset
3761 * @param pio PointerIO instance that knows how to read the elements pointed by the resulting pointer
3762 */
3763 public <U> Pointer<U>[] getPointersAtOffset(long byteOffset, int arrayLength, PointerIO pio) {
3764 Pointer<U>[] values = (Pointer<U>[])new Pointer[arrayLength];
3765 int s = Platform.POINTER_SIZE;
3766 for (int i = 0; i < arrayLength; i++)
3767 values[i] = getPointerAtOffset(byteOffset + i * s, pio);
3768 return values;
3769 }
3770 /**
3771 * Write an array of pointer values to the pointed memory location shifted by a byte offset
3772 */
3773 public Pointer<T> setPointersAtOffset(long byteOffset, Pointer<?>[] values) {
3774 return setPointersAtOffset(byteOffset, values, 0, values.length);
3775 }
3776
3777 /**
3778 * Write length pointer values from the given array (starting at the given value offset) to the pointed memory location shifted by a byte offset
3779 */
3780 public Pointer<T> setPointersAtOffset(long byteOffset, Pointer<?>[] values, int valuesOffset, int length) {
3781 if (values == null)
3782 throw new IllegalArgumentException("Null values");
3783 int n = length, s = Platform.POINTER_SIZE;
3784 for (int i = 0; i < n; i++)
3785 setPointerAtOffset(byteOffset + i * s, values[valuesOffset + i]);
3786 return this;
3787 }
3788
3789 /**
3790 * Write an array of pointer values to the pointed memory location
3791 */
3792 public Pointer<T> setPointers(Pointer<?>[] values) {
3793 return setPointersAtOffset(0, values);
3794 }
3795
3796 /**
3797 * Read an array of elements from the pointed memory location shifted by a byte offset.<br>
3798 * For pointers to primitive types (e.g. {@code Pointer<Integer> }), this method returns primitive arrays (e.g. {@code int[] }), unlike {@link Pointer#toArray } (which returns arrays of objects so primitives end up being boxed, e.g. {@code Integer[] })
3799 * @return an array of values of the requested length. The array is an array of primitives if the pointer's target type is a primitive or a boxed primitive type
3800 */
3801 public Object getArrayAtOffset(long byteOffset, int length) {
3802 return getIO("Cannot create sublist").getArray(this, byteOffset, length);
3803 }
3804
3805 /**
3806 * Read an array of elements from the pointed memory location.<br>
3807 * For pointers to primitive types (e.g. {@code Pointer<Integer> }), this method returns primitive arrays (e.g. {@code int[] }), unlike {@link Pointer#toArray } (which returns arrays of objects so primitives end up being boxed, e.g. {@code Integer[] })
3808 * @return an array of values of the requested length. The array is an array of primitives if the pointer's target type is a primitive or a boxed primitive type
3809 */
3810 public Object getArray(int length) {
3811 return getArrayAtOffset(0L, length);
3812 }
3813
3814 /**
3815 * Read the array of remaining elements from the pointed memory location.<br>
3816 * For pointers to primitive types (e.g. {@code Pointer<Integer> }), this method returns primitive arrays (e.g. {@code int[] }), unlike {@link Pointer#toArray } (which returns arrays of objects so primitives end up being boxed, e.g. {@code Integer[] })
3817 * @return an array of values of the requested length. The array is an array of primitives if the pointer's target type is a primitive or a boxed primitive type
3818 */
3819 public Object getArray() {
3820 return getArray((int)getValidElements());
3821 }
3822
3823 /**
3824 * Read an NIO {@link Buffer} of elements from the pointed memory location shifted by a byte offset.<br>
3825 * @return an NIO {@link Buffer} of values of the requested length.
3826 * @throws UnsupportedOperationException if this pointer's target type is not a Java primitive type with a corresponding NIO {@link Buffer} class.
3827 */
3828 public <B extends Buffer> B getBufferAtOffset(long byteOffset, int length) {
3829 return (B)getIO("Cannot create Buffer").getBuffer(this, byteOffset, length);
3830 }
3831
3832 /**
3833 * Read an NIO {@link Buffer} of elements from the pointed memory location.<br>
3834 * @return an NIO {@link Buffer} of values of the requested length.
3835 * @throws UnsupportedOperationException if this pointer's target type is not a Java primitive type with a corresponding NIO {@link Buffer} class.
3836 */
3837 public <B extends Buffer> B getBuffer(int length) {
3838 return (B)getBufferAtOffset(0L, length);
3839 }
3840
3841 /**
3842 * Read the NIO {@link Buffer} of remaining elements from the pointed memory location.<br>
3843 * @return an array of values of the requested length.
3844 * @throws UnsupportedOperationException if this pointer's target type is not a Java primitive type with a corresponding NIO {@link Buffer} class.
3845 */
3846 public <B extends Buffer> B getBuffer() {
3847 return (B)getBuffer((int)getValidElements());
3848 }
3849
3850 /**
3851 * Write an array of elements to the pointed memory location shifted by a byte offset.<br>
3852 * For pointers to primitive types (e.g. {@code Pointer<Integer> }), this method accepts primitive arrays (e.g. {@code int[] }) instead of arrays of boxed primitives (e.g. {@code Integer[] })
3853 */
3854 public Pointer<T> setArrayAtOffset(long byteOffset, Object array) {
3855 getIO("Cannot create sublist").setArray(this, byteOffset, array);
3856 return this;
3857 }
3858
3859 /**
3860 * Allocate enough memory for array.length values, copy the values of the array provided as argument into it and return a pointer to that memory.<br>
3861 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3862 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3863 * For pointers to primitive types (e.g. {@code Pointer<Integer> }), this method accepts primitive arrays (e.g. {@code int[] }) instead of arrays of boxed primitives (e.g. {@code Integer[] })
3864 * @param array primitive array containing the initial values for the created memory area
3865 * @return pointer to a new memory location that initially contains the consecutive values provided in argument
3866 */
3867 public static <T> Pointer<T> pointerToArray(Object array) {
3868 if (array == null)
3869 return null;
3870
3871 PointerIO<T> io = PointerIO.getArrayIO(array);
3872 if (io == null)
3873 throwBecauseUntyped("Cannot create pointer to array");
3874
3875 Pointer<T> ptr = allocateArray(io, java.lang.reflect.Array.getLength(array));
3876 io.setArray(ptr, 0, array);
3877 return ptr;
3878 }
3879
3880 /**
3881 * Write an array of elements to the pointed memory location.<br>
3882 * For pointers to primitive types (e.g. {@code Pointer<Integer> }), this method accepts primitive arrays (e.g. {@code int[] }) instead of arrays of boxed primitives (e.g. {@code Integer[] })
3883 */
3884 public Pointer<T> setArray(Object array) {
3885 return setArrayAtOffset(0L, array);
3886 }
3887
3888 //-- size primitive: SizeT --
3889
3890 /**
3891 * Allocate enough memory for a single SizeT value, copy the value provided in argument into it and return a pointer to that memory.<br>
3892 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3893 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3894 * @param value initial value for the created memory location
3895 * @return pointer to a new memory location that initially contains the SizeT value given in argument
3896 */
3897 public static Pointer<SizeT> pointerToSizeT(long value) {
3898 Pointer<SizeT> p = allocate(PointerIO.getSizeTInstance());
3899 p.setSizeT(value);
3900 return p;
3901 }
3902 /**
3903 * Allocate enough memory for a single SizeT value, copy the value provided in argument into it and return a pointer to that memory.<br>
3904 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3905 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3906 * @param value initial value for the created memory location
3907 * @return pointer to a new memory location that initially contains the SizeT value given in argument
3908 */
3909 public static Pointer<SizeT> pointerToSizeT(SizeT value) {
3910 Pointer<SizeT> p = allocate(PointerIO.getSizeTInstance());
3911 p.setSizeT(value);
3912 return p;
3913 }
3914 /**
3915 * Allocate enough memory for values.length SizeT values, copy the values provided as argument into it and return a pointer to that memory.<br>
3916 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3917 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3918 * The returned pointer is also an {@code Iterable<SizeT>} instance that can be safely iterated upon :
3919 <pre>{@code
3920 for (float f : pointerTo(1f, 2f, 3.3f))
3921 System.out.println(f); }</pre>
3922 * @param values initial values for the created memory location
3923 * @return pointer to a new memory location that initially contains the SizeT consecutive values provided in argument
3924 */
3925 public static Pointer<SizeT> pointerToSizeTs(long... values) {
3926 if (values == null)
3927 return null;
3928 return allocateArray(PointerIO.getSizeTInstance(), values.length).setSizeTsAtOffset(0, values);
3929 }
3930 /**
3931 * Allocate enough memory for values.length SizeT values, copy the values provided as argument into it and return a pointer to that memory.<br>
3932 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3933 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3934 * The returned pointer is also an {@code Iterable<SizeT>} instance that can be safely iterated upon :
3935 <pre>{@code
3936 for (float f : pointerTo(1f, 2f, 3.3f))
3937 System.out.println(f); }</pre>
3938 * @param values initial values for the created memory location
3939 * @return pointer to a new memory location that initially contains the SizeT consecutive values provided in argument
3940 */
3941 public static Pointer<SizeT> pointerToSizeTs(SizeT... values) {
3942 if (values == null)
3943 return null;
3944 return allocateArray(PointerIO.getSizeTInstance(), values.length).setSizeTsAtOffset(0, values);
3945 }
3946
3947 /**
3948 * Allocate enough memory for values.length SizeT values, copy the values provided as argument into it and return a pointer to that memory.<br>
3949 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3950 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3951 * The returned pointer is also an {@code Iterable<SizeT>} instance that can be safely iterated upon :
3952 <pre>{@code
3953 for (float f : pointerTo(1f, 2f, 3.3f))
3954 System.out.println(f); }</pre>
3955 * @param values initial values for the created memory location
3956 * @return pointer to a new memory location that initially contains the SizeT consecutive values provided in argument
3957 */
3958 public static Pointer<SizeT> pointerToSizeTs(int[] values) {
3959 if (values == null)
3960 return null;
3961 return allocateArray(PointerIO.getSizeTInstance(), values.length).setSizeTsAtOffset(0, values);
3962 }
3963
3964 /**
3965 * Allocate enough memory for arrayLength SizeT values and return a pointer to that memory.<br>
3966 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3967 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
3968 * The returned pointer is also an {@code Iterable<SizeT>} instance that can be safely iterated upon.
3969 * @return pointer to arrayLength zero-initialized SizeT consecutive values
3970 */
3971 public static Pointer<SizeT> allocateSizeTs(long arrayLength) {
3972 return allocateArray(PointerIO.getSizeTInstance(), arrayLength);
3973 }
3974 /**
3975 * Allocate enough memory for a SizeT value and return a pointer to it.<br>
3976 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
3977 * @return pointer to a single zero-initialized SizeT value
3978 */
3979 public static Pointer<SizeT> allocateSizeT() {
3980 return allocate(PointerIO.getSizeTInstance());
3981 }
3982
3983 /**
3984 * Read a SizeT value from the pointed memory location
3985 */
3986 public long getSizeT() {
3987 return SizeT.SIZE == 8 ?
3988 getLong() :
3989 getInt();
3990 }
3991 /**
3992 * Read a SizeT value from the pointed memory location shifted by a byte offset
3993 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#getSizeT()} over this method.
3994 */
3995 public long getSizeTAtOffset(long byteOffset) {
3996 return SizeT.SIZE == 8 ?
3997 getLongAtOffset(byteOffset) :
3998 getIntAtOffset(byteOffset);
3999 }
4000 /**
4001 * Read the nth contiguous SizeT value from the pointed memory location.<br>
4002 * Equivalent to <code>getSizeTAtOffset(valueIndex * SizeT.SIZE</code>.
4003 * @param valueIndex index of the value to read
4004 */
4005 public long getSizeTAtIndex(long valueIndex) {
4006 return getSizeTAtOffset(valueIndex * SizeT.SIZE);
4007 }
4008 /**
4009 * Read the array of remaining SizeT values from the pointed memory location
4010 */
4011 public long[] getSizeTs() {
4012 long rem = getValidElements("Cannot create array if remaining length is not known. Please use getSizeTs(int length) instead.");
4013 if (SizeT.SIZE == 8)
4014 return getLongs((int)rem);
4015 return getSizeTs((int)rem);
4016 }
4017 /**
4018 * Read an array of SizeT values of the specified length from the pointed memory location
4019 */
4020 public long[] getSizeTs(int arrayLength) {
4021 if (SizeT.SIZE == 8)
4022 return getLongs(arrayLength);
4023 return getSizeTsAtOffset(0, arrayLength);
4024 }
4025 /**
4026 * Read an array of SizeT values of the specified length from the pointed memory location shifted by a byte offset
4027 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#getSizeTs(int)} over this method.
4028 */
4029 public long[] getSizeTsAtOffset(long byteOffset, int arrayLength) {
4030 if (SizeT.SIZE == 8)
4031 return getLongsAtOffset(byteOffset, arrayLength);
4032
4033 int[] values = getIntsAtOffset(byteOffset, arrayLength);
4034 long[] ret = new long[arrayLength];
4035 for (int i = 0; i < arrayLength; i++) {
4036 ret[i] = //0xffffffffL &
4037 values[i];
4038 }
4039 return ret;
4040 }
4041
4042 /**
4043 * Write a SizeT value to the pointed memory location
4044 */
4045 public Pointer<T> setSizeT(long value) {
4046 if (SizeT.SIZE == 8)
4047 setLong(value);
4048 else {
4049 setInt(SizeT.safeIntCast(value));
4050 }
4051 return this;
4052 }
4053 /**
4054 * Write a SizeT value to the pointed memory location
4055 */
4056 public Pointer<T> setSizeT(SizeT value) {
4057 return setSizeT(value.longValue());
4058 }
4059 /**
4060 * Write a SizeT value to the pointed memory location shifted by a byte offset
4061 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#setSizeT(long)} over this method.
4062 */
4063 public Pointer<T> setSizeTAtOffset(long byteOffset, long value) {
4064 if (SizeT.SIZE == 8)
4065 setLongAtOffset(byteOffset, value);
4066 else {
4067 setIntAtOffset(byteOffset, SizeT.safeIntCast(value));
4068 }
4069 return this;
4070 }
4071 /**
4072 * Write the nth contiguous SizeT value to the pointed memory location.<br>
4073 * Equivalent to <code>setSizeTAtOffset(valueIndex * SizeT.SIZE, value)</code>.
4074 * @param valueIndex index of the value to write
4075 * @param value SizeT value to write
4076 */
4077 public Pointer<T> setSizeTAtIndex(long valueIndex, long value) {
4078 return setSizeTAtOffset(valueIndex * SizeT.SIZE, value);
4079 }
4080
4081 /**
4082 * Write a SizeT value to the pointed memory location shifted by a byte offset
4083 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#setSizeT(SizeT)} over this method.
4084 */
4085 public Pointer<T> setSizeTAtOffset(long byteOffset, SizeT value) {
4086 return setSizeTAtOffset(byteOffset, value.longValue());
4087 }
4088 /**
4089 * Write an array of SizeT values to the pointed memory location
4090 */
4091 public Pointer<T> setSizeTs(long[] values) {
4092 if (SizeT.SIZE == 8)
4093 return setLongs(values);
4094 return setSizeTsAtOffset(0, values);
4095 }
4096 /**
4097 * Write an array of SizeT values to the pointed memory location
4098 */
4099 public Pointer<T> setSizeTs(int[] values) {
4100 if (SizeT.SIZE == 4)
4101 return setInts(values);
4102 return setSizeTsAtOffset(0, values);
4103 }
4104 /**
4105 * Write an array of SizeT values to the pointed memory location
4106 */
4107 public Pointer<T> setSizeTs(SizeT[] values) {
4108 return setSizeTsAtOffset(0, values);
4109 }
4110 /**
4111 * Write an array of SizeT values to the pointed memory location shifted by a byte offset
4112 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#setSizeTs(long[])} over this method.
4113 */
4114 public Pointer<T> setSizeTsAtOffset(long byteOffset, long[] values) {
4115 return setSizeTsAtOffset(byteOffset, values, 0, values.length);
4116 }
4117 /**
4118 * Write an array of SizeT values to the pointed memory location shifted by a byte offset
4119 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#setSizeTs(long[])} over this method.
4120 */
4121 public abstract Pointer<T> setSizeTsAtOffset(long byteOffset, long[] values, int valuesOffset, int length);
4122 /**
4123 * Write an array of SizeT values to the pointed memory location shifted by a byte offset
4124 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#setSizeTs(SizeT...)} over this method.
4125 */
4126 public Pointer<T> setSizeTsAtOffset(long byteOffset, SizeT... values) {
4127 if (values == null)
4128 throw new IllegalArgumentException("Null values");
4129 int n = values.length, s = SizeT.SIZE;
4130 for (int i = 0; i < n; i++)
4131 setSizeTAtOffset(byteOffset + i * s, values[i].longValue());
4132 return this;
4133 }
4134 /**
4135 * Write an array of SizeT values to the pointed memory location shifted by a byte offset
4136 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#setSizeTs(int[])} over this method.
4137 */
4138 public abstract Pointer<T> setSizeTsAtOffset(long byteOffset, int[] values);
4139
4140 //-- size primitive: CLong --
4141
4142 /**
4143 * Allocate enough memory for a single CLong value, copy the value provided in argument into it and return a pointer to that memory.<br>
4144 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
4145 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
4146 * @param value initial value for the created memory location
4147 * @return pointer to a new memory location that initially contains the CLong value given in argument
4148 */
4149 public static Pointer<CLong> pointerToCLong(long value) {
4150 Pointer<CLong> p = allocate(PointerIO.getCLongInstance());
4151 p.setCLong(value);
4152 return p;
4153 }
4154 /**
4155 * Allocate enough memory for a single CLong value, copy the value provided in argument into it and return a pointer to that memory.<br>
4156 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
4157 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
4158 * @param value initial value for the created memory location
4159 * @return pointer to a new memory location that initially contains the CLong value given in argument
4160 */
4161 public static Pointer<CLong> pointerToCLong(CLong value) {
4162 Pointer<CLong> p = allocate(PointerIO.getCLongInstance());
4163 p.setCLong(value);
4164 return p;
4165 }
4166 /**
4167 * Allocate enough memory for values.length CLong values, copy the values provided as argument into it and return a pointer to that memory.<br>
4168 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
4169 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
4170 * The returned pointer is also an {@code Iterable<CLong>} instance that can be safely iterated upon :
4171 <pre>{@code
4172 for (float f : pointerTo(1f, 2f, 3.3f))
4173 System.out.println(f); }</pre>
4174 * @param values initial values for the created memory location
4175 * @return pointer to a new memory location that initially contains the CLong consecutive values provided in argument
4176 */
4177 public static Pointer<CLong> pointerToCLongs(long... values) {
4178 if (values == null)
4179 return null;
4180 return allocateArray(PointerIO.getCLongInstance(), values.length).setCLongsAtOffset(0, values);
4181 }
4182 /**
4183 * Allocate enough memory for values.length CLong values, copy the values provided as argument into it and return a pointer to that memory.<br>
4184 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
4185 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
4186 * The returned pointer is also an {@code Iterable<CLong>} instance that can be safely iterated upon :
4187 <pre>{@code
4188 for (float f : pointerTo(1f, 2f, 3.3f))
4189 System.out.println(f); }</pre>
4190 * @param values initial values for the created memory location
4191 * @return pointer to a new memory location that initially contains the CLong consecutive values provided in argument
4192 */
4193 public static Pointer<CLong> pointerToCLongs(CLong... values) {
4194 if (values == null)
4195 return null;
4196 return allocateArray(PointerIO.getCLongInstance(), values.length).setCLongsAtOffset(0, values);
4197 }
4198
4199 /**
4200 * Allocate enough memory for values.length CLong values, copy the values provided as argument into it and return a pointer to that memory.<br>
4201 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
4202 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
4203 * The returned pointer is also an {@code Iterable<CLong>} instance that can be safely iterated upon :
4204 <pre>{@code
4205 for (float f : pointerTo(1f, 2f, 3.3f))
4206 System.out.println(f); }</pre>
4207 * @param values initial values for the created memory location
4208 * @return pointer to a new memory location that initially contains the CLong consecutive values provided in argument
4209 */
4210 public static Pointer<CLong> pointerToCLongs(int[] values) {
4211 if (values == null)
4212 return null;
4213 return allocateArray(PointerIO.getCLongInstance(), values.length).setCLongsAtOffset(0, values);
4214 }
4215
4216 /**
4217 * Allocate enough memory for arrayLength CLong values and return a pointer to that memory.<br>
4218 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
4219 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
4220 * The returned pointer is also an {@code Iterable<CLong>} instance that can be safely iterated upon.
4221 * @return pointer to arrayLength zero-initialized CLong consecutive values
4222 */
4223 public static Pointer<CLong> allocateCLongs(long arrayLength) {
4224 return allocateArray(PointerIO.getCLongInstance(), arrayLength);
4225 }
4226 /**
4227 * Allocate enough memory for a CLong value and return a pointer to it.<br>
4228 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
4229 * @return pointer to a single zero-initialized CLong value
4230 */
4231 public static Pointer<CLong> allocateCLong() {
4232 return allocate(PointerIO.getCLongInstance());
4233 }
4234
4235 /**
4236 * Read a CLong value from the pointed memory location
4237 */
4238 public long getCLong() {
4239 return CLong.SIZE == 8 ?
4240 getLong() :
4241 getInt();
4242 }
4243 /**
4244 * Read a CLong value from the pointed memory location shifted by a byte offset
4245 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#getCLong()} over this method.
4246 */
4247 public long getCLongAtOffset(long byteOffset) {
4248 return CLong.SIZE == 8 ?
4249 getLongAtOffset(byteOffset) :
4250 getIntAtOffset(byteOffset);
4251 }
4252 /**
4253 * Read the nth contiguous CLong value from the pointed memory location.<br>
4254 * Equivalent to <code>getCLongAtOffset(valueIndex * CLong.SIZE</code>.
4255 * @param valueIndex index of the value to read
4256 */
4257 public long getCLongAtIndex(long valueIndex) {
4258 return getCLongAtOffset(valueIndex * CLong.SIZE);
4259 }
4260 /**
4261 * Read the array of remaining CLong values from the pointed memory location
4262 */
4263 public long[] getCLongs() {
4264 long rem = getValidElements("Cannot create array if remaining length is not known. Please use getCLongs(int length) instead.");
4265 if (CLong.SIZE == 8)
4266 return getLongs((int)rem);
4267 return getCLongs((int)rem);
4268 }
4269 /**
4270 * Read an array of CLong values of the specified length from the pointed memory location
4271 */
4272 public long[] getCLongs(int arrayLength) {
4273 if (CLong.SIZE == 8)
4274 return getLongs(arrayLength);
4275 return getCLongsAtOffset(0, arrayLength);
4276 }
4277 /**
4278 * Read an array of CLong values of the specified length from the pointed memory location shifted by a byte offset
4279 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#getCLongs(int)} over this method.
4280 */
4281 public long[] getCLongsAtOffset(long byteOffset, int arrayLength) {
4282 if (CLong.SIZE == 8)
4283 return getLongsAtOffset(byteOffset, arrayLength);
4284
4285 int[] values = getIntsAtOffset(byteOffset, arrayLength);
4286 long[] ret = new long[arrayLength];
4287 for (int i = 0; i < arrayLength; i++) {
4288 ret[i] = //0xffffffffL &
4289 values[i];
4290 }
4291 return ret;
4292 }
4293
4294 /**
4295 * Write a CLong value to the pointed memory location
4296 */
4297 public Pointer<T> setCLong(long value) {
4298 if (CLong.SIZE == 8)
4299 setLong(value);
4300 else {
4301 setInt(SizeT.safeIntCast(value));
4302 }
4303 return this;
4304 }
4305 /**
4306 * Write a CLong value to the pointed memory location
4307 */
4308 public Pointer<T> setCLong(CLong value) {
4309 return setCLong(value.longValue());
4310 }
4311 /**
4312 * Write a CLong value to the pointed memory location shifted by a byte offset
4313 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#setCLong(long)} over this method.
4314 */
4315 public Pointer<T> setCLongAtOffset(long byteOffset, long value) {
4316 if (CLong.SIZE == 8)
4317 setLongAtOffset(byteOffset, value);
4318 else {
4319 setIntAtOffset(byteOffset, SizeT.safeIntCast(value));
4320 }
4321 return this;
4322 }
4323 /**
4324 * Write the nth contiguous CLong value to the pointed memory location.<br>
4325 * Equivalent to <code>setCLongAtOffset(valueIndex * CLong.SIZE, value)</code>.
4326 * @param valueIndex index of the value to write
4327 * @param value CLong value to write
4328 */
4329 public Pointer<T> setCLongAtIndex(long valueIndex, long value) {
4330 return setCLongAtOffset(valueIndex * CLong.SIZE, value);
4331 }
4332
4333 /**
4334 * Write a CLong value to the pointed memory location shifted by a byte offset
4335 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#setCLong(CLong)} over this method.
4336 */
4337 public Pointer<T> setCLongAtOffset(long byteOffset, CLong value) {
4338 return setCLongAtOffset(byteOffset, value.longValue());
4339 }
4340 /**
4341 * Write an array of CLong values to the pointed memory location
4342 */
4343 public Pointer<T> setCLongs(long[] values) {
4344 if (CLong.SIZE == 8)
4345 return setLongs(values);
4346 return setCLongsAtOffset(0, values);
4347 }
4348 /**
4349 * Write an array of CLong values to the pointed memory location
4350 */
4351 public Pointer<T> setCLongs(int[] values) {
4352 if (CLong.SIZE == 4)
4353 return setInts(values);
4354 return setCLongsAtOffset(0, values);
4355 }
4356 /**
4357 * Write an array of CLong values to the pointed memory location
4358 */
4359 public Pointer<T> setCLongs(CLong[] values) {
4360 return setCLongsAtOffset(0, values);
4361 }
4362 /**
4363 * Write an array of CLong values to the pointed memory location shifted by a byte offset
4364 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#setCLongs(long[])} over this method.
4365 */
4366 public Pointer<T> setCLongsAtOffset(long byteOffset, long[] values) {
4367 return setCLongsAtOffset(byteOffset, values, 0, values.length);
4368 }
4369 /**
4370 * Write an array of CLong values to the pointed memory location shifted by a byte offset
4371 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#setCLongs(long[])} over this method.
4372 */
4373 public abstract Pointer<T> setCLongsAtOffset(long byteOffset, long[] values, int valuesOffset, int length);
4374 /**
4375 * Write an array of CLong values to the pointed memory location shifted by a byte offset
4376 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#setCLongs(CLong...)} over this method.
4377 */
4378 public Pointer<T> setCLongsAtOffset(long byteOffset, CLong... values) {
4379 if (values == null)
4380 throw new IllegalArgumentException("Null values");
4381 int n = values.length, s = CLong.SIZE;
4382 for (int i = 0; i < n; i++)
4383 setCLongAtOffset(byteOffset + i * s, values[i].longValue());
4384 return this;
4385 }
4386 /**
4387 * Write an array of CLong values to the pointed memory location shifted by a byte offset
4388 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#setCLongs(int[])} over this method.
4389 */
4390 public abstract Pointer<T> setCLongsAtOffset(long byteOffset, int[] values);
4391
4392
4393 void setSignedIntegralAtOffset(long byteOffset, long value, long sizeOfIntegral) {
4394 switch ((int)sizeOfIntegral) {
4395 case 1:
4396 if (value > Byte.MAX_VALUE || value < Byte.MIN_VALUE)
4397 throw new RuntimeException("Value out of byte bounds : " + value);
4398 setByteAtOffset(byteOffset, (byte)value);
4399 break;
4400 case 2:
4401 if (value > Short.MAX_VALUE || value < Short.MIN_VALUE)
4402 throw new RuntimeException("Value out of short bounds : " + value);
4403 setShortAtOffset(byteOffset, (short)value);
4404 break;
4405 case 4:
4406 if (value > Integer.MAX_VALUE || value < Integer.MIN_VALUE)
4407 throw new RuntimeException("Value out of int bounds : " + value);
4408 setIntAtOffset(byteOffset, (int)value);
4409 break;
4410 case 8:
4411 setLongAtOffset(byteOffset, value);
4412 break;
4413 default:
4414 throw new IllegalArgumentException("Cannot write integral type of size " + sizeOfIntegral + " (value = " + value + ")");
4415 }
4416 }
4417 long getSignedIntegralAtOffset(long byteOffset, long sizeOfIntegral) {
4418 switch ((int)sizeOfIntegral) {
4419 case 1:
4420 return getByteAtOffset(byteOffset);
4421 case 2:
4422 return getShortAtOffset(byteOffset);
4423 case 4:
4424 return getIntAtOffset(byteOffset);
4425 case 8:
4426 return getLongAtOffset(byteOffset);
4427 default:
4428 throw new IllegalArgumentException("Cannot read integral type of size " + sizeOfIntegral);
4429 }
4430 }
4431
4432 /**
4433 * Allocate enough memory for a single pointer value, copy the value provided in argument into it and return a pointer to that memory.<br>
4434 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
4435 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
4436 * @param value initial value for the created memory location
4437 * @return pointer to a new memory location that initially contains the pointer value given in argument
4438 */
4439 public static <T> Pointer<Pointer<T>> pointerToPointer(Pointer<T> value) {
4440 Pointer<Pointer<T>> p = (Pointer<Pointer<T>>)(Pointer)allocate(PointerIO.getPointerInstance());
4441 p.setPointerAtOffset(0, value);
4442 return p;
4443 }
4444
4445 /**
4446 * Allocate enough memory for values.length pointer values, copy the values provided as argument into it and return a pointer to that memory.<br>
4447 * The memory will be automatically be freed when the pointer is garbage-collected or upon manual calls to {@link Pointer#release()}.<br>
4448 * The pointer won't be garbage-collected until all its views are garbage-collected themselves ({@link Pointer#offset(long)}, {@link Pointer#next(long)}, {@link Pointer#next()}).<br>
4449 * The returned pointer is also an {@code Iterable<Pointer>} instance that can be safely iterated upon :
4450 <pre>{@code
4451 for (float f : pointerTo(1f, 2f, 3.3f))
4452 System.out.println(f); }</pre>
4453 * @param values initial values for the created memory location
4454 * @return pointer to a new memory location that initially contains the pointer consecutive values provided in argument
4455 */
4456 public static <T> Pointer<Pointer<T>> pointerToPointers(Pointer<T>... values) {
4457 if (values == null)
4458 return null;
4459 int n = values.length, s = Pointer.SIZE;
4460 PointerIO<Pointer> pio = PointerIO.getPointerInstance(); // TODO get actual pointer instances PointerIO !!!
4461 Pointer<Pointer<T>> p = (Pointer<Pointer<T>>)(Pointer)allocateArray(pio, n);
4462 for (int i = 0; i < n; i++) {
4463 p.setPointerAtOffset(i * s, values[i]);
4464 }
4465 return p;
4466 }
4467
4468 /**
4469 * Copy all values from an NIO buffer to the pointed memory location shifted by a byte offset
4470 */
4471 public Pointer<T> setValuesAtOffset(long byteOffset, Buffer values) {
4472 if (values instanceof IntBuffer) {
4473 setIntsAtOffset(byteOffset, (IntBuffer)values);
4474 return this;
4475 }
4476 if (values instanceof LongBuffer) {
4477 setLongsAtOffset(byteOffset, (LongBuffer)values);
4478 return this;
4479 }
4480 if (values instanceof ShortBuffer) {
4481 setShortsAtOffset(byteOffset, (ShortBuffer)values);
4482 return this;
4483 }
4484 if (values instanceof ByteBuffer) {
4485 setBytesAtOffset(byteOffset, (ByteBuffer)values);
4486 return this;
4487 }
4488 if (values instanceof CharBuffer) {
4489 setCharsAtOffset(byteOffset, (CharBuffer)values);
4490 return this;
4491 }
4492 if (values instanceof FloatBuffer) {
4493 setFloatsAtOffset(byteOffset, (FloatBuffer)values);
4494 return this;
4495 }
4496 if (values instanceof DoubleBuffer) {
4497 setDoublesAtOffset(byteOffset, (DoubleBuffer)values);
4498 return this;
4499 }
4500 throw new UnsupportedOperationException("Unhandled buffer type : " + values.getClass().getName());
4501 }
4502
4503 /**
4504 * Copy length values from an NIO buffer (beginning at element at valuesOffset index) to the pointed memory location shifted by a byte offset
4505 */
4506 public Pointer<T> setValuesAtOffset(long byteOffset, Buffer values, int valuesOffset, int length) {
4507 if (values instanceof IntBuffer) {
4508 setIntsAtOffset(byteOffset, (IntBuffer)values, valuesOffset, length);
4509 return this;
4510 }
4511 if (values instanceof LongBuffer) {
4512 setLongsAtOffset(byteOffset, (LongBuffer)values, valuesOffset, length);
4513 return this;
4514 }
4515 if (values instanceof ShortBuffer) {
4516 setShortsAtOffset(byteOffset, (ShortBuffer)values, valuesOffset, length);
4517 return this;
4518 }
4519 if (values instanceof ByteBuffer) {
4520 setBytesAtOffset(byteOffset, (ByteBuffer)values, valuesOffset, length);
4521 return this;
4522 }
4523 if (values instanceof CharBuffer) {
4524 setCharsAtOffset(byteOffset, (CharBuffer)values, valuesOffset, length);
4525 return this;
4526 }
4527 if (values instanceof FloatBuffer) {
4528 setFloatsAtOffset(byteOffset, (FloatBuffer)values, valuesOffset, length);
4529 return this;
4530 }
4531 if (values instanceof DoubleBuffer) {
4532 setDoublesAtOffset(byteOffset, (DoubleBuffer)values, valuesOffset, length);
4533 return this;
4534 }
4535 throw new UnsupportedOperationException("Unhandled buffer type : " + values.getClass().getName());
4536 }
4537
4538 /**
4539 * Copy values from an NIO buffer to the pointed memory location
4540 */
4541 public Pointer<T> setValues(Buffer values) {
4542 if (values instanceof IntBuffer) {
4543 setInts((IntBuffer)values);
4544 return this;
4545 }
4546 if (values instanceof LongBuffer) {
4547 setLongs((LongBuffer)values);
4548 return this;
4549 }
4550 if (values instanceof ShortBuffer) {
4551 setShorts((ShortBuffer)values);
4552 return this;
4553 }
4554 if (values instanceof ByteBuffer) {
4555 setBytes((ByteBuffer)values);
4556 return this;
4557 }
4558 if (values instanceof CharBuffer) {
4559 setChars((CharBuffer)values);
4560 return this;
4561 }
4562 if (values instanceof FloatBuffer) {
4563 setFloats((FloatBuffer)values);
4564 return this;
4565 }
4566 if (values instanceof DoubleBuffer) {
4567 setDoubles((DoubleBuffer)values);
4568 return this;
4569 }
4570 throw new UnsupportedOperationException("Unhandled buffer type : " + values.getClass().getName());
4571 }
4572
4573 /**
4574 * Copy bytes from the memory location indicated by this pointer to that of another pointer (with byte offsets for both the source and the destination), using the @see <a href="http://www.cplusplus.com/reference/clibrary/cstring/memcpy/">memcpy</a> C function.<br>
4575 * If the destination and source memory locations are likely to overlap, {@link Pointer#moveBytesAtOffsetTo(long, Pointer, long, long)} must be used instead.
4576 */
4577 @Deprecated
4578 public Pointer<T> copyBytesAtOffsetTo(long byteOffset, Pointer<?> destination, long byteOffsetInDestination, long byteCount) {
4579 long checkedPeer = peer + byteOffset;
4580 if (validStart != UNKNOWN_VALIDITY)
4581 checkPeer(checkedPeer, byteCount);
4582 JNI.memcpy(destination.getCheckedPeer(byteOffsetInDestination, byteCount), checkedPeer, byteCount);
4583 return this;
4584 }
4585
4586 /**
4587 * Copy bytes from the memory location indicated by this pointer to that of another pointer using the @see <a href="http://www.cplusplus.com/reference/clibrary/cstring/memcpy/">memcpy</a> C function.<br>
4588 * If the destination and source memory locations are likely to overlap, {@link Pointer#moveBytesAtOffsetTo(long, Pointer, long, long)} must be used instead.<br>
4589 * See {@link Pointer#copyBytesAtOffsetTo(long, Pointer, long, long)} for more options.
4590 */
4591 @Deprecated
4592 public Pointer<T> copyBytesTo(Pointer<?> destination, long byteCount) {
4593 return copyBytesAtOffsetTo(0, destination, 0, byteCount);
4594 }
4595
4596 /**
4597 * Copy bytes from the memory location indicated by this pointer to that of another pointer (with byte offsets for both the source and the destination), using the @see <a href="http://www.cplusplus.com/reference/clibrary/cstring/memmove/">memmove</a> C function.<br>
4598 * Works even if the destination and source memory locations are overlapping.
4599 */
4600 @Deprecated
4601 public Pointer<T> moveBytesAtOffsetTo(long byteOffset, Pointer<?> destination, long byteOffsetInDestination, long byteCount) {
4602 long checkedPeer = peer + byteOffset;
4603 if (validStart != UNKNOWN_VALIDITY)
4604 checkPeer(checkedPeer, byteCount);
4605 JNI.memmove(destination.getCheckedPeer(byteOffsetInDestination, byteCount), checkedPeer, byteCount);
4606 return this;
4607 }
4608
4609 /**
4610 * Copy bytes from the memory location indicated by this pointer to that of another pointer, using the @see <a href="http://www.cplusplus.com/reference/clibrary/cstring/memmove/">memmove</a> C function.<br>
4611 * Works even if the destination and source memory locations are overlapping.
4612 */
4613 public Pointer<T> moveBytesTo(Pointer<?> destination, long byteCount) {
4614 return moveBytesAtOffsetTo(0, destination, 0, byteCount);
4615 }
4616
4617 /**
4618 * Copy all valid bytes from the memory location indicated by this pointer to that of another pointer, using the @see <a href="http://www.cplusplus.com/reference/clibrary/cstring/memmove/">memmove</a> C function.<br>
4619 * Works even if the destination and source memory locations are overlapping.
4620 */
4621 public Pointer<T> moveBytesTo(Pointer<?> destination) {
4622 return moveBytesTo(destination, getValidBytes("Cannot move an unbounded memory location. Please use validBytes(long)."));
4623 }
4624
4625 final long getValidBytes(String error) {
4626 long rem = getValidBytes();
4627 if (rem < 0)
4628 throw new IndexOutOfBoundsException(error);
4629
4630 return rem;
4631 }
4632 final long getValidElements(String error) {
4633 long rem = getValidElements();
4634 if (rem < 0)
4635 throw new IndexOutOfBoundsException(error);
4636
4637 return rem;
4638 }
4639 final PointerIO<T> getIO(String error) {
4640 PointerIO<T> io = getIO();
4641 if (io == null)
4642 throwBecauseUntyped(error);
4643 return io;
4644 }
4645
4646 /**
4647 * Copy remaining bytes from this pointer to a destination using the @see <a href="http://www.cplusplus.com/reference/clibrary/cstring/memcpy/">memcpy</a> C function (see {@link Pointer#copyBytesTo(Pointer, long)}, {@link Pointer#getValidBytes()})
4648 */
4649 public Pointer<T> copyTo(Pointer<?> destination) {
4650 return copyTo(destination, getValidElements());
4651 }
4652
4653 /**
4654 * Copy remaining elements from this pointer to a destination using the @see <a href="http://www.cplusplus.com/reference/clibrary/cstring/memcpy/">memcpy</a> C function (see {@link Pointer#copyBytesAtOffsetTo(long, Pointer, long, long)}, {@link Pointer#getValidBytes})
4655 */
4656 public Pointer<T> copyTo(Pointer<?> destination, long elementCount) {
4657 PointerIO<T> io = getIO("Cannot copy untyped pointer without byte count information. Please use copyBytesAtOffsetTo(offset, destination, destinationOffset, byteCount) instead");
4658 return copyBytesAtOffsetTo(0, destination, 0, elementCount * io.getTargetSize());
4659 }
4660
4661 /**
4662 * Find the first appearance of the sequence of valid bytes pointed by needle in the memory area pointed to by this bounded pointer (behaviour equivalent to <a href="http://linux.die.net/man/3/memmem">memmem</a>, which is used underneath on platforms where it is available)
4663 */
4664 public Pointer<T> find(Pointer<?> needle) {
4665 if (needle == null)
4666 return null;
4667 long firstOccurrence = JNI.memmem(
4668 getPeer(),
4669 getValidBytes("Cannot search an unbounded memory area. Please set bounds with validBytes(long)."),
4670 needle.getPeer(),
4671 needle.getValidBytes("Cannot search for an unbounded content. Please set bounds with validBytes(long).")
4672 );
4673 return pointerToAddress(firstOccurrence, io);
4674 }
4675
4676 /**
4677 * Find the last appearance of the sequence of valid bytes pointed by needle in the memory area pointed to by this bounded pointer (also see {@link Pointer#find(Pointer)}).
4678 */
4679 public Pointer<T> findLast(Pointer<?> needle) {
4680 if (needle == null)
4681 return null;
4682 long lastOccurrence = JNI.memmem_last(
4683 getPeer(),
4684 getValidBytes("Cannot search an unbounded memory area. Please set bounds with validBytes(long)."),
4685 needle.getPeer(),
4686 needle.getValidBytes("Cannot search for an unbounded content. Please set bounds with validBytes(long).")
4687 );
4688 return pointerToAddress(lastOccurrence, io);
4689 }
4690
4691
4692 //-- primitive: int --
4693
4694 /**
4695 * Write a int value to the pointed memory location
4696 */
4697 public abstract Pointer<T> setInt(int value);
4698
4699 /**
4700 * Write a int value to the pointed memory location shifted by a byte offset
4701 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#setInt(int)} over this method.
4702 */
4703 public abstract Pointer<T> setIntAtOffset(long byteOffset, int value);
4704
4705 /**
4706 * Write the nth contiguous int value to the pointed memory location.<br>
4707 * Equivalent to <code>setIntAtOffset(valueIndex * 4, value)</code>.
4708 * @param valueIndex index of the value to write
4709 * @param value int value to write
4710 */
4711 public Pointer<T> setIntAtIndex(long valueIndex, int value) {
4712 return setIntAtOffset(valueIndex * 4, value);
4713 }
4714
4715 /**
4716 * Write an array of int values of the specified length to the pointed memory location
4717 */
4718 public Pointer<T> setInts(int[] values) {
4719 return setIntsAtOffset(0, values, 0, values.length);
4720 }
4721
4722 /**
4723 * Write an array of int values of the specified length to the pointed memory location shifted by a byte offset
4724 */
4725 public Pointer<T> setIntsAtOffset(long byteOffset, int[] values) {
4726 return setIntsAtOffset(byteOffset, values, 0, values.length);
4727 }
4728
4729 /**
4730 * Write an array of int values of the specified length to the pointed memory location shifted by a byte offset, reading values at the given array offset and for the given length from the provided array.
4731 */
4732 public Pointer<T> setIntsAtOffset(long byteOffset, int[] values, int valuesOffset, int length) {
4733 long checkedPeer = peer + byteOffset;
4734 if (validStart != UNKNOWN_VALIDITY)
4735 checkPeer(checkedPeer, 4 * length);
4736 if (!isOrdered()) {
4737 JNI.set_int_array_disordered(checkedPeer, values, valuesOffset, length);
4738 return this;
4739 }
4740 JNI.set_int_array(checkedPeer, values, valuesOffset, length);
4741 return this;
4742 }
4743
4744 /**
4745 * Read a int value from the pointed memory location
4746 */
4747 public abstract int getInt();
4748
4749 /**
4750 * Read a int value from the pointed memory location shifted by a byte offset
4751 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#getInt()} over this method.
4752 */
4753 public abstract int getIntAtOffset(long byteOffset);
4754
4755 /**
4756 * Read the nth contiguous int value from the pointed memory location.<br>
4757 * Equivalent to <code>getIntAtOffset(valueIndex * 4)</code>.
4758 * @param valueIndex index of the value to read
4759 */
4760 public int getIntAtIndex(long valueIndex) {
4761 return getIntAtOffset(valueIndex * 4);
4762 }
4763
4764 /**
4765 * Read an array of int values of the specified length from the pointed memory location
4766 */
4767 public int[] getInts(int length) {
4768 return getIntsAtOffset(0, length);
4769 }
4770
4771
4772 /**
4773 * Read the array of remaining int values from the pointed memory location
4774 */
4775 public int[] getInts() {
4776 long validBytes = getValidBytes("Cannot create array if remaining length is not known. Please use getInts(int length) instead.");
4777 return getInts((int)(validBytes / 4));
4778 }
4779
4780 /**
4781 * Read an array of int values of the specified length from the pointed memory location shifted by a byte offset
4782 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#getInts(int)} over this method.
4783 */
4784 public int[] getIntsAtOffset(long byteOffset, int length) {
4785 long checkedPeer = peer + byteOffset;
4786 if (validStart != UNKNOWN_VALIDITY)
4787 checkPeer(checkedPeer, 4 * length);
4788 if (!isOrdered())
4789 return JNI.get_int_array_disordered(checkedPeer, length);
4790 return JNI.get_int_array(checkedPeer, length);
4791 }
4792
4793 //-- primitive: long --
4794
4795 /**
4796 * Write a long value to the pointed memory location
4797 */
4798 public abstract Pointer<T> setLong(long value);
4799
4800 /**
4801 * Write a long value to the pointed memory location shifted by a byte offset
4802 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#setLong(long)} over this method.
4803 */
4804 public abstract Pointer<T> setLongAtOffset(long byteOffset, long value);
4805
4806 /**
4807 * Write the nth contiguous long value to the pointed memory location.<br>
4808 * Equivalent to <code>setLongAtOffset(valueIndex * 8, value)</code>.
4809 * @param valueIndex index of the value to write
4810 * @param value long value to write
4811 */
4812 public Pointer<T> setLongAtIndex(long valueIndex, long value) {
4813 return setLongAtOffset(valueIndex * 8, value);
4814 }
4815
4816 /**
4817 * Write an array of long values of the specified length to the pointed memory location
4818 */
4819 public Pointer<T> setLongs(long[] values) {
4820 return setLongsAtOffset(0, values, 0, values.length);
4821 }
4822
4823 /**
4824 * Write an array of long values of the specified length to the pointed memory location shifted by a byte offset
4825 */
4826 public Pointer<T> setLongsAtOffset(long byteOffset, long[] values) {
4827 return setLongsAtOffset(byteOffset, values, 0, values.length);
4828 }
4829
4830 /**
4831 * Write an array of long values of the specified length to the pointed memory location shifted by a byte offset, reading values at the given array offset and for the given length from the provided array.
4832 */
4833 public Pointer<T> setLongsAtOffset(long byteOffset, long[] values, int valuesOffset, int length) {
4834 long checkedPeer = peer + byteOffset;
4835 if (validStart != UNKNOWN_VALIDITY)
4836 checkPeer(checkedPeer, 8 * length);
4837 if (!isOrdered()) {
4838 JNI.set_long_array_disordered(checkedPeer, values, valuesOffset, length);
4839 return this;
4840 }
4841 JNI.set_long_array(checkedPeer, values, valuesOffset, length);
4842 return this;
4843 }
4844
4845 /**
4846 * Read a long value from the pointed memory location
4847 */
4848 public abstract long getLong();
4849
4850 /**
4851 * Read a long value from the pointed memory location shifted by a byte offset
4852 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#getLong()} over this method.
4853 */
4854 public abstract long getLongAtOffset(long byteOffset);
4855
4856 /**
4857 * Read the nth contiguous long value from the pointed memory location.<br>
4858 * Equivalent to <code>getLongAtOffset(valueIndex * 8)</code>.
4859 * @param valueIndex index of the value to read
4860 */
4861 public long getLongAtIndex(long valueIndex) {
4862 return getLongAtOffset(valueIndex * 8);
4863 }
4864
4865 /**
4866 * Read an array of long values of the specified length from the pointed memory location
4867 */
4868 public long[] getLongs(int length) {
4869 return getLongsAtOffset(0, length);
4870 }
4871
4872
4873 /**
4874 * Read the array of remaining long values from the pointed memory location
4875 */
4876 public long[] getLongs() {
4877 long validBytes = getValidBytes("Cannot create array if remaining length is not known. Please use getLongs(int length) instead.");
4878 return getLongs((int)(validBytes / 8));
4879 }
4880
4881 /**
4882 * Read an array of long values of the specified length from the pointed memory location shifted by a byte offset
4883 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#getLongs(int)} over this method.
4884 */
4885 public long[] getLongsAtOffset(long byteOffset, int length) {
4886 long checkedPeer = peer + byteOffset;
4887 if (validStart != UNKNOWN_VALIDITY)
4888 checkPeer(checkedPeer, 8 * length);
4889 if (!isOrdered())
4890 return JNI.get_long_array_disordered(checkedPeer, length);
4891 return JNI.get_long_array(checkedPeer, length);
4892 }
4893
4894 //-- primitive: short --
4895
4896 /**
4897 * Write a short value to the pointed memory location
4898 */
4899 public abstract Pointer<T> setShort(short value);
4900
4901 /**
4902 * Write a short value to the pointed memory location shifted by a byte offset
4903 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#setShort(short)} over this method.
4904 */
4905 public abstract Pointer<T> setShortAtOffset(long byteOffset, short value);
4906
4907 /**
4908 * Write the nth contiguous short value to the pointed memory location.<br>
4909 * Equivalent to <code>setShortAtOffset(valueIndex * 2, value)</code>.
4910 * @param valueIndex index of the value to write
4911 * @param value short value to write
4912 */
4913 public Pointer<T> setShortAtIndex(long valueIndex, short value) {
4914 return setShortAtOffset(valueIndex * 2, value);
4915 }
4916
4917 /**
4918 * Write an array of short values of the specified length to the pointed memory location
4919 */
4920 public Pointer<T> setShorts(short[] values) {
4921 return setShortsAtOffset(0, values, 0, values.length);
4922 }
4923
4924 /**
4925 * Write an array of short values of the specified length to the pointed memory location shifted by a byte offset
4926 */
4927 public Pointer<T> setShortsAtOffset(long byteOffset, short[] values) {
4928 return setShortsAtOffset(byteOffset, values, 0, values.length);
4929 }
4930
4931 /**
4932 * Write an array of short values of the specified length to the pointed memory location shifted by a byte offset, reading values at the given array offset and for the given length from the provided array.
4933 */
4934 public Pointer<T> setShortsAtOffset(long byteOffset, short[] values, int valuesOffset, int length) {
4935 long checkedPeer = peer + byteOffset;
4936 if (validStart != UNKNOWN_VALIDITY)
4937 checkPeer(checkedPeer, 2 * length);
4938 if (!isOrdered()) {
4939 JNI.set_short_array_disordered(checkedPeer, values, valuesOffset, length);
4940 return this;
4941 }
4942 JNI.set_short_array(checkedPeer, values, valuesOffset, length);
4943 return this;
4944 }
4945
4946 /**
4947 * Read a short value from the pointed memory location
4948 */
4949 public abstract short getShort();
4950
4951 /**
4952 * Read a short value from the pointed memory location shifted by a byte offset
4953 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#getShort()} over this method.
4954 */
4955 public abstract short getShortAtOffset(long byteOffset);
4956
4957 /**
4958 * Read the nth contiguous short value from the pointed memory location.<br>
4959 * Equivalent to <code>getShortAtOffset(valueIndex * 2)</code>.
4960 * @param valueIndex index of the value to read
4961 */
4962 public short getShortAtIndex(long valueIndex) {
4963 return getShortAtOffset(valueIndex * 2);
4964 }
4965
4966 /**
4967 * Read an array of short values of the specified length from the pointed memory location
4968 */
4969 public short[] getShorts(int length) {
4970 return getShortsAtOffset(0, length);
4971 }
4972
4973
4974 /**
4975 * Read the array of remaining short values from the pointed memory location
4976 */
4977 public short[] getShorts() {
4978 long validBytes = getValidBytes("Cannot create array if remaining length is not known. Please use getShorts(int length) instead.");
4979 return getShorts((int)(validBytes / 2));
4980 }
4981
4982 /**
4983 * Read an array of short values of the specified length from the pointed memory location shifted by a byte offset
4984 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#getShorts(int)} over this method.
4985 */
4986 public short[] getShortsAtOffset(long byteOffset, int length) {
4987 long checkedPeer = peer + byteOffset;
4988 if (validStart != UNKNOWN_VALIDITY)
4989 checkPeer(checkedPeer, 2 * length);
4990 if (!isOrdered())
4991 return JNI.get_short_array_disordered(checkedPeer, length);
4992 return JNI.get_short_array(checkedPeer, length);
4993 }
4994
4995 //-- primitive: byte --
4996
4997 /**
4998 * Write a byte value to the pointed memory location
4999 */
5000 public abstract Pointer<T> setByte(byte value);
5001
5002 /**
5003 * Write a byte value to the pointed memory location shifted by a byte offset
5004 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#setByte(byte)} over this method.
5005 */
5006 public abstract Pointer<T> setByteAtOffset(long byteOffset, byte value);
5007
5008 /**
5009 * Write the nth contiguous byte value to the pointed memory location.<br>
5010 * Equivalent to <code>setByteAtOffset(valueIndex * 1, value)</code>.
5011 * @param valueIndex index of the value to write
5012 * @param value byte value to write
5013 */
5014 public Pointer<T> setByteAtIndex(long valueIndex, byte value) {
5015 return setByteAtOffset(valueIndex * 1, value);
5016 }
5017
5018 /**
5019 * Write an array of byte values of the specified length to the pointed memory location
5020 */
5021 public Pointer<T> setBytes(byte[] values) {
5022 return setBytesAtOffset(0, values, 0, values.length);
5023 }
5024
5025 /**
5026 * Write an array of byte values of the specified length to the pointed memory location shifted by a byte offset
5027 */
5028 public Pointer<T> setBytesAtOffset(long byteOffset, byte[] values) {
5029 return setBytesAtOffset(byteOffset, values, 0, values.length);
5030 }
5031
5032 /**
5033 * Write an array of byte values of the specified length to the pointed memory location shifted by a byte offset, reading values at the given array offset and for the given length from the provided array.
5034 */
5035 public Pointer<T> setBytesAtOffset(long byteOffset, byte[] values, int valuesOffset, int length) {
5036 long checkedPeer = peer + byteOffset;
5037 if (validStart != UNKNOWN_VALIDITY)
5038 checkPeer(checkedPeer, 1 * length);
5039 JNI.set_byte_array(checkedPeer, values, valuesOffset, length);
5040 return this;
5041 }
5042
5043 /**
5044 * Read a byte value from the pointed memory location
5045 */
5046 public abstract byte getByte();
5047
5048 /**
5049 * Read a byte value from the pointed memory location shifted by a byte offset
5050 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#getByte()} over this method.
5051 */
5052 public abstract byte getByteAtOffset(long byteOffset);
5053
5054 /**
5055 * Read the nth contiguous byte value from the pointed memory location.<br>
5056 * Equivalent to <code>getByteAtOffset(valueIndex * 1)</code>.
5057 * @param valueIndex index of the value to read
5058 */
5059 public byte getByteAtIndex(long valueIndex) {
5060 return getByteAtOffset(valueIndex * 1);
5061 }
5062
5063 /**
5064 * Read an array of byte values of the specified length from the pointed memory location
5065 */
5066 public byte[] getBytes(int length) {
5067 return getBytesAtOffset(0, length);
5068 }
5069
5070
5071 /**
5072 * Read the array of remaining byte values from the pointed memory location
5073 */
5074 public byte[] getBytes() {
5075 long validBytes = getValidBytes("Cannot create array if remaining length is not known. Please use getBytes(int length) instead.");
5076 return getBytes((int)(validBytes / 1));
5077 }
5078
5079 /**
5080 * Read an array of byte values of the specified length from the pointed memory location shifted by a byte offset
5081 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#getBytes(int)} over this method.
5082 */
5083 public byte[] getBytesAtOffset(long byteOffset, int length) {
5084 long checkedPeer = peer + byteOffset;
5085 if (validStart != UNKNOWN_VALIDITY)
5086 checkPeer(checkedPeer, 1 * length);
5087 return JNI.get_byte_array(checkedPeer, length);
5088 }
5089
5090 //-- primitive: char --
5091
5092 /**
5093 * Write a char value to the pointed memory location
5094 */
5095 public abstract Pointer<T> setChar(char value);
5096
5097 /**
5098 * Write a char value to the pointed memory location shifted by a byte offset
5099 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#setChar(char)} over this method.
5100 */
5101 public abstract Pointer<T> setCharAtOffset(long byteOffset, char value);
5102
5103 /**
5104 * Write the nth contiguous char value to the pointed memory location.<br>
5105 * Equivalent to <code>setCharAtOffset(valueIndex * Platform.WCHAR_T_SIZE, value)</code>.
5106 * @param valueIndex index of the value to write
5107 * @param value char value to write
5108 */
5109 public Pointer<T> setCharAtIndex(long valueIndex, char value) {
5110 return setCharAtOffset(valueIndex * Platform.WCHAR_T_SIZE, value);
5111 }
5112
5113 /**
5114 * Write an array of char values of the specified length to the pointed memory location
5115 */
5116 public Pointer<T> setChars(char[] values) {
5117 return setCharsAtOffset(0, values, 0, values.length);
5118 }
5119
5120 /**
5121 * Write an array of char values of the specified length to the pointed memory location shifted by a byte offset
5122 */
5123 public Pointer<T> setCharsAtOffset(long byteOffset, char[] values) {
5124 return setCharsAtOffset(byteOffset, values, 0, values.length);
5125 }
5126
5127 /**
5128 * Write an array of char values of the specified length to the pointed memory location shifted by a byte offset, reading values at the given array offset and for the given length from the provided array.
5129 */
5130 public Pointer<T> setCharsAtOffset(long byteOffset, char[] values, int valuesOffset, int length) {
5131 if (Platform.WCHAR_T_SIZE == 4)
5132 return setIntsAtOffset(byteOffset, wcharsToInts(values, valuesOffset, length));
5133 long checkedPeer = peer + byteOffset;
5134 if (validStart != UNKNOWN_VALIDITY)
5135 checkPeer(checkedPeer, Platform.WCHAR_T_SIZE * length);
5136 if (!isOrdered()) {
5137 JNI.set_char_array_disordered(checkedPeer, values, valuesOffset, length);
5138 return this;
5139 }
5140 JNI.set_char_array(checkedPeer, values, valuesOffset, length);
5141 return this;
5142 }
5143
5144 /**
5145 * Read a char value from the pointed memory location
5146 */
5147 public abstract char getChar();
5148
5149 /**
5150 * Read a char value from the pointed memory location shifted by a byte offset
5151 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#getChar()} over this method.
5152 */
5153 public abstract char getCharAtOffset(long byteOffset);
5154
5155 /**
5156 * Read the nth contiguous char value from the pointed memory location.<br>
5157 * Equivalent to <code>getCharAtOffset(valueIndex * Platform.WCHAR_T_SIZE)</code>.
5158 * @param valueIndex index of the value to read
5159 */
5160 public char getCharAtIndex(long valueIndex) {
5161 return getCharAtOffset(valueIndex * Platform.WCHAR_T_SIZE);
5162 }
5163
5164 /**
5165 * Read an array of char values of the specified length from the pointed memory location
5166 */
5167 public char[] getChars(int length) {
5168 return getCharsAtOffset(0, length);
5169 }
5170
5171
5172 /**
5173 * Read the array of remaining char values from the pointed memory location
5174 */
5175 public char[] getChars() {
5176 long validBytes = getValidBytes("Cannot create array if remaining length is not known. Please use getChars(int length) instead.");
5177 return getChars((int)(validBytes / Platform.WCHAR_T_SIZE));
5178 }
5179
5180 /**
5181 * Read an array of char values of the specified length from the pointed memory location shifted by a byte offset
5182 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#getChars(int)} over this method.
5183 */
5184 public char[] getCharsAtOffset(long byteOffset, int length) {
5185 if (Platform.WCHAR_T_SIZE == 4)
5186 return intsToWChars(getIntsAtOffset(byteOffset, length));
5187 long checkedPeer = peer + byteOffset;
5188 if (validStart != UNKNOWN_VALIDITY)
5189 checkPeer(checkedPeer, Platform.WCHAR_T_SIZE * length);
5190 if (!isOrdered())
5191 return JNI.get_char_array_disordered(checkedPeer, length);
5192 return JNI.get_char_array(checkedPeer, length);
5193 }
5194
5195 //-- primitive: float --
5196
5197 /**
5198 * Write a float value to the pointed memory location
5199 */
5200 public abstract Pointer<T> setFloat(float value);
5201
5202 /**
5203 * Write a float value to the pointed memory location shifted by a byte offset
5204 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#setFloat(float)} over this method.
5205 */
5206 public abstract Pointer<T> setFloatAtOffset(long byteOffset, float value);
5207
5208 /**
5209 * Write the nth contiguous float value to the pointed memory location.<br>
5210 * Equivalent to <code>setFloatAtOffset(valueIndex * 4, value)</code>.
5211 * @param valueIndex index of the value to write
5212 * @param value float value to write
5213 */
5214 public Pointer<T> setFloatAtIndex(long valueIndex, float value) {
5215 return setFloatAtOffset(valueIndex * 4, value);
5216 }
5217
5218 /**
5219 * Write an array of float values of the specified length to the pointed memory location
5220 */
5221 public Pointer<T> setFloats(float[] values) {
5222 return setFloatsAtOffset(0, values, 0, values.length);
5223 }
5224
5225 /**
5226 * Write an array of float values of the specified length to the pointed memory location shifted by a byte offset
5227 */
5228 public Pointer<T> setFloatsAtOffset(long byteOffset, float[] values) {
5229 return setFloatsAtOffset(byteOffset, values, 0, values.length);
5230 }
5231
5232 /**
5233 * Write an array of float values of the specified length to the pointed memory location shifted by a byte offset, reading values at the given array offset and for the given length from the provided array.
5234 */
5235 public Pointer<T> setFloatsAtOffset(long byteOffset, float[] values, int valuesOffset, int length) {
5236 long checkedPeer = peer + byteOffset;
5237 if (validStart != UNKNOWN_VALIDITY)
5238 checkPeer(checkedPeer, 4 * length);
5239 if (!isOrdered()) {
5240 JNI.set_float_array_disordered(checkedPeer, values, valuesOffset, length);
5241 return this;
5242 }
5243 JNI.set_float_array(checkedPeer, values, valuesOffset, length);
5244 return this;
5245 }
5246
5247 /**
5248 * Read a float value from the pointed memory location
5249 */
5250 public abstract float getFloat();
5251
5252 /**
5253 * Read a float value from the pointed memory location shifted by a byte offset
5254 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#getFloat()} over this method.
5255 */
5256 public abstract float getFloatAtOffset(long byteOffset);
5257
5258 /**
5259 * Read the nth contiguous float value from the pointed memory location.<br>
5260 * Equivalent to <code>getFloatAtOffset(valueIndex * 4)</code>.
5261 * @param valueIndex index of the value to read
5262 */
5263 public float getFloatAtIndex(long valueIndex) {
5264 return getFloatAtOffset(valueIndex * 4);
5265 }
5266
5267 /**
5268 * Read an array of float values of the specified length from the pointed memory location
5269 */
5270 public float[] getFloats(int length) {
5271 return getFloatsAtOffset(0, length);
5272 }
5273
5274
5275 /**
5276 * Read the array of remaining float values from the pointed memory location
5277 */
5278 public float[] getFloats() {
5279 long validBytes = getValidBytes("Cannot create array if remaining length is not known. Please use getFloats(int length) instead.");
5280 return getFloats((int)(validBytes / 4));
5281 }
5282
5283 /**
5284 * Read an array of float values of the specified length from the pointed memory location shifted by a byte offset
5285 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#getFloats(int)} over this method.
5286 */
5287 public float[] getFloatsAtOffset(long byteOffset, int length) {
5288 long checkedPeer = peer + byteOffset;
5289 if (validStart != UNKNOWN_VALIDITY)
5290 checkPeer(checkedPeer, 4 * length);
5291 if (!isOrdered())
5292 return JNI.get_float_array_disordered(checkedPeer, length);
5293 return JNI.get_float_array(checkedPeer, length);
5294 }
5295
5296 //-- primitive: double --
5297
5298 /**
5299 * Write a double value to the pointed memory location
5300 */
5301 public abstract Pointer<T> setDouble(double value);
5302
5303 /**
5304 * Write a double value to the pointed memory location shifted by a byte offset
5305 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#setDouble(double)} over this method.
5306 */
5307 public abstract Pointer<T> setDoubleAtOffset(long byteOffset, double value);
5308
5309 /**
5310 * Write the nth contiguous double value to the pointed memory location.<br>
5311 * Equivalent to <code>setDoubleAtOffset(valueIndex * 8, value)</code>.
5312 * @param valueIndex index of the value to write
5313 * @param value double value to write
5314 */
5315 public Pointer<T> setDoubleAtIndex(long valueIndex, double value) {
5316 return setDoubleAtOffset(valueIndex * 8, value);
5317 }
5318
5319 /**
5320 * Write an array of double values of the specified length to the pointed memory location
5321 */
5322 public Pointer<T> setDoubles(double[] values) {
5323 return setDoublesAtOffset(0, values, 0, values.length);
5324 }
5325
5326 /**
5327 * Write an array of double values of the specified length to the pointed memory location shifted by a byte offset
5328 */
5329 public Pointer<T> setDoublesAtOffset(long byteOffset, double[] values) {
5330 return setDoublesAtOffset(byteOffset, values, 0, values.length);
5331 }
5332
5333 /**
5334 * Write an array of double values of the specified length to the pointed memory location shifted by a byte offset, reading values at the given array offset and for the given length from the provided array.
5335 */
5336 public Pointer<T> setDoublesAtOffset(long byteOffset, double[] values, int valuesOffset, int length) {
5337 long checkedPeer = peer + byteOffset;
5338 if (validStart != UNKNOWN_VALIDITY)
5339 checkPeer(checkedPeer, 8 * length);
5340 if (!isOrdered()) {
5341 JNI.set_double_array_disordered(checkedPeer, values, valuesOffset, length);
5342 return this;
5343 }
5344 JNI.set_double_array(checkedPeer, values, valuesOffset, length);
5345 return this;
5346 }
5347
5348 /**
5349 * Read a double value from the pointed memory location
5350 */
5351 public abstract double getDouble();
5352
5353 /**
5354 * Read a double value from the pointed memory location shifted by a byte offset
5355 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#getDouble()} over this method.
5356 */
5357 public abstract double getDoubleAtOffset(long byteOffset);
5358
5359 /**
5360 * Read the nth contiguous double value from the pointed memory location.<br>
5361 * Equivalent to <code>getDoubleAtOffset(valueIndex * 8)</code>.
5362 * @param valueIndex index of the value to read
5363 */
5364 public double getDoubleAtIndex(long valueIndex) {
5365 return getDoubleAtOffset(valueIndex * 8);
5366 }
5367
5368 /**
5369 * Read an array of double values of the specified length from the pointed memory location
5370 */
5371 public double[] getDoubles(int length) {
5372 return getDoublesAtOffset(0, length);
5373 }
5374
5375
5376 /**
5377 * Read the array of remaining double values from the pointed memory location
5378 */
5379 public double[] getDoubles() {
5380 long validBytes = getValidBytes("Cannot create array if remaining length is not known. Please use getDoubles(int length) instead.");
5381 return getDoubles((int)(validBytes / 8));
5382 }
5383
5384 /**
5385 * Read an array of double values of the specified length from the pointed memory location shifted by a byte offset
5386 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#getDoubles(int)} over this method.
5387 */
5388 public double[] getDoublesAtOffset(long byteOffset, int length) {
5389 long checkedPeer = peer + byteOffset;
5390 if (validStart != UNKNOWN_VALIDITY)
5391 checkPeer(checkedPeer, 8 * length);
5392 if (!isOrdered())
5393 return JNI.get_double_array_disordered(checkedPeer, length);
5394 return JNI.get_double_array(checkedPeer, length);
5395 }
5396
5397 //-- primitive: boolean --
5398
5399 /**
5400 * Write a boolean value to the pointed memory location
5401 */
5402 public abstract Pointer<T> setBoolean(boolean value);
5403
5404 /**
5405 * Write a boolean value to the pointed memory location shifted by a byte offset
5406 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#setBoolean(boolean)} over this method.
5407 */
5408 public abstract Pointer<T> setBooleanAtOffset(long byteOffset, boolean value);
5409
5410 /**
5411 * Write the nth contiguous boolean value to the pointed memory location.<br>
5412 * Equivalent to <code>setBooleanAtOffset(valueIndex * 1, value)</code>.
5413 * @param valueIndex index of the value to write
5414 * @param value boolean value to write
5415 */
5416 public Pointer<T> setBooleanAtIndex(long valueIndex, boolean value) {
5417 return setBooleanAtOffset(valueIndex * 1, value);
5418 }
5419
5420 /**
5421 * Write an array of boolean values of the specified length to the pointed memory location
5422 */
5423 public Pointer<T> setBooleans(boolean[] values) {
5424 return setBooleansAtOffset(0, values, 0, values.length);
5425 }
5426
5427 /**
5428 * Write an array of boolean values of the specified length to the pointed memory location shifted by a byte offset
5429 */
5430 public Pointer<T> setBooleansAtOffset(long byteOffset, boolean[] values) {
5431 return setBooleansAtOffset(byteOffset, values, 0, values.length);
5432 }
5433
5434 /**
5435 * Write an array of boolean values of the specified length to the pointed memory location shifted by a byte offset, reading values at the given array offset and for the given length from the provided array.
5436 */
5437 public Pointer<T> setBooleansAtOffset(long byteOffset, boolean[] values, int valuesOffset, int length) {
5438 long checkedPeer = peer + byteOffset;
5439 if (validStart != UNKNOWN_VALIDITY)
5440 checkPeer(checkedPeer, 1 * length);
5441 JNI.set_boolean_array(checkedPeer, values, valuesOffset, length);
5442 return this;
5443 }
5444
5445 /**
5446 * Read a boolean value from the pointed memory location
5447 */
5448 public abstract boolean getBoolean();
5449
5450 /**
5451 * Read a boolean value from the pointed memory location shifted by a byte offset
5452 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#getBoolean()} over this method.
5453 */
5454 public abstract boolean getBooleanAtOffset(long byteOffset);
5455
5456 /**
5457 * Read the nth contiguous boolean value from the pointed memory location.<br>
5458 * Equivalent to <code>getBooleanAtOffset(valueIndex * 1)</code>.
5459 * @param valueIndex index of the value to read
5460 */
5461 public boolean getBooleanAtIndex(long valueIndex) {
5462 return getBooleanAtOffset(valueIndex * 1);
5463 }
5464
5465 /**
5466 * Read an array of boolean values of the specified length from the pointed memory location
5467 */
5468 public boolean[] getBooleans(int length) {
5469 return getBooleansAtOffset(0, length);
5470 }
5471
5472
5473 /**
5474 * Read the array of remaining boolean values from the pointed memory location
5475 */
5476 public boolean[] getBooleans() {
5477 long validBytes = getValidBytes("Cannot create array if remaining length is not known. Please use getBooleans(int length) instead.");
5478 return getBooleans((int)(validBytes / 1));
5479 }
5480
5481 /**
5482 * Read an array of boolean values of the specified length from the pointed memory location shifted by a byte offset
5483 * @deprecated Avoid using the byte offset methods variants unless you know what you're doing (may cause alignment issues). Please favour {@link Pointer#getBooleans(int)} over this method.
5484 */
5485 public boolean[] getBooleansAtOffset(long byteOffset, int length) {
5486 long checkedPeer = peer + byteOffset;
5487 if (validStart != UNKNOWN_VALIDITY)
5488 checkPeer(checkedPeer, 1 * length);
5489 return JNI.get_boolean_array(checkedPeer, length);
5490 }
5491
5492 //-- primitive (no bool): int --
5493
5494 /**
5495 * Read int values into the specified destination array from the pointed memory location
5496 */
5497 public void getInts(int[] dest) {
5498 getIntBuffer().get(dest);
5499 }
5500
5501 /**
5502 * Read int values into the specified destination buffer from the pointed memory location
5503 */
5504 public void getInts(IntBuffer dest) {
5505 dest.duplicate().put(getIntBuffer());
5506 }
5507
5508 /**
5509 * Read length int values into the specified destination array from the pointed memory location shifted by a byte offset, storing values after the provided destination offset.
5510 */
5511 public void getIntsAtOffset(long byteOffset, int[] dest, int destOffset, int length) {
5512 getIntBufferAtOffset(byteOffset, length).get(dest, destOffset, length);
5513 }
5514
5515 /**
5516 * Write a buffer of int values of the specified length to the pointed memory location
5517 */
5518 public Pointer<T> setInts(IntBuffer values) {
5519 return setIntsAtOffset(0, values, 0, values.capacity());
5520 }
5521
5522 /**
5523 * Write a buffer of int values of the specified length to the pointed memory location shifted by a byte offset
5524 */
5525 public Pointer<T> setIntsAtOffset(long byteOffset, IntBuffer values) {
5526 return setIntsAtOffset(byteOffset, values, 0, values.capacity());
5527 }
5528
5529 /**
5530 * Write a buffer of int values of the specified length to the pointed memory location shifted by a byte offset, reading values at the given buffer offset and for the given length from the provided buffer.
5531 */
5532 public Pointer<T> setIntsAtOffset(long byteOffset, IntBuffer values, long valuesOffset, long length) {
5533 if (values == null)
5534 throw new IllegalArgumentException("Null values");
5535 if (values.isDirect()) {
5536 long len = length * 4, off = valuesOffset * 4;
5537 long cap = JNI.getDirectBufferCapacity(values);
5538 // HACK (TODO?) the JNI spec says size is in bytes, but in practice on mac os x it's in elements !!!
5539 cap *= 4;
5540
5541 if (cap < off + len)
5542 throw new IndexOutOfBoundsException("The provided buffer has a capacity (" + cap + " bytes) smaller than the requested write operation (" + len + " bytes starting at byte offset " + off + ")");
5543
5544
5545 long checkedPeer = peer + byteOffset;
5546 if (validStart != UNKNOWN_VALIDITY)
5547 checkPeer(checkedPeer, 4 * length);
5548 JNI.memcpy(checkedPeer, JNI.getDirectBufferAddress(values) + off, len);
5549 }
5550 else if (values.isReadOnly()) {
5551 getIntBufferAtOffset(byteOffset, length).put(values.duplicate());
5552 }
5553 else {
5554 setIntsAtOffset(byteOffset, values.array(), (int)(values.arrayOffset() + valuesOffset), (int)length);
5555 }
5556 return this;
5557 }
5558
5559 /**
5560 * Get a direct buffer of int values of the specified length that points to this pointer's target memory location
5561 */
5562 public IntBuffer getIntBuffer(long length) {
5563 return getIntBufferAtOffset(0, length);
5564 }
5565
5566 /**
5567 * Get a direct buffer of int values that points to this pointer's target memory locations
5568 */
5569 public IntBuffer getIntBuffer() {
5570 long validBytes = getValidBytes("Cannot create buffer if remaining length is not known. Please use getIntBuffer(long length) instead.");
5571 return getIntBufferAtOffset(0, validBytes / 4);
5572 }
5573
5574 /**
5575 * Get a direct buffer of int values of the specified length that points to this pointer's target memory location shifted by a byte offset
5576 */
5577 public IntBuffer getIntBufferAtOffset(long byteOffset, long length) {
5578 long blen = 4 * length;
5579 long checkedPeer = peer + byteOffset;
5580 if (validStart != UNKNOWN_VALIDITY)
5581 checkPeer(checkedPeer, blen);
5582 ByteBuffer buffer = JNI.newDirectByteBuffer(checkedPeer, blen);
5583 buffer.order(order()); // mutates buffer order
5584 return buffer.asIntBuffer();
5585 }
5586
5587 //-- primitive (no bool): long --
5588
5589 /**
5590 * Read long values into the specified destination array from the pointed memory location
5591 */
5592 public void getLongs(long[] dest) {
5593 getLongBuffer().get(dest);
5594 }
5595
5596 /**
5597 * Read long values into the specified destination buffer from the pointed memory location
5598 */
5599 public void getLongs(LongBuffer dest) {
5600 dest.duplicate().put(getLongBuffer());
5601 }
5602
5603 /**
5604 * Read length long values into the specified destination array from the pointed memory location shifted by a byte offset, storing values after the provided destination offset.
5605 */
5606 public void getLongsAtOffset(long byteOffset, long[] dest, int destOffset, int length) {
5607 getLongBufferAtOffset(byteOffset, length).get(dest, destOffset, length);
5608 }
5609
5610 /**
5611 * Write a buffer of long values of the specified length to the pointed memory location
5612 */
5613 public Pointer<T> setLongs(LongBuffer values) {
5614 return setLongsAtOffset(0, values, 0, values.capacity());
5615 }
5616
5617 /**
5618 * Write a buffer of long values of the specified length to the pointed memory location shifted by a byte offset
5619 */
5620 public Pointer<T> setLongsAtOffset(long byteOffset, LongBuffer values) {
5621 return setLongsAtOffset(byteOffset, values, 0, values.capacity());
5622 }
5623
5624 /**
5625 * Write a buffer of long values of the specified length to the pointed memory location shifted by a byte offset, reading values at the given buffer offset and for the given length from the provided buffer.
5626 */
5627 public Pointer<T> setLongsAtOffset(long byteOffset, LongBuffer values, long valuesOffset, long length) {
5628 if (values == null)
5629 throw new IllegalArgumentException("Null values");
5630 if (values.isDirect()) {
5631 long len = length * 8, off = valuesOffset * 8;
5632 long cap = JNI.getDirectBufferCapacity(values);
5633 // HACK (TODO?) the JNI spec says size is in bytes, but in practice on mac os x it's in elements !!!
5634 cap *= 8;
5635
5636 if (cap < off + len)
5637 throw new IndexOutOfBoundsException("The provided buffer has a capacity (" + cap + " bytes) smaller than the requested write operation (" + len + " bytes starting at byte offset " + off + ")");
5638
5639
5640 long checkedPeer = peer + byteOffset;
5641 if (validStart != UNKNOWN_VALIDITY)
5642 checkPeer(checkedPeer, 8 * length);
5643 JNI.memcpy(checkedPeer, JNI.getDirectBufferAddress(values) + off, len);
5644 }
5645 else if (values.isReadOnly()) {
5646 getLongBufferAtOffset(byteOffset, length).put(values.duplicate());
5647 }
5648 else {
5649 setLongsAtOffset(byteOffset, values.array(), (int)(values.arrayOffset() + valuesOffset), (int)length);
5650 }
5651 return this;
5652 }
5653
5654 /**
5655 * Get a direct buffer of long values of the specified length that points to this pointer's target memory location
5656 */
5657 public LongBuffer getLongBuffer(long length) {
5658 return getLongBufferAtOffset(0, length);
5659 }
5660
5661 /**
5662 * Get a direct buffer of long values that points to this pointer's target memory locations
5663 */
5664 public LongBuffer getLongBuffer() {
5665 long validBytes = getValidBytes("Cannot create buffer if remaining length is not known. Please use getLongBuffer(long length) instead.");
5666 return getLongBufferAtOffset(0, validBytes / 8);
5667 }
5668
5669 /**
5670 * Get a direct buffer of long values of the specified length that points to this pointer's target memory location shifted by a byte offset
5671 */
5672 public LongBuffer getLongBufferAtOffset(long byteOffset, long length) {
5673 long blen = 8 * length;
5674 long checkedPeer = peer + byteOffset;
5675 if (validStart != UNKNOWN_VALIDITY)
5676 checkPeer(checkedPeer, blen);
5677 ByteBuffer buffer = JNI.newDirectByteBuffer(checkedPeer, blen);
5678 buffer.order(order()); // mutates buffer order
5679 return buffer.asLongBuffer();
5680 }
5681
5682 //-- primitive (no bool): short --
5683
5684 /**
5685 * Read short values into the specified destination array from the pointed memory location
5686 */
5687 public void getShorts(short[] dest) {
5688 getShortBuffer().get(dest);
5689 }
5690
5691 /**
5692 * Read short values into the specified destination buffer from the pointed memory location
5693 */
5694 public void getShorts(ShortBuffer dest) {
5695 dest.duplicate().put(getShortBuffer());
5696 }
5697
5698 /**
5699 * Read length short values into the specified destination array from the pointed memory location shifted by a byte offset, storing values after the provided destination offset.
5700 */
5701 public void getShortsAtOffset(long byteOffset, short[] dest, int destOffset, int length) {
5702 getShortBufferAtOffset(byteOffset, length).get(dest, destOffset, length);
5703 }
5704
5705 /**
5706 * Write a buffer of short values of the specified length to the pointed memory location
5707 */
5708 public Pointer<T> setShorts(ShortBuffer values) {
5709 return setShortsAtOffset(0, values, 0, values.capacity());
5710 }
5711
5712 /**
5713 * Write a buffer of short values of the specified length to the pointed memory location shifted by a byte offset
5714 */
5715 public Pointer<T> setShortsAtOffset(long byteOffset, ShortBuffer values) {
5716 return setShortsAtOffset(byteOffset, values, 0, values.capacity());
5717 }
5718
5719 /**
5720 * Write a buffer of short values of the specified length to the pointed memory location shifted by a byte offset, reading values at the given buffer offset and for the given length from the provided buffer.
5721 */
5722 public Pointer<T> setShortsAtOffset(long byteOffset, ShortBuffer values, long valuesOffset, long length) {
5723 if (values == null)
5724 throw new IllegalArgumentException("Null values");
5725 if (values.isDirect()) {
5726 long len = length * 2, off = valuesOffset * 2;
5727 long cap = JNI.getDirectBufferCapacity(values);
5728 // HACK (TODO?) the JNI spec says size is in bytes, but in practice on mac os x it's in elements !!!
5729 cap *= 2;
5730
5731 if (cap < off + len)
5732 throw new IndexOutOfBoundsException("The provided buffer has a capacity (" + cap + " bytes) smaller than the requested write operation (" + len + " bytes starting at byte offset " + off + ")");
5733
5734
5735 long checkedPeer = peer + byteOffset;
5736 if (validStart != UNKNOWN_VALIDITY)
5737 checkPeer(checkedPeer, 2 * length);
5738 JNI.memcpy(checkedPeer, JNI.getDirectBufferAddress(values) + off, len);
5739 }
5740 else if (values.isReadOnly()) {
5741 getShortBufferAtOffset(byteOffset, length).put(values.duplicate());
5742 }
5743 else {
5744 setShortsAtOffset(byteOffset, values.array(), (int)(values.arrayOffset() + valuesOffset), (int)length);
5745 }
5746 return this;
5747 }
5748
5749 /**
5750 * Get a direct buffer of short values of the specified length that points to this pointer's target memory location
5751 */
5752 public ShortBuffer getShortBuffer(long length) {
5753 return getShortBufferAtOffset(0, length);
5754 }
5755
5756 /**
5757 * Get a direct buffer of short values that points to this pointer's target memory locations
5758 */
5759 public ShortBuffer getShortBuffer() {
5760 long validBytes = getValidBytes("Cannot create buffer if remaining length is not known. Please use getShortBuffer(long length) instead.");
5761 return getShortBufferAtOffset(0, validBytes / 2);
5762 }
5763
5764 /**
5765 * Get a direct buffer of short values of the specified length that points to this pointer's target memory location shifted by a byte offset
5766 */
5767 public ShortBuffer getShortBufferAtOffset(long byteOffset, long length) {
5768 long blen = 2 * length;
5769 long checkedPeer = peer + byteOffset;
5770 if (validStart != UNKNOWN_VALIDITY)
5771 checkPeer(checkedPeer, blen);
5772 ByteBuffer buffer = JNI.newDirectByteBuffer(checkedPeer, blen);
5773 buffer.order(order()); // mutates buffer order
5774 return buffer.asShortBuffer();
5775 }
5776
5777 //-- primitive (no bool): byte --
5778
5779 /**
5780 * Read byte values into the specified destination array from the pointed memory location
5781 */
5782 public void getBytes(byte[] dest) {
5783 getByteBuffer().get(dest);
5784 }
5785
5786 /**
5787 * Read byte values into the specified destination buffer from the pointed memory location
5788 */
5789 public void getBytes(ByteBuffer dest) {
5790 dest.duplicate().put(getByteBuffer());
5791 }
5792
5793 /**
5794 * Read length byte values into the specified destination array from the pointed memory location shifted by a byte offset, storing values after the provided destination offset.
5795 */
5796 public void getBytesAtOffset(long byteOffset, byte[] dest, int destOffset, int length) {
5797 getByteBufferAtOffset(byteOffset, length).get(dest, destOffset, length);
5798 }
5799
5800 /**
5801 * Write a buffer of byte values of the specified length to the pointed memory location
5802 */
5803 public Pointer<T> setBytes(ByteBuffer values) {
5804 return setBytesAtOffset(0, values, 0, values.capacity());
5805 }
5806
5807 /**
5808 * Write a buffer of byte values of the specified length to the pointed memory location shifted by a byte offset
5809 */
5810 public Pointer<T> setBytesAtOffset(long byteOffset, ByteBuffer values) {
5811 return setBytesAtOffset(byteOffset, values, 0, values.capacity());
5812 }
5813
5814 /**
5815 * Write a buffer of byte values of the specified length to the pointed memory location shifted by a byte offset, reading values at the given buffer offset and for the given length from the provided buffer.
5816 */
5817 public Pointer<T> setBytesAtOffset(long byteOffset, ByteBuffer values, long valuesOffset, long length) {
5818 if (values == null)
5819 throw new IllegalArgumentException("Null values");
5820 if (values.isDirect()) {
5821 long len = length * 1, off = valuesOffset * 1;
5822 long cap = JNI.getDirectBufferCapacity(values);
5823 // HACK (TODO?) the JNI spec says size is in bytes, but in practice on mac os x it's in elements !!!
5824 cap *= 1;
5825
5826 if (cap < off + len)
5827 throw new IndexOutOfBoundsException("The provided buffer has a capacity (" + cap + " bytes) smaller than the requested write operation (" + len + " bytes starting at byte offset " + off + ")");
5828
5829
5830 long checkedPeer = peer + byteOffset;
5831 if (validStart != UNKNOWN_VALIDITY)
5832 checkPeer(checkedPeer, 1 * length);
5833 JNI.memcpy(checkedPeer, JNI.getDirectBufferAddress(values) + off, len);
5834 }
5835 else if (values.isReadOnly()) {
5836 getByteBufferAtOffset(byteOffset, length).put(values.duplicate());
5837 }
5838 else {
5839 setBytesAtOffset(byteOffset, values.array(), (int)(values.arrayOffset() + valuesOffset), (int)length);
5840 }
5841 return this;
5842 }
5843
5844 /**
5845 * Get a direct buffer of byte values of the specified length that points to this pointer's target memory location
5846 */
5847 public ByteBuffer getByteBuffer(long length) {
5848 return getByteBufferAtOffset(0, length);
5849 }
5850
5851 /**
5852 * Get a direct buffer of byte values that points to this pointer's target memory locations
5853 */
5854 public ByteBuffer getByteBuffer() {
5855 long validBytes = getValidBytes("Cannot create buffer if remaining length is not known. Please use getByteBuffer(long length) instead.");
5856 return getByteBufferAtOffset(0, validBytes / 1);
5857 }
5858
5859 /**
5860 * Get a direct buffer of byte values of the specified length that points to this pointer's target memory location shifted by a byte offset
5861 */
5862 public ByteBuffer getByteBufferAtOffset(long byteOffset, long length) {
5863 long blen = 1 * length;
5864 long checkedPeer = peer + byteOffset;
5865 if (validStart != UNKNOWN_VALIDITY)
5866 checkPeer(checkedPeer, blen);
5867 ByteBuffer buffer = JNI.newDirectByteBuffer(checkedPeer, blen);
5868 buffer.order(order()); // mutates buffer order
5869 return buffer;
5870 }
5871
5872 //-- primitive (no bool): char --
5873
5874
5875 /**
5876 * Write a buffer of char values of the specified length to the pointed memory location
5877 */
5878 public Pointer<T> setChars(CharBuffer values) {
5879 return setCharsAtOffset(0, values, 0, values.capacity());
5880 }
5881
5882 /**
5883 * Write a buffer of char values of the specified length to the pointed memory location shifted by a byte offset
5884 */
5885 public Pointer<T> setCharsAtOffset(long byteOffset, CharBuffer values) {
5886 return setCharsAtOffset(byteOffset, values, 0, values.capacity());
5887 }
5888
5889 /**
5890 * Write a buffer of char values of the specified length to the pointed memory location shifted by a byte offset, reading values at the given buffer offset and for the given length from the provided buffer.
5891 */
5892 public Pointer<T> setCharsAtOffset(long byteOffset, CharBuffer values, long valuesOffset, long length) {
5893 if (values == null)
5894 throw new IllegalArgumentException("Null values");
5895 if (Platform.WCHAR_T_SIZE == 4) {
5896 for (int i = 0; i < length; i++)
5897 setCharAtOffset(byteOffset + i, values.get((int)(valuesOffset + i)));
5898 return this;
5899 }
5900 if (values.isDirect()) {
5901 long len = length * Platform.WCHAR_T_SIZE, off = valuesOffset * Platform.WCHAR_T_SIZE;
5902 long cap = JNI.getDirectBufferCapacity(values);
5903 // HACK (TODO?) the JNI spec says size is in bytes, but in practice on mac os x it's in elements !!!
5904 cap *= Platform.WCHAR_T_SIZE;
5905
5906 if (cap < off + len)
5907 throw new IndexOutOfBoundsException("The provided buffer has a capacity (" + cap + " bytes) smaller than the requested write operation (" + len + " bytes starting at byte offset " + off + ")");
5908
5909
5910 long checkedPeer = peer + byteOffset;
5911 if (validStart != UNKNOWN_VALIDITY)
5912 checkPeer(checkedPeer, Platform.WCHAR_T_SIZE * length);
5913 JNI.memcpy(checkedPeer, JNI.getDirectBufferAddress(values) + off, len);
5914 }
5915 else {
5916 setCharsAtOffset(byteOffset, values.array(), (int)(values.arrayOffset() + valuesOffset), (int)length);
5917 }
5918 return this;
5919 }
5920
5921
5922 //-- primitive (no bool): float --
5923
5924 /**
5925 * Read float values into the specified destination array from the pointed memory location
5926 */
5927 public void getFloats(float[] dest) {
5928 getFloatBuffer().get(dest);
5929 }
5930
5931 /**
5932 * Read float values into the specified destination buffer from the pointed memory location
5933 */
5934 public void getFloats(FloatBuffer dest) {
5935 dest.duplicate().put(getFloatBuffer());
5936 }
5937
5938 /**
5939 * Read length float values into the specified destination array from the pointed memory location shifted by a byte offset, storing values after the provided destination offset.
5940 */
5941 public void getFloatsAtOffset(long byteOffset, float[] dest, int destOffset, int length) {
5942 getFloatBufferAtOffset(byteOffset, length).get(dest, destOffset, length);
5943 }
5944
5945 /**
5946 * Write a buffer of float values of the specified length to the pointed memory location
5947 */
5948 public Pointer<T> setFloats(FloatBuffer values) {
5949 return setFloatsAtOffset(0, values, 0, values.capacity());
5950 }
5951
5952 /**
5953 * Write a buffer of float values of the specified length to the pointed memory location shifted by a byte offset
5954 */
5955 public Pointer<T> setFloatsAtOffset(long byteOffset, FloatBuffer values) {
5956 return setFloatsAtOffset(byteOffset, values, 0, values.capacity());
5957 }
5958
5959 /**
5960 * Write a buffer of float values of the specified length to the pointed memory location shifted by a byte offset, reading values at the given buffer offset and for the given length from the provided buffer.
5961 */
5962 public Pointer<T> setFloatsAtOffset(long byteOffset, FloatBuffer values, long valuesOffset, long length) {
5963 if (values == null)
5964 throw new IllegalArgumentException("Null values");
5965 if (values.isDirect()) {
5966 long len = length * 4, off = valuesOffset * 4;
5967 long cap = JNI.getDirectBufferCapacity(values);
5968 // HACK (TODO?) the JNI spec says size is in bytes, but in practice on mac os x it's in elements !!!
5969 cap *= 4;
5970
5971 if (cap < off + len)
5972 throw new IndexOutOfBoundsException("The provided buffer has a capacity (" + cap + " bytes) smaller than the requested write operation (" + len + " bytes starting at byte offset " + off + ")");
5973
5974
5975 long checkedPeer = peer + byteOffset;
5976 if (validStart != UNKNOWN_VALIDITY)
5977 checkPeer(checkedPeer, 4 * length);
5978 JNI.memcpy(checkedPeer, JNI.getDirectBufferAddress(values) + off, len);
5979 }
5980 else if (values.isReadOnly()) {
5981 getFloatBufferAtOffset(byteOffset, length).put(values.duplicate());
5982 }
5983 else {
5984 setFloatsAtOffset(byteOffset, values.array(), (int)(values.arrayOffset() + valuesOffset), (int)length);
5985 }
5986 return this;
5987 }
5988
5989 /**
5990 * Get a direct buffer of float values of the specified length that points to this pointer's target memory location
5991 */
5992 public FloatBuffer getFloatBuffer(long length) {
5993 return getFloatBufferAtOffset(0, length);
5994 }
5995
5996 /**
5997 * Get a direct buffer of float values that points to this pointer's target memory locations
5998 */
5999 public FloatBuffer getFloatBuffer() {
6000 long validBytes = getValidBytes("Cannot create buffer if remaining length is not known. Please use getFloatBuffer(long length) instead.");
6001 return getFloatBufferAtOffset(0, validBytes / 4);
6002 }
6003
6004 /**
6005 * Get a direct buffer of float values of the specified length that points to this pointer's target memory location shifted by a byte offset
6006 */
6007 public FloatBuffer getFloatBufferAtOffset(long byteOffset, long length) {
6008 long blen = 4 * length;
6009 long checkedPeer = peer + byteOffset;
6010 if (validStart != UNKNOWN_VALIDITY)
6011 checkPeer(checkedPeer, blen);
6012 ByteBuffer buffer = JNI.newDirectByteBuffer(checkedPeer, blen);
6013 buffer.order(order()); // mutates buffer order
6014 return buffer.asFloatBuffer();
6015 }
6016
6017 //-- primitive (no bool): double --
6018
6019 /**
6020 * Read double values into the specified destination array from the pointed memory location
6021 */
6022 public void getDoubles(double[] dest) {
6023 getDoubleBuffer().get(dest);
6024 }
6025
6026 /**
6027 * Read double values into the specified destination buffer from the pointed memory location
6028 */
6029 public void getDoubles(DoubleBuffer dest) {
6030 dest.duplicate().put(getDoubleBuffer());
6031 }
6032
6033 /**
6034 * Read length double values into the specified destination array from the pointed memory location shifted by a byte offset, storing values after the provided destination offset.
6035 */
6036 public void getDoublesAtOffset(long byteOffset, double[] dest, int destOffset, int length) {
6037 getDoubleBufferAtOffset(byteOffset, length).get(dest, destOffset, length);
6038 }
6039
6040 /**
6041 * Write a buffer of double values of the specified length to the pointed memory location
6042 */
6043 public Pointer<T> setDoubles(DoubleBuffer values) {
6044 return setDoublesAtOffset(0, values, 0, values.capacity());
6045 }
6046
6047 /**
6048 * Write a buffer of double values of the specified length to the pointed memory location shifted by a byte offset
6049 */
6050 public Pointer<T> setDoublesAtOffset(long byteOffset, DoubleBuffer values) {
6051 return setDoublesAtOffset(byteOffset, values, 0, values.capacity());
6052 }
6053
6054 /**
6055 * Write a buffer of double values of the specified length to the pointed memory location shifted by a byte offset, reading values at the given buffer offset and for the given length from the provided buffer.
6056 */
6057 public Pointer<T> setDoublesAtOffset(long byteOffset, DoubleBuffer values, long valuesOffset, long length) {
6058 if (values == null)
6059 throw new IllegalArgumentException("Null values");
6060 if (values.isDirect()) {
6061 long len = length * 8, off = valuesOffset * 8;
6062 long cap = JNI.getDirectBufferCapacity(values);
6063 // HACK (TODO?) the JNI spec says size is in bytes, but in practice on mac os x it's in elements !!!
6064 cap *= 8;
6065
6066 if (cap < off + len)
6067 throw new IndexOutOfBoundsException("The provided buffer has a capacity (" + cap + " bytes) smaller than the requested write operation (" + len + " bytes starting at byte offset " + off + ")");
6068
6069
6070 long checkedPeer = peer + byteOffset;
6071 if (validStart != UNKNOWN_VALIDITY)
6072 checkPeer(checkedPeer, 8 * length);
6073 JNI.memcpy(checkedPeer, JNI.getDirectBufferAddress(values) + off, len);
6074 }
6075 else if (values.isReadOnly()) {
6076 getDoubleBufferAtOffset(byteOffset, length).put(values.duplicate());
6077 }
6078 else {
6079 setDoublesAtOffset(byteOffset, values.array(), (int)(values.arrayOffset() + valuesOffset), (int)length);
6080 }
6081 return this;
6082 }
6083
6084 /**
6085 * Get a direct buffer of double values of the specified length that points to this pointer's target memory location
6086 */
6087 public DoubleBuffer getDoubleBuffer(long length) {
6088 return getDoubleBufferAtOffset(0, length);
6089 }
6090
6091 /**
6092 * Get a direct buffer of double values that points to this pointer's target memory locations
6093 */
6094 public DoubleBuffer getDoubleBuffer() {
6095 long validBytes = getValidBytes("Cannot create buffer if remaining length is not known. Please use getDoubleBuffer(long length) instead.");
6096 return getDoubleBufferAtOffset(0, validBytes / 8);
6097 }
6098
6099 /**
6100 * Get a direct buffer of double values of the specified length that points to this pointer's target memory location shifted by a byte offset
6101 */
6102 public DoubleBuffer getDoubleBufferAtOffset(long byteOffset, long length) {
6103 long blen = 8 * length;
6104 long checkedPeer = peer + byteOffset;
6105 if (validStart != UNKNOWN_VALIDITY)
6106 checkPeer(checkedPeer, blen);
6107 ByteBuffer buffer = JNI.newDirectByteBuffer(checkedPeer, blen);
6108 buffer.order(order()); // mutates buffer order
6109 return buffer.asDoubleBuffer();
6110 }
6111
6112
6113 /**
6114 * Type of a native character string.<br>
6115 * In the native world, there are several ways to represent a string.<br>
6116 * See {@link Pointer#getStringAtOffset(long, StringType, Charset)} and {@link Pointer#setStringAtOffset(long, String, StringType, Charset)}
6117 */
6118 public enum StringType {
6119 /**
6120 * C strings (a.k.a "NULL-terminated strings") have no size limit and are the most used strings in the C world.
6121 * They are stored with the bytes of the string (using either a single-byte encoding such as ASCII, ISO-8859 or windows-1252 or a C-string compatible multi-byte encoding, such as UTF-8), followed with a zero byte that indicates the end of the string.<br>
6122 * Corresponding C types : {@code char* }, {@code const char* }, {@code LPCSTR }<br>
6123 * Corresponding Pascal type : {@code PChar }<br>
6124 * See {@link Pointer#pointerToCString(String)}, {@link Pointer#getCString()} and {@link Pointer#setCString(String)}
6125 */
6126 C(false, true),
6127 /**
6128 * Wide C strings are stored as C strings (see {@link StringType#C}) except they are composed of shorts instead of bytes (and are ended by one zero short value = two zero byte values).
6129 * This allows the use of two-bytes encodings, which is why this kind of strings is often found in modern Unicode-aware system APIs.<br>
6130 * Corresponding C types : {@code wchar_t* }, {@code const wchar_t* }, {@code LPCWSTR }<br>
6131 * See {@link Pointer#pointerToWideCString(String)}, {@link Pointer#getWideCString()} and {@link Pointer#setWideCString(String)}
6132 */
6133 WideC(true, true),
6134 /**
6135 * Pascal strings can be up to 255 characters long.<br>
6136 * They are stored with a first byte that indicates the length of the string, followed by the ascii or extended ascii chars of the string (no support for multibyte encoding).<br>
6137 * They are often used in very old Mac OS programs and / or Pascal programs.<br>
6138 * Usual corresponding C types : {@code unsigned char* } and {@code const unsigned char* }<br>
6139 * Corresponding Pascal type : {@code ShortString } (see @see <a href="http://www.codexterity.com/delphistrings.htm">http://www.codexterity.com/delphistrings.htm</a>)<br>
6140 * See {@link Pointer#pointerToString(String, StringType, Charset)}, {@link Pointer#getString(StringType)}, {@link Pointer#setString(String, StringType)},
6141 */
6142 PascalShort(false, true),
6143 /**
6144 * Wide Pascal strings are ref-counted unicode strings that look like WideC strings but are prepended with a ref count and length (both 32 bits ints).<br>
6145 * They are the current default in Delphi (2010).<br>
6146 * Corresponding Pascal type : {@code WideString } (see @see <a href="http://www.codexterity.com/delphistrings.htm">http://www.codexterity.com/delphistrings.htm</a>)<br>
6147 * See {@link Pointer#pointerToString(String, StringType, Charset)}, {@link Pointer#getString(StringType)}, {@link Pointer#setString(String, StringType)},
6148 */
6149 PascalWide(true, true),
6150 /**
6151 * Pascal ANSI strings are ref-counted single-byte strings that look like C strings but are prepended with a ref count and length (both 32 bits ints).<br>
6152 * Corresponding Pascal type : {@code AnsiString } (see @see <a href="http://www.codexterity.com/delphistrings.htm">http://www.codexterity.com/delphistrings.htm</a>)<br>
6153 * See {@link Pointer#pointerToString(String, StringType, Charset)}, {@link Pointer#getString(StringType)}, {@link Pointer#setString(String, StringType)},
6154 */
6155 PascalAnsi(false, true),
6156 /**
6157 * Microsoft's BSTR strings, used in COM, OLE, MS.NET Interop and MS.NET Automation functions.<br>
6158 * See @see <a href="http://msdn.microsoft.com/en-us/library/ms221069.aspx">http://msdn.microsoft.com/en-us/library/ms221069.aspx</a> for more details.<br>
6159 * See {@link Pointer#pointerToString(String, StringType, Charset)}, {@link Pointer#getString(StringType)}, {@link Pointer#setString(String, StringType)},
6160 */
6161 BSTR(true, true),
6162 /**
6163 * STL strings have compiler- and STL library-specific implementations and memory layouts.<br>
6164 * BridJ support reading and writing to / from pointers to most implementation's STL strings, though.
6165 * See {@link Pointer#pointerToString(String, StringType, Charset)}, {@link Pointer#getString(StringType)}, {@link Pointer#setString(String, StringType)},
6166 */
6167 STL(false, false),
6168 /**
6169 * STL wide strings have compiler- and STL library-specific implementations and memory layouts.<br>
6170 * BridJ supports reading and writing to / from pointers to most implementation's STL strings, though.
6171 * See {@link Pointer#pointerToString(String, StringType, Charset)}, {@link Pointer#getString(StringType)}, {@link Pointer#setString(String, StringType)},
6172 */
6173 WideSTL(true, false);
6174 //MFCCString,
6175 //CComBSTR,
6176 //_bstr_t
6177
6178 final boolean isWide, canCreate;
6179 StringType(boolean isWide, boolean canCreate) {
6180 this.isWide = isWide;
6181 this.canCreate = canCreate;
6182 }
6183
6184 }
6185
6186 private static void notAString(StringType type, String reason) {
6187 throw new RuntimeException("There is no " + type + " String here ! (" + reason + ")");
6188 }
6189
6190 protected void checkIntRefCount(StringType type, long byteOffset) {
6191 int refCount = getIntAtOffset(byteOffset);
6192 if (refCount <= 0)
6193 notAString(type, "invalid refcount: " + refCount);
6194 }
6195
6196 /**
6197 * Read a native string from the pointed memory location using the default charset.<br>
6198 * See {@link Pointer#getStringAtOffset(long, StringType, Charset)} for more options.
6199 * @param type Type of the native String to read. See {@link StringType} for details on the supported types.
6200 * @return string read from native memory
6201 */
6202 public String getString(StringType type) {
6203 return getStringAtOffset(0, type, null);
6204 }
6205
6206 /**
6207 * Read a native string from the pointed memory location, using the provided charset or the system's default if not provided.
6208 * See {@link Pointer#getStringAtOffset(long, StringType, Charset)} for more options.
6209 * @param type Type of the native String to read. See {@link StringType} for details on the supported types.
6210 * @param charset Character set used to convert bytes to String characters. If null, {@link Charset#defaultCharset()} will be used
6211 * @return string read from native memory
6212 */
6213 public String getString(StringType type, Charset charset) {
6214 return getStringAtOffset(0, type, charset);
6215 }
6216
6217
6218 String getSTLStringAtOffset(long byteOffset, StringType type, Charset charset) {
6219 // Assume the following layout :
6220 // - fixed buff of 16 chars
6221 // - ptr to dynamic array if the string is bigger
6222 // - size of the string (size_t)
6223 // - max allowed size of the string without the need for reallocation
6224 boolean wide = type == StringType.WideSTL;
6225
6226 int fixedBuffLength = 16;
6227 int fixedBuffSize = wide ? fixedBuffLength * Platform.WCHAR_T_SIZE : fixedBuffLength;
6228 long length = getSizeTAtOffset(byteOffset + fixedBuffSize + Pointer.SIZE);
6229 long pOff;
6230 Pointer<?> p;
6231 if (length < fixedBuffLength - 1) {
6232 pOff = byteOffset;
6233 p = this;
6234 } else {
6235 pOff = 0;
6236 p = getPointerAtOffset(byteOffset + fixedBuffSize + Pointer.SIZE);
6237 }
6238 int endChar = wide ? p.getCharAtOffset(pOff + length * Platform.WCHAR_T_SIZE) : p.getByteAtOffset(pOff + length);
6239 if (endChar != 0)
6240 notAString(type, "STL string format is not recognized : did not find a NULL char at the expected end of string of expected length " + length);
6241 return p.getStringAtOffset(pOff, wide ? StringType.WideC : StringType.C, charset);
6242 }
6243
6244 static <U> Pointer<U> setSTLString(Pointer<U> pointer, long byteOffset, String s, StringType type, Charset charset) {
6245 boolean wide = type == StringType.WideSTL;
6246
6247 int fixedBuffLength = 16;
6248 int fixedBuffSize = wide ? fixedBuffLength * Platform.WCHAR_T_SIZE : fixedBuffLength;
6249 long lengthOffset = byteOffset + fixedBuffSize + Pointer.SIZE;
6250 long capacityOffset = lengthOffset + Pointer.SIZE;
6251
6252 long length = s.length();
6253 if (pointer == null)// { && length > fixedBuffLength - 1)
6254 throw new UnsupportedOperationException("Cannot create STL strings (yet)");
6255
6256 long currentLength = pointer.getSizeTAtOffset(lengthOffset);
6257 long currentCapacity = pointer.getSizeTAtOffset(capacityOffset);
6258
6259 if (currentLength < 0 || currentCapacity < 0 || currentLength > currentCapacity)
6260 notAString(type, "STL string format not recognized : currentLength = " + currentLength + ", currentCapacity = " + currentCapacity);
6261
6262 if (length > currentCapacity)
6263 throw new RuntimeException("The target STL string is not large enough to write a string of length " + length + " (current capacity = " + currentCapacity + ")");
6264
6265 pointer.setSizeTAtOffset(lengthOffset, length);
6266
6267 long pOff;
6268 Pointer<?> p;
6269 if (length < fixedBuffLength - 1) {
6270 pOff = byteOffset;
6271 p = pointer;
6272 } else {
6273 pOff = 0;
6274 p = pointer.getPointerAtOffset(byteOffset + fixedBuffSize + SizeT.SIZE);
6275 }
6276
6277 int endChar = wide ? p.getCharAtOffset(pOff + currentLength * Platform.WCHAR_T_SIZE) : p.getByteAtOffset(pOff + currentLength);
6278 if (endChar != 0)
6279 notAString(type, "STL string format is not recognized : did not find a NULL char at the expected end of string of expected length " + currentLength);
6280
6281 p.setStringAtOffset(pOff, s, wide ? StringType.WideC : StringType.C, charset);
6282 return pointer;
6283 }
6284
6285
6286 /**
6287 * Read a native string from the pointed memory location shifted by a byte offset, using the provided charset or the system's default if not provided.
6288 * @param byteOffset
6289 * @param charset Character set used to convert bytes to String characters. If null, {@link Charset#defaultCharset()} will be used
6290 * @param type Type of the native String to read. See {@link StringType} for details on the supported types.
6291 * @return string read from native memory
6292 */
6293 public String getStringAtOffset(long byteOffset, StringType type, Charset charset) {
6294 try {
6295 long len;
6296
6297 switch (type) {
6298 case PascalShort:
6299 len = getByteAtOffset(byteOffset) & 0xff;
6300 return new String(getBytesAtOffset(byteOffset + 1, safeIntCast(len)), charset(charset));
6301 case PascalWide:
6302 checkIntRefCount(type, byteOffset - 8);
6303 case BSTR:
6304 len = getIntAtOffset(byteOffset - 4);
6305 if (len < 0 || ((len & 1) == 1))
6306 notAString(type, "invalid byte length: " + len);
6307 //len = wcslen(byteOffset);
6308 if (getCharAtOffset(byteOffset + len) != 0)
6309 notAString(type, "no null short after the " + len + " declared bytes");
6310 return new String(getCharsAtOffset(byteOffset, safeIntCast(len / Platform.WCHAR_T_SIZE)));
6311 case PascalAnsi:
6312 checkIntRefCount(type, byteOffset - 8);
6313 len = getIntAtOffset(byteOffset - 4);
6314 if (len < 0)
6315 notAString(type, "invalid byte length: " + len);
6316 if (getByteAtOffset(byteOffset + len) != 0)
6317 notAString(type, "no null short after the " + len + " declared bytes");
6318 return new String(getBytesAtOffset(byteOffset, safeIntCast(len)), charset(charset));
6319 case C:
6320 len = strlen(byteOffset);
6321 return new String(getBytesAtOffset(byteOffset, safeIntCast(len)), charset(charset));
6322 case WideC:
6323 len = wcslen(byteOffset);
6324 return new String(getCharsAtOffset(byteOffset, safeIntCast(len)));
6325 case STL:
6326 case WideSTL:
6327 return getSTLStringAtOffset(byteOffset, type, charset);
6328 default:
6329 throw new RuntimeException("Unhandled string type : " + type);
6330 }
6331 } catch (UnsupportedEncodingException ex) {
6332 throwUnexpected(ex);
6333 return null;
6334 }
6335 }
6336
6337 /**
6338 * Write a native string to the pointed memory location using the default charset.<br>
6339 * See {@link Pointer#setStringAtOffset(long, String, StringType, Charset)} for more options.
6340 * @param s string to write
6341 * @param type Type of the native String to write. See {@link StringType} for details on the supported types.
6342 * @return this
6343 */
6344 public Pointer<T> setString(String s, StringType type) {
6345 return setString(this, 0, s, type, null);
6346 }
6347
6348
6349 /**
6350 * Write a native string to the pointed memory location shifted by a byte offset, using the provided charset or the system's default if not provided.
6351 * @param byteOffset
6352 * @param s string to write
6353 * @param charset Character set used to convert String characters to bytes. If null, {@link Charset#defaultCharset()} will be used
6354 * @param type Type of the native String to write. See {@link StringType} for details on the supported types.
6355 * @return this
6356 */
6357 public Pointer<T> setStringAtOffset(long byteOffset, String s, StringType type, Charset charset) {
6358 return setString(this, byteOffset, s, type, charset);
6359 }
6360
6361 private static String charset(Charset charset) {
6362 return (charset == null ? Charset.defaultCharset() : charset).name();
6363 }
6364
6365 static <U> Pointer<U> setString(Pointer<U> pointer, long byteOffset, String s, StringType type, Charset charset) {
6366 try {
6367 if (s == null)
6368 return null;
6369
6370 byte[] bytes;
6371 char[] chars;
6372 int bytesCount, headerBytes;
6373 int headerShift;
6374
6375 switch (type) {
6376 case PascalShort:
6377 bytes = s.getBytes(charset(charset));
6378 bytesCount = bytes.length;
6379 if (pointer == null)
6380 pointer = (Pointer<U>)allocateBytes(bytesCount + 1);
6381 if (bytesCount > 255)
6382 throw new IllegalArgumentException("Pascal strings cannot be more than 255 chars long (tried to write string of byte length " + bytesCount + ")");
6383 pointer.setByteAtOffset(byteOffset, (byte)bytesCount);
6384 pointer.setBytesAtOffset(byteOffset + 1, bytes, 0, bytesCount);
6385 break;
6386 case C:
6387 bytes = s.getBytes(charset(charset));
6388 bytesCount = bytes.length;
6389 if (pointer == null)
6390 pointer = (Pointer<U>)allocateBytes(bytesCount + 1);
6391 pointer.setBytesAtOffset(byteOffset, bytes, 0, bytesCount);
6392 pointer.setByteAtOffset(byteOffset + bytesCount, (byte)0);
6393 break;
6394 case WideC:
6395 chars = s.toCharArray();
6396 bytesCount = chars.length * Platform.WCHAR_T_SIZE;
6397 if (pointer == null)
6398 pointer = (Pointer<U>)allocateChars(bytesCount + 2);
6399 pointer.setCharsAtOffset(byteOffset, chars);
6400 pointer.setCharAtOffset(byteOffset + bytesCount, (char)0);
6401 break;
6402 case PascalWide:
6403 headerBytes = 8;
6404 chars = s.toCharArray();
6405 bytesCount = chars.length * Platform.WCHAR_T_SIZE;
6406 if (pointer == null) {
6407 pointer = (Pointer<U>)allocateChars(headerBytes + bytesCount + 2);
6408 byteOffset = headerShift = headerBytes;
6409 } else
6410 headerShift = 0;
6411 pointer.setIntAtOffset(byteOffset - 8, 1); // refcount
6412 pointer.setIntAtOffset(byteOffset - 4, bytesCount); // length header
6413 pointer.setCharsAtOffset(byteOffset, chars);
6414 pointer.setCharAtOffset(byteOffset + bytesCount, (char)0);
6415 // Return a pointer to the WideC string-compatible part of the Pascal WideString
6416 return (Pointer<U>)pointer.offset(headerShift);
6417 case PascalAnsi:
6418 headerBytes = 8;
6419 bytes = s.getBytes(charset(charset));
6420 bytesCount = bytes.length;
6421 if (pointer == null) {
6422 pointer = (Pointer<U>)allocateBytes(headerBytes + bytesCount + 1);
6423 byteOffset = headerShift = headerBytes;
6424 } else
6425 headerShift = 0;
6426 pointer.setIntAtOffset(byteOffset - 8, 1); // refcount
6427 pointer.setIntAtOffset(byteOffset - 4, bytesCount); // length header
6428 pointer.setBytesAtOffset(byteOffset, bytes);
6429 pointer.setByteAtOffset(byteOffset + bytesCount, (byte)0);
6430 // Return a pointer to the WideC string-compatible part of the Pascal WideString
6431 return (Pointer<U>)pointer.offset(headerShift);
6432 case BSTR:
6433 headerBytes = 4;
6434 chars = s.toCharArray();
6435 bytesCount = chars.length * Platform.WCHAR_T_SIZE;
6436 if (pointer == null) {
6437 pointer = (Pointer<U>)allocateChars(headerBytes + bytesCount + 2);
6438 byteOffset = headerShift = headerBytes;
6439 } else
6440 headerShift = 0;
6441 pointer.setIntAtOffset(byteOffset - 4, bytesCount); // length header IN BYTES
6442 pointer.setCharsAtOffset(byteOffset, chars);
6443 pointer.setCharAtOffset(byteOffset + bytesCount, (char)0);
6444 // Return a pointer to the WideC string-compatible part of the Pascal WideString
6445 return (Pointer<U>)pointer.offset(headerShift);
6446 case STL:
6447 case WideSTL:
6448 return setSTLString(pointer, byteOffset, s, type, charset);
6449 default:
6450 throw new RuntimeException("Unhandled string type : " + type);
6451 }
6452
6453 return (Pointer<U>)pointer;
6454 } catch (UnsupportedEncodingException ex) {
6455 throwUnexpected(ex);
6456 return null;
6457 }
6458 }
6459
6460 /**
6461 * Allocate memory and write a string to it, using the system's default charset to convert the string (See {@link StringType} for details on the supported types).<br>
6462 * See {@link Pointer#setString(String, StringType)}, {@link Pointer#getString(StringType)}.
6463 * @param charset Character set used to convert String characters to bytes. If null, {@link Charset#defaultCharset()} will be used
6464 * @param type Type of the native String to create.
6465 */
6466 public static Pointer<?> pointerToString(String string, StringType type, Charset charset) {
6467 return setString(null, 0, string, type, charset);
6468 }
6469
6470
6471 /**
6472 * Allocate memory and write a C string to it, using the system's default charset to convert the string. (see {@link StringType#C}).<br>
6473 * See {@link Pointer#setCString(String)}, {@link Pointer#getCString()}.<br>
6474 * See {@link Pointer#pointerToString(String, StringType, Charset)} for choice of the String type or Charset.
6475 */
6476 public static Pointer<Byte> pointerToCString(String string) {
6477 return setString(null, 0, string, StringType.C, null);
6478 }
6479
6480 /**
6481 * The update will take place inside the release() call
6482 */
6483 public static Pointer<Pointer<Byte>> pointerToCStrings(final String... strings) {
6484 if (strings == null)
6485 return null;
6486 final int len = strings.length;
6487 final Pointer<Byte>[] pointers = (Pointer<Byte>[])new Pointer[len];
6488 Pointer<Pointer<Byte>> mem = allocateArray((PointerIO<Pointer<Byte>>)(PointerIO)PointerIO.getPointerInstance(Byte.class), len, new Releaser() {
6489 //@Override
6490 public void release(Pointer<?> p) {
6491 Pointer<Pointer<Byte>> mem = (Pointer<Pointer<Byte>>)p;
6492 for (int i = 0; i < len; i++) {
6493 Pointer<Byte> pp = mem.get(i);
6494 if (pp != null)
6495 strings[i] = pp.getCString();
6496 pp = pointers[i];
6497 if (pp != null)
6498 pp.release();
6499 }
6500 }
6501 });
6502 for (int i = 0; i < len; i++)
6503 mem.set(i, pointers[i] = pointerToCString(strings[i]));
6504
6505 return mem;
6506 }
6507
6508 /**
6509 * Allocate memory and write a WideC string to it, using the system's default charset to convert the string. (see {@link StringType#WideC}).<br>
6510 * See {@link Pointer#setWideCString(String)}, {@link Pointer#getWideCString()}.<br>
6511 * See {@link Pointer#pointerToString(String, StringType, Charset)} for choice of the String type or Charset.
6512 */
6513 public static Pointer<Character> pointerToWideCString(String string) {
6514 return setString(null, 0, string, StringType.WideC, null);
6515 }
6516
6517 /**
6518 * The update will take place inside the release() call
6519 */
6520 public static Pointer<Pointer<Character>> pointerToWideCStrings(final String... strings) {
6521 if (strings == null)
6522 return null;
6523 final int len = strings.length;
6524 final Pointer<Character>[] pointers = (Pointer<Character>[])new Pointer[len];
6525 Pointer<Pointer<Character>> mem = allocateArray((PointerIO<Pointer<Character>>)(PointerIO)PointerIO.getPointerInstance(Character.class), len, new Releaser() {
6526 //@Override
6527 public void release(Pointer<?> p) {
6528 Pointer<Pointer<Character>> mem = (Pointer<Pointer<Character>>)p;
6529 for (int i = 0; i < len; i++) {
6530 Pointer<Character> pp = mem.get(i);
6531 if (pp != null)
6532 strings[i] = pp.getWideCString();
6533 pp = pointers[i];
6534 if (pp != null)
6535 pp.release();
6536 }
6537 }
6538 });
6539 for (int i = 0; i < len; i++)
6540 mem.set(i, pointers[i] = pointerToWideCString(strings[i]));
6541
6542 return mem;
6543 }
6544
6545
6546
6547 //-- StringType: C --
6548
6549 /**
6550 * Read a C string using the default charset from the pointed memory location (see {@link StringType#C}).<br>
6551 * See {@link Pointer#getCStringAtOffset(long)}, {@link Pointer#getString(StringType)} and {@link Pointer#getStringAtOffset(long, StringType, Charset)} for more options
6552 */
6553 public String getCString() {
6554 return getCStringAtOffset(0);
6555 }
6556
6557 /**
6558 * Read a C string using the default charset from the pointed memory location shifted by a byte offset (see {@link StringType#C}).<br>
6559 * See {@link Pointer#getStringAtOffset(long, StringType, Charset)} for more options
6560 */
6561 public String getCStringAtOffset(long byteOffset) {
6562 return getStringAtOffset(byteOffset, StringType.C, null);
6563 }
6564
6565 /**
6566 * Write a C string using the default charset to the pointed memory location (see {@link StringType#C}).<br>
6567 * See {@link Pointer#setCStringAtOffset(long, String)} and {@link Pointer#setStringAtOffset(long, String, StringType, Charset)} for more options
6568 */
6569 public Pointer<T> setCString(String s) {
6570 return setCStringAtOffset(0, s);
6571 }
6572 /**
6573 * Write a C string using the default charset to the pointed memory location shifted by a byte offset (see {@link StringType#C}).<br>
6574 * See {@link Pointer#setStringAtOffset(long, String, StringType, Charset)} for more options
6575 */
6576 public Pointer<T> setCStringAtOffset(long byteOffset, String s) {
6577 return setStringAtOffset(byteOffset, s, StringType.C, null);
6578 }
6579
6580 //-- StringType: WideC --
6581
6582 /**
6583 * Read a WideC string using the default charset from the pointed memory location (see {@link StringType#WideC}).<br>
6584 * See {@link Pointer#getWideCStringAtOffset(long)}, {@link Pointer#getString(StringType)} and {@link Pointer#getStringAtOffset(long, StringType, Charset)} for more options
6585 */
6586 public String getWideCString() {
6587 return getWideCStringAtOffset(0);
6588 }
6589
6590 /**
6591 * Read a WideC string using the default charset from the pointed memory location shifted by a byte offset (see {@link StringType#WideC}).<br>
6592 * See {@link Pointer#getStringAtOffset(long, StringType, Charset)} for more options
6593 */
6594 public String getWideCStringAtOffset(long byteOffset) {
6595 return getStringAtOffset(byteOffset, StringType.WideC, null);
6596 }
6597
6598 /**
6599 * Write a WideC string using the default charset to the pointed memory location (see {@link StringType#WideC}).<br>
6600 * See {@link Pointer#setWideCStringAtOffset(long, String)} and {@link Pointer#setStringAtOffset(long, String, StringType, Charset)} for more options
6601 */
6602 public Pointer<T> setWideCString(String s) {
6603 return setWideCStringAtOffset(0, s);
6604 }
6605 /**
6606 * Write a WideC string using the default charset to the pointed memory location shifted by a byte offset (see {@link StringType#WideC}).<br>
6607 * See {@link Pointer#setStringAtOffset(long, String, StringType, Charset)} for more options
6608 */
6609 public Pointer<T> setWideCStringAtOffset(long byteOffset, String s) {
6610 return setStringAtOffset(byteOffset, s, StringType.WideC, null);
6611 }
6612
6613
6614 /**
6615 * Get the length of the C string at the pointed memory location shifted by a byte offset (see {@link StringType#C}).
6616 */
6617 protected long strlen(long byteOffset) {
6618 long checkedPeer = peer + byteOffset;
6619 if (validStart != UNKNOWN_VALIDITY)
6620 checkPeer(checkedPeer, 1);
6621 return JNI.strlen(checkedPeer);
6622 }
6623
6624 /**
6625 * Get the length of the wide C string at the pointed memory location shifted by a byte offset (see {@link StringType#WideC}).
6626 */
6627 protected long wcslen(long byteOffset) {
6628 long checkedPeer = peer + byteOffset;
6629 if (validStart != UNKNOWN_VALIDITY)
6630 checkPeer(checkedPeer, Platform.WCHAR_T_SIZE);
6631 return JNI.wcslen(checkedPeer);
6632 }
6633
6634 /**
6635 * Write zero bytes to all of the valid bytes pointed by this pointer
6636 */
6637 public void clearValidBytes() {
6638 long bytes = getValidBytes();
6639 if (bytes < 0)
6640 throw new UnsupportedOperationException("Number of valid bytes is unknown. Please use clearBytes(long) or validBytes(long).");
6641 clearBytes(bytes);
6642 }
6643
6644 /**
6645 * Write zero bytes to the first length bytes pointed by this pointer
6646 */
6647 public void clearBytes(long length) {
6648 clearBytesAtOffset(0, length, (byte)0);
6649 }
6650 /**
6651 * Write a byte {@code value} to each of the {@code length} bytes at the address pointed to by this pointer shifted by a {@code byteOffset}
6652 */
6653 public void clearBytesAtOffset(long byteOffset, long length, byte value) {
6654 long checkedPeer = peer + byteOffset;
6655 if (validStart != UNKNOWN_VALIDITY)
6656 checkPeer(checkedPeer, length);
6657 JNI.memset(checkedPeer, value, length);
6658 }
6659
6660 /**
6661 * Find the first occurrence of a value in the memory block of length searchLength bytes pointed by this pointer shifted by a byteOffset
6662 */
6663 public Pointer<T> findByte(long byteOffset, byte value, long searchLength) {
6664 long checkedPeer = peer + byteOffset;
6665 if (validStart != UNKNOWN_VALIDITY)
6666 checkPeer(checkedPeer, searchLength);
6667 long found = JNI.memchr(checkedPeer, value, searchLength);
6668 return found == 0 ? null : offset(found - checkedPeer);
6669 }
6670
6671 /**
6672 * Alias for {@link Pointer#get(long)} defined for more natural use from the Scala language.
6673 */
6674 public final T apply(long index) {
6675 return get(index);
6676 }
6677
6678 /**
6679 * Alias for {@link Pointer#set(long, Object)} defined for more natural use from the Scala language.
6680 */
6681 public final void update(long index, T element) {
6682 set(index, element);
6683 }
6684
6685 /**
6686 * Create an array with all the values in the bounded memory area.<br>
6687 * Note that if you wish to get an array of primitives (if T is boolean, char or a numeric type), then you need to call {@link Pointer#getArray()}.
6688 * @throws IndexOutOfBoundsException if this pointer's bounds are unknown
6689 */
6690 public T[] toArray() {
6691 getIO("Cannot create array");
6692 return toArray((int)getValidElements("Length of pointed memory is unknown, cannot create array out of this pointer"));
6693 }
6694
6695 T[] toArray(int length) {
6696 Class<?> c = Utils.getClass(getIO("Cannot create array").getTargetType());
6697 if (c == null)
6698 throw new RuntimeException("Unable to get the target type's class (target type = " + io.getTargetType() + ")");
6699 return (T[])toArray((Object[])Array.newInstance(c, length));
6700 }
6701
6702 /**
6703 * Create an array with all the values in the bounded memory area, reusing the provided array if its type is compatible and its size is big enough.<br>
6704 * Note that if you wish to get an array of primitives (if T is boolean, char or a numeric type), then you need to call {@link Pointer#getArray()}.
6705 * @throws IndexOutOfBoundsException if this pointer's bounds are unknown
6706 */
6707 public <U> U[] toArray(U[] array) {
6708 int n = (int)getValidElements();
6709 if (n < 0)
6710 throwBecauseUntyped("Cannot create array");
6711
6712 if (array.length != n)
6713 return (U[])toArray();
6714
6715 for (int i = 0; i < n; i++)
6716 array[i] = (U)get(i);
6717 return array;
6718 }
6719
6720 /**
6721 * Types of pointer-based list implementations that can be created through {@link Pointer#asList()} or {@link Pointer#asList(ListType)}.
6722 */
6723 public enum ListType {
6724 /**
6725 * Read-only list
6726 */
6727 Unmodifiable,
6728 /**
6729 * List is modifiable and can shrink, but capacity cannot be increased (some operations will hence throw UnsupportedOperationException when the capacity is unsufficient for the requested operation)
6730 */
6731 FixedCapacity,
6732 /**
6733 * List is modifiable and its underlying memory will be reallocated if it needs to grow beyond its current capacity.
6734 */
6735 Dynamic
6736 }
6737
6738 /**
6739 * Create a {@link ListType#FixedCapacity} native list that uses this pointer as storage (and has this pointer's pointed valid elements as initial content).<br>
6740 * Same as {@link Pointer#asList(ListType)}({@link ListType#FixedCapacity}).
6741 */
6742 public NativeList<T> asList() {
6743 return asList(ListType.FixedCapacity);
6744 }
6745 /**
6746 * Create a native list that uses this pointer as <b>initial</b> storage (and has this pointer's pointed valid elements as initial content).<br>
6747 * If the list is {@link ListType#Dynamic} and if its capacity is grown at some point, this pointer will probably no longer point to the native memory storage of the list, so you need to get back the pointer with {@link NativeList#getPointer()} when you're done mutating the list.
6748 */
6749 public NativeList<T> asList(ListType type) {
6750 return new DefaultNativeList(this, type);
6751 }
6752 /**
6753 * Create a {@link ListType#Dynamic} list with the provided initial capacity (see {@link ListType#Dynamic}).
6754 * @param io Type of the elements of the list
6755 * @param capacity Initial capacity of the list
6756 */
6757 public static <E> NativeList<E> allocateList(PointerIO<E> io, long capacity) {
6758 NativeList<E> list = new DefaultNativeList(allocateArray(io, capacity), ListType.Dynamic);
6759 list.clear();
6760 return list;
6761 }
6762 /**
6763 * Create a {@link ListType#Dynamic} list with the provided initial capacity (see {@link ListType#Dynamic}).
6764 * @param type Type of the elements of the list
6765 * @param capacity Initial capacity of the list
6766 */
6767 public static <E> NativeList<E> allocateList(Class<E> type, long capacity) {
6768 return allocateList((Type)type, capacity);
6769 }
6770 /**
6771 * Create a {@link ListType#Dynamic} list with the provided initial capacity (see {@link ListType#Dynamic}).
6772 * @param type Type of the elements of the list
6773 * @param capacity Initial capacity of the list
6774 */
6775 public static <E> NativeList<E> allocateList(Type type, long capacity) {
6776 return (NativeList)allocateList(PointerIO.getInstance(type), capacity);
6777 }
6778
6779 private static char[] intsToWChars(int[] in) {
6780 int n = in.length;
6781 char[] out = new char[n];
6782 for (int i = 0; i < n; i++)
6783 out[i] = (char)in[i];
6784 return out;
6785 }
6786 private static int[] wcharsToInts(char[] in, int valuesOffset, int length) {
6787 int[] out = new int[length];
6788 for (int i = 0; i < length; i++)
6789 out[i] = in[valuesOffset + i];
6790 return out;
6791 }
6792 }