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