001 /* This library is free software; you can redistribute it and/or 002 * modify it under the terms of the GNU Lesser General Public 003 * License as published by the Free Software Foundation; either 004 * version 2.1 of the License, or (at your option) any later version. 005 * <p/> 006 * This library is distributed in the hope that it will be useful, 007 * but WITHOUT ANY WARRANTY; without even the implied warranty of 008 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 009 * Lesser General Public License for more details. 010 */ 011 package com.sun.jna; 012 013 import com.sun.jna.ptr.ByReference; 014 import java.io.UnsupportedEncodingException; 015 import java.lang.reflect.Array; 016 import java.nio.Buffer; 017 import java.nio.ByteBuffer; 018 import java.nio.ByteOrder; 019 import java.util.ArrayList; 020 import java.util.HashMap; 021 import java.util.List; 022 import java.util.Map; 023 024 /** 025 * An abstraction for a native pointer data type. A Pointer instance 026 * represents, on the Java side, a native pointer. The native pointer could 027 * be any <em>type</em> of native pointer. Methods such as <code>write</code>, 028 * <code>read</code>, <code>getXXX</code>, and <code>setXXX</code>, provide 029 * means to access memory underlying the native pointer.<p> 030 * The constructors are intentionally package-private, since it's not generally 031 * a good idea to be creating C pointers de novo. 032 * 033 * @author Sheng Liang, originator 034 * @author Todd Fast, suitability modifications 035 * @author Timothy Wall, robust library loading 036 * @see Function 037 */ 038 public class Pointer { 039 040 /** Size of a native pointer, in bytes. */ 041 public static final int SIZE; 042 043 static { 044 // Force load of native library 045 if ((SIZE = Native.POINTER_SIZE) == 0) { 046 throw new Error("Native library not initialized"); 047 } 048 } 049 050 /** Convenience constant, same as <code>null</code>. */ 051 public static final Pointer NULL = null; 052 053 /** Convenience constant, equivalent to <code>(void*)-1</code>. */ 054 public static final Pointer createConstant(long peer) { 055 return new Opaque(peer); 056 } 057 058 /** Pointer value of the real native pointer. Use long to be 64-bit safe. 059 */ 060 protected long peer; 061 062 /** Derived class must assign peer pointer value. */ 063 Pointer() { } 064 065 /** Create from native pointer. */ 066 Pointer(long peer) { 067 this.peer = peer; 068 } 069 070 public Pointer share(long offset) { 071 return share(offset, 0); 072 } 073 074 /** Provide a view of this pointer with a different peer base. */ 075 public Pointer share(long offset, long sz) { 076 if (offset == 0) return this; 077 return new Pointer(peer + offset); 078 } 079 080 /** Zero memory for the given number of bytes. */ 081 public void clear(long size) { 082 setMemory(0, size, (byte)0); 083 } 084 085 /** 086 * Compares this <code>Pointer</code> to the specified object. 087 * 088 * @param o 089 * A <code>Pointer</code> instance 090 * @return True if the other object is a <code>Pointer</code>, 091 * and the C pointers being pointed to by these objects are also 092 * equal. Returns false otherwise. 093 */ 094 public boolean equals(Object o) { 095 if (o == this) return true; 096 if (o == null) return false; 097 return o instanceof Pointer && ((Pointer)o).peer == peer; 098 } 099 100 /** 101 * Returns a hashcode for the native pointer represented by this 102 * <code>Pointer</code> object 103 * 104 * @return A hash code value for the represented native pointer 105 */ 106 public int hashCode() { 107 return (int)((peer >>> 32) + (peer & 0xFFFFFFFF)); 108 } 109 110 111 ////////////////////////////////////////////////////////////////////////// 112 // Raw read methods 113 ////////////////////////////////////////////////////////////////////////// 114 115 /** Returns the offset of the given value in memory from the given offset, 116 * or -1 if the value is not found. 117 */ 118 public long indexOf(long offset, byte value) { 119 return _indexOf(peer + offset, value); 120 } 121 122 private static native long _indexOf(long addr, byte value); 123 124 /** 125 * Indirect the native pointer, copying <em>from</em> memory pointed to by 126 * native pointer, into the specified array. 127 * 128 * @param offset byte offset from pointer into which data is copied 129 * @param buf <code>byte</code> array into which data is copied 130 * @param index array index from which to start copying 131 * @param length number of elements from native pointer that must be copied 132 */ 133 public void read(long offset, byte[] buf, int index, int length) { 134 _read(peer + offset, buf, index, length); 135 } 136 137 private static native void _read(long addr, byte[] buf, int index, int length); 138 139 140 /** 141 * Indirect the native pointer, copying <em>from</em> memory pointed to by 142 * native pointer, into the specified array. 143 * 144 * @param offset byte offset from pointer from which data is copied 145 * @param buf <code>short</code> array into which data is copied 146 * @param index array index to which data is copied 147 * @param length number of elements from native pointer that must be copied 148 */ 149 public void read(long offset, short[] buf, int index, int length) { 150 _read(peer + offset, buf, index, length); 151 } 152 153 private static native void _read(long addr, short[] buf, int index, int length); 154 155 156 /** 157 * Indirect the native pointer, copying <em>from</em> memory pointed to by 158 * native pointer, into the specified array. 159 * 160 * @param offset byte offset from pointer from which data is copied 161 * @param buf <code>char</code> array into which data is copied 162 * @param index array index to which data is copied 163 * @param length number of elements from native pointer that must be copied 164 */ 165 public void read(long offset, char[] buf, int index, int length) { 166 _read(peer + offset, buf, index, length); 167 } 168 169 private static native void _read(long addr, char[] buf, int index, int length); 170 171 172 /** 173 * Indirect the native pointer, copying <em>from</em> memory pointed to by 174 * native pointer, into the specified array. 175 * 176 * @param offset byte offset from pointer from which data is copied 177 * @param buf <code>int</code> array into which data is copied 178 * @param index array index to which data is copied 179 * @param length number of elements from native pointer that must be copied 180 */ 181 public void read(long offset, int[] buf, int index, int length) { 182 _read(peer + offset, buf, index, length); 183 } 184 185 private static native void _read(long addr, int[] buf, int index, int length); 186 187 /** 188 * Indirect the native pointer, copying <em>from</em> memory pointed to by 189 * native pointer, into the specified array. 190 * 191 * @param offset byte offset from pointer from which data is copied 192 * @param buf <code>long</code> array into which data is copied 193 * @param index array index to which data is copied 194 * @param length number of elements from native pointer that must be copied 195 */ 196 public void read(long offset, long[] buf, int index, int length) { 197 _read(peer + offset, buf, index, length); 198 } 199 200 private static native void _read(long addr, long[] buf, int index, int length); 201 202 /** 203 * Indirect the native pointer, copying <em>from</em> memory pointed to by 204 * native pointer, into the specified array. 205 * 206 * @param offset byte offset from pointer from which data is copied 207 * @param buf <code>float</code> array into which data is copied 208 * @param index array index to which data is copied 209 * @param length number of elements from native pointer that must be copied 210 */ 211 public void read(long offset, float[] buf, int index, int length) { 212 _read(peer + offset, buf, index, length); 213 } 214 215 private static native void _read(long addr, float[] buf, int index, int length); 216 217 /** 218 * Indirect the native pointer, copying <em>from</em> memory pointed to by 219 * native pointer, into the specified array. 220 * 221 * @param offset byte offset from pointer from which data is copied 222 * @param buf <code>double</code> array into which data is copied 223 * @param index array index to which data is copied 224 * @param length number of elements from native pointer that must be copied 225 */ 226 public void read(long offset, double[] buf, int index, int length) { 227 _read(peer + offset, buf, index, length); 228 } 229 230 private static native void _read(long addr, double[] buf, int index, int length); 231 232 /** 233 * Indirect the native pointer, copying <em>from</em> memory pointed to by 234 * native pointer, into the specified array. 235 * 236 * @param offset byte offset from pointer from which data is copied 237 * @param buf {@link Pointer} array into which data is copied 238 * @param index array index to which data is copied 239 * @param length number of elements from native pointer that must be copied 240 */ 241 public void read(long offset, Pointer[] buf, int index, int length) { 242 for (int i=0;i < length;i++) { 243 buf[i + index] = getPointer(offset + i*Pointer.SIZE); 244 } 245 } 246 247 248 ////////////////////////////////////////////////////////////////////////// 249 // Raw write methods 250 ////////////////////////////////////////////////////////////////////////// 251 252 /** 253 * Indirect the native pointer, copying <em>into</em> memory pointed to by 254 * native pointer, from the specified array. 255 * 256 * @param offset byte offset from pointer into which data is copied 257 * @param buf <code>byte</code> array from which to copy 258 * @param index array index from which to start copying 259 * @param length number of elements from <code>buf</code> that must be 260 * copied 261 */ 262 public void write(long offset, byte[] buf, int index, int length) { 263 _write(peer + offset, buf, index, length); 264 } 265 266 private static native void _write(long addr, byte[] buf, int index, int length); 267 268 269 /** 270 * Indirect the native pointer, copying <em>into</em> memory pointed to by 271 * native pointer, from the specified array. 272 * 273 * @param offset byte offset from pointer into which data is copied 274 * @param buf <code>short</code> array from which to copy 275 * @param index array index from which to start copying 276 * @param length number of elements from <code>buf</code> that must be 277 * copied 278 */ 279 public void write(long offset, short[] buf, int index, int length) { 280 _write(peer + offset, buf, index, length); 281 } 282 283 private static native void _write(long addr, short[] buf, int index, int length); 284 285 /** 286 * Indirect the native pointer, copying <em>into</em> memory pointed to by 287 * native pointer, from the specified array. 288 * 289 * @param offset byte offset from pointer into which data is copied 290 * @param buf <code>char</code> array from which to copy 291 * @param index array index from which to start copying 292 * @param length number of elements from <code>buf</code> that must be 293 * copied 294 */ 295 public void write(long offset, char[] buf, int index, int length) { 296 _write(peer + offset, buf, index, length); 297 } 298 299 private static native void _write(long addr, char[] buf, int index, int length); 300 301 /** 302 * Indirect the native pointer, copying <em>into</em> memory pointed to by 303 * native pointer, from the specified array. 304 * 305 * @param offset byte offset from pointer into which data is copied 306 * @param buf <code>int</code> array from which to copy 307 * @param index array index from which to start copying 308 * @param length number of elements from <code>buf</code> that must be 309 * copied 310 */ 311 public void write(long offset, int[] buf, int index, int length) { 312 _write(peer + offset, buf, index, length); 313 } 314 315 private static native void _write(long addr, int[] buf, int index, int length); 316 317 /** 318 * Indirect the native pointer, copying <em>into</em> memory pointed to by 319 * native pointer, from the specified array. 320 * 321 * @param offset byte offset from pointer into which data is copied 322 * @param buf <code>long</code> array from which to copy 323 * @param index array index from which to start copying 324 * @param length number of elements from <code>buf</code> that must be 325 * copied 326 */ 327 public void write(long offset, long[] buf, int index, int length) { 328 _write(peer + offset, buf, index, length); 329 } 330 331 private static native void _write(long addr, long[] buf, int index, int length); 332 333 /** 334 * Indirect the native pointer, copying <em>into</em> memory pointed to by 335 * native pointer, from the specified array. 336 * 337 * @param offset byte offset from pointer into which data is copied 338 * @param buf <code>float</code> array from which to copy 339 * @param index array index from which to start copying 340 * @param length number of elements from <code>buf</code> that must be 341 * copied 342 */ 343 public void write(long offset, float[] buf, int index, int length) { 344 _write(peer + offset, buf, index, length); 345 } 346 347 private static native void _write(long addr, float[] buf, int index, int length); 348 349 /** 350 * Indirect the native pointer, copying <em>into</em> memory pointed to by 351 * native pointer, from the specified array. 352 * 353 * @param offset byte offset from pointer into which data is copied 354 * @param buf <code>double</code> array from which to copy 355 * @param index array index from which to start copying 356 * @param length number of elements from <code>buf</code> that must be 357 * copied 358 */ 359 public void write(long offset, double[] buf, int index, int length) { 360 _write(peer + offset, buf, index, length); 361 } 362 363 private static native void _write(long addr, double[] buf, int index, int length); 364 365 /** Write the given array of Pointer to native memory. 366 * @param bOff byte offset from pointer into which data is copied 367 * @param buf <code>Pointer</code> array from which to copy 368 * @param index array index from which to start copying 369 * @param length number of elements from <code>buf</code> that must be 370 * copied 371 */ 372 public void write(long bOff, Pointer[] buf, int index, int length) { 373 for (int i=0;i < length;i++) { 374 setPointer(bOff + i * Pointer.SIZE, buf[index + i]); 375 } 376 } 377 378 ////////////////////////////////////////////////////////////////////////// 379 // Java type read methods 380 ////////////////////////////////////////////////////////////////////////// 381 382 Object getValue(long offset, Class type, Object currentValue) { 383 return getValue(offset, 0, 0, type, currentValue); 384 } 385 386 Object getValue(long offset, int bitOffset, int bits, Class type, Object currentValue) { 387 388 Object result = BitFields.getPrimitiveValue(this, offset, bitOffset, bits, type); 389 if (result != BitFields.UNHANDLED_TYPE) 390 return result; 391 392 result = null; 393 if (Structure.class.isAssignableFrom(type)) { 394 Structure s = (Structure)currentValue; 395 if (Structure.ByReference.class.isAssignableFrom(type)) { 396 s = Structure.updateStructureByReference(type, s, getPointer(offset)); 397 } 398 else { 399 s.useMemory(this, (int)offset); 400 s.read(); 401 } 402 result = s; 403 } 404 else if (Pointer.class.isAssignableFrom(type)) { 405 Pointer p = getPointer(offset); 406 if (p != null) { 407 Pointer oldp = currentValue instanceof Pointer 408 ? (Pointer)currentValue : null; 409 if (oldp == null || p.peer != oldp.peer) 410 result = p; 411 else 412 result = oldp; 413 } 414 } 415 else if (Callback.class.isAssignableFrom(type)) { 416 // Overwrite the Java memory if the native pointer is a different 417 // function pointer. 418 Pointer fp = getPointer(offset); 419 if (fp == null) { 420 result = null; 421 } 422 else { 423 Callback cb = (Callback)currentValue; 424 Pointer oldfp = CallbackReference.getFunctionPointer(cb); 425 if (!fp.equals(oldfp)) { 426 cb = CallbackReference.getCallback(type, fp); 427 } 428 result = cb; 429 } 430 } 431 else if (Buffer.class.isAssignableFrom(type)) { 432 Pointer bp = getPointer(offset); 433 if (bp == null) { 434 result = null; 435 } 436 else { 437 Pointer oldbp = currentValue == null ? null 438 : Native.getDirectBufferPointer((Buffer)currentValue); 439 if (oldbp == null || !oldbp.equals(bp)) { 440 throw new IllegalStateException("Can't autogenerate a direct buffer on memory read"); 441 } 442 } 443 } 444 else if (NativeMapped.class.isAssignableFrom(type)) { 445 NativeMapped nm = (NativeMapped)currentValue; 446 if (nm != null) { 447 Object value = getValue(offset, nm.nativeType(), null); 448 result = nm.fromNative(value, new FromNativeContext(type)); 449 } 450 else { 451 NativeMappedConverter tc = NativeMappedConverter.getInstance(type); 452 Object value = getValue(offset, tc.nativeType(), null); 453 result = tc.fromNative(value, new FromNativeContext(type)); 454 } 455 } 456 else if (type.isArray()) { 457 result = currentValue; 458 if (result == null) { 459 throw new IllegalStateException("Need an initialized array"); 460 } 461 getArrayValue(offset, result, type.getComponentType()); 462 } 463 else { 464 throw new IllegalArgumentException("Reading \"" 465 + type + "\" from memory is not supported"); 466 } 467 return result; 468 } 469 470 private void getArrayValue(long offset, Object o, Class cls) { 471 int length = 0; 472 length = Array.getLength(o); 473 Object result = o; 474 475 if (cls == byte.class) { 476 read(offset, (byte[])result, 0, length); 477 } 478 else if (cls == short.class) { 479 read(offset, (short[])result, 0, length); 480 } 481 else if (cls == char.class) { 482 read(offset, (char[])result, 0, length); 483 } 484 else if (cls == int.class) { 485 read(offset, (int[])result, 0, length); 486 } 487 else if (cls == long.class) { 488 read(offset, (long[])result, 0, length); 489 } 490 else if (cls == float.class) { 491 read(offset, (float[])result, 0, length); 492 } 493 else if (cls == double.class) { 494 read(offset, (double[])result, 0, length); 495 } 496 else if (Pointer.class.isAssignableFrom(cls)) { 497 read(offset, (Pointer[])result, 0, length); 498 } 499 else if (Structure.class.isAssignableFrom(cls)) { 500 Structure[] sarray = (Structure[])result; 501 if (Structure.ByReference.class.isAssignableFrom(cls)) { 502 Pointer[] parray = getPointerArray(offset, sarray.length); 503 for (int i=0;i < sarray.length;i++) { 504 sarray[i] = Structure.updateStructureByReference(cls, sarray[i], parray[i]); 505 } 506 } 507 else { 508 for (int i=0;i < sarray.length;i++) { 509 if (sarray[i] == null) { 510 sarray[i] = Structure.newInstance(cls); 511 } 512 sarray[i].useMemory(this, (int)(offset + i * sarray[i].size())); 513 sarray[i].read(); 514 } 515 } 516 } 517 else if (NativeMapped.class.isAssignableFrom(cls)) { 518 NativeMapped[] array = (NativeMapped[])result; 519 NativeMappedConverter tc = NativeMappedConverter.getInstance(cls); 520 int size = Native.getNativeSize(result.getClass(), result) / array.length; 521 for (int i=0;i < array.length;i++) { 522 Object value = getValue(offset + size*i, tc.nativeType(), array[i]); 523 array[i] = (NativeMapped)tc.fromNative(value, new FromNativeContext(cls)); 524 } 525 } 526 else { 527 throw new IllegalArgumentException("Reading array of " 528 + cls 529 + " from memory not supported"); 530 } 531 } 532 533 /** 534 * Indirect the native pointer as a pointer to <code>byte</code>. This is 535 * equivalent to the expression 536 * <code>*((jbyte *)((char *)Pointer + offset))</code>. 537 * 538 * @param offset offset from pointer to perform the indirection 539 * @return the <code>byte</code> value being pointed to 540 */ 541 public byte getByte(long offset) { 542 return _getByte(peer + offset); 543 } 544 545 private static native byte _getByte(long addr); 546 547 /** 548 * Indirect the native pointer as a pointer to <code>wchar_t</code>. This 549 * is equivalent to the expression 550 * <code>*((wchar_t*)((char *)Pointer + offset))</code>. 551 * 552 * @param offset offset from pointer to perform the indirection 553 * @return the <code>wchar_t</code> value being pointed to 554 */ 555 public char getChar(long offset) { 556 return _getChar(peer + offset); 557 } 558 559 private static native char _getChar(long addr); 560 561 /** 562 * Indirect the native pointer as a pointer to <code>short</code>. This is 563 * equivalent to the expression 564 * <code>*((jshort *)((char *)Pointer + offset))</code>. 565 * 566 * @param offset byte offset from pointer to perform the indirection 567 * @return the <code>short</code> value being pointed to 568 */ 569 public short getShort(long offset) { 570 return _getShort(peer + offset); 571 } 572 573 private static native short _getShort(long addr); 574 575 /** 576 * Indirect the native pointer as a pointer to <code>int</code>. This is 577 * equivalent to the expression 578 * <code>*((jint *)((char *)Pointer + offset))</code>. 579 * 580 * @param offset byte offset from pointer to perform the indirection 581 * @return the <code>int</code> value being pointed to 582 */ 583 public int getInt(long offset) { 584 return _getInt(peer + offset); 585 } 586 587 private static native int _getInt(long addr); 588 589 /** 590 * Indirect the native pointer as a pointer to <code>long</code>. This is 591 * equivalent to the expression 592 * <code>*((jlong *)((char *)Pointer + offset))</code>. 593 * 594 * @param offset byte offset from pointer to perform the indirection 595 * @return the <code>long</code> value being pointed to 596 */ 597 public long getLong(long offset) { 598 return _getLong(peer + offset); 599 } 600 601 private static native long _getLong(long addr); 602 603 /** 604 * Indirect the native pointer as a pointer to <code>long</code>. This is 605 * equivalent to the expression 606 * <code>*((long *)((char *)Pointer + offset))</code>. 607 * 608 * @param offset byte offset from pointer to perform the indirection 609 * @return the <code>long</code> value being pointed to 610 */ 611 public NativeLong getNativeLong(long offset) { 612 return new NativeLong(NativeLong.SIZE == 8 ? getLong(offset) : getInt(offset)); 613 } 614 615 /** 616 * Indirect the native pointer as a pointer to <code>float</code>. This is 617 * equivalent to the expression 618 * <code>*((jfloat *)((char *)Pointer + offset))</code>. 619 * 620 * @param offset byte offset from pointer to perform the indirection 621 * @return the <code>float</code> value being pointed to 622 */ 623 public float getFloat(long offset) { 624 return _getFloat(peer + offset); 625 } 626 627 private native float _getFloat(long addr); 628 629 /** 630 * Indirect the native pointer as a pointer to <code>double</code>. This 631 * is equivalent to the expression 632 * <code>*((jdouble *)((char *)Pointer + offset))</code>. 633 * 634 * @param offset byte offset from pointer to perform the indirection 635 * @return the <code>double</code> value being pointed to 636 */ 637 public double getDouble(long offset) { 638 return _getDouble(peer + offset); 639 } 640 641 private static native double _getDouble(long addr); 642 643 /** 644 * Indirect the native pointer as a pointer to pointer. This is equivalent 645 * to the expression 646 * <code>*((void **)((char *)Pointer + offset))</code>. 647 * 648 * @param offset byte offset from pointer to perform the indirection 649 * @return a {@link Pointer} equivalent of the pointer value 650 * being pointed to, or <code>null</code> if the pointer value is 651 * <code>NULL</code>; 652 */ 653 public Pointer getPointer(long offset) { 654 return _getPointer(peer + offset); 655 } 656 657 private static native Pointer _getPointer(long addr); 658 659 /** 660 * Get a ByteBuffer mapped to the memory pointed to by the pointer, 661 * ensuring the buffer uses native byte order. 662 * 663 * @param offset byte offset from pointer to start the buffer 664 * @param length Length of ByteBuffer 665 * @return a direct ByteBuffer that accesses the memory being pointed to, 666 */ 667 public ByteBuffer getByteBuffer(long offset, long length) { 668 return _getDirectByteBuffer(peer + offset, length).order(ByteOrder.nativeOrder()); 669 } 670 671 /** 672 * Get a direct ByteBuffer mapped to the memory pointed to by the pointer. 673 * 674 * @param addr byte offset from pointer to start the buffer 675 * @param length Length of ByteBuffer 676 * @return a direct ByteBuffer that accesses the memory being pointed to, 677 */ 678 private native ByteBuffer _getDirectByteBuffer(long addr, long length); 679 680 /** 681 * Copy native memory to a Java String. If <code>wide</code> is true, 682 * access the memory as an array of <code>wchar_t</code>, otherwise 683 * as an array of <code>char</code>, using the default platform encoding. 684 * 685 * @param offset byte offset from pointer to obtain the native string 686 v * @param wide whether to convert from a wide or standard C string 687 * @return the <code>String</code> value being pointed to 688 */ 689 public String getString(long offset, boolean wide) { 690 return _getString(peer + offset, wide); 691 } 692 693 private static native String _getString(long addr, boolean wide); 694 695 /** 696 * Copy native memory to a Java String. If the system property 697 * <code>jna.encoding</code> is set, uses it as the native charset 698 * when decoding the value, otherwise falls back to the default platform 699 * encoding. 700 * 701 * @param offset byte offset from pointer to obtain the native string 702 * @return the <code>String</code> value being pointed to 703 */ 704 public String getString(long offset) { 705 String encoding = System.getProperty("jna.encoding"); 706 if (encoding != null) { 707 long len = indexOf(offset, (byte)0); 708 if (len != -1) { 709 if (len > Integer.MAX_VALUE) { 710 throw new OutOfMemoryError("String exceeds maximum length: " + len); 711 } 712 byte[] data = getByteArray(offset, (int)len); 713 try { 714 return new String(data, encoding); 715 } 716 catch(UnsupportedEncodingException e) { 717 } 718 } 719 } 720 return getString(offset, false); 721 } 722 723 public byte[] getByteArray(long offset, int arraySize) { 724 byte[] buf = new byte[arraySize]; 725 read(offset, buf, 0, arraySize); 726 return buf; 727 } 728 729 public char[] getCharArray(long offset, int arraySize) { 730 char[] buf = new char[arraySize]; 731 read(offset, buf, 0, arraySize); 732 return buf; 733 } 734 735 public short[] getShortArray(long offset, int arraySize) { 736 short[] buf = new short[arraySize]; 737 read(offset, buf, 0, arraySize); 738 return buf; 739 } 740 741 public int[] getIntArray(long offset, int arraySize) { 742 int[] buf = new int[arraySize]; 743 read(offset, buf, 0, arraySize); 744 return buf; 745 } 746 747 public long[] getLongArray(long offset, int arraySize) { 748 long[] buf = new long[arraySize]; 749 read(offset, buf, 0, arraySize); 750 return buf; 751 } 752 753 public float[] getFloatArray(long offset, int arraySize) { 754 float[] buf = new float[arraySize]; 755 read(offset, buf, 0, arraySize); 756 return buf; 757 } 758 759 public double[] getDoubleArray(long offset, int arraySize) { 760 double[] buf = new double[arraySize]; 761 read(offset, buf, 0, arraySize); 762 return buf; 763 } 764 765 /** Returns an array of {@link Pointer}. The array length is 766 * determined by a NULL-valued terminating element. 767 */ 768 public Pointer[] getPointerArray(long base) { 769 List array = new ArrayList(); 770 int offset = 0; 771 Pointer p = getPointer(base); 772 while (p != null) { 773 array.add(p); 774 offset += Pointer.SIZE; 775 p = getPointer(base + offset); 776 } 777 return (Pointer[])array.toArray(new Pointer[array.size()]); 778 } 779 780 /** Returns an array of {@link Pointer} of the requested size. */ 781 public Pointer[] getPointerArray(long offset, int arraySize) { 782 Pointer[] buf = new Pointer[arraySize]; 783 read(offset, buf, 0, arraySize); 784 return buf; 785 } 786 787 /** Returns an array of <code>String</code> based on a native array 788 * of <code>char *</code>. The array length is determined by a 789 * NULL-valued terminating element. 790 */ 791 public String[] getStringArray(long base) { 792 return getStringArray(base, -1, false); 793 } 794 795 /** Returns an array of <code>String</code> based on a native array 796 * of <code>char *</code>, using the given array length. 797 */ 798 public String[] getStringArray(long base, int length) { 799 return getStringArray(base, length, false); 800 } 801 802 /** Returns an array of <code>String</code> based on a native array 803 * of <code>char*</code> or <code>wchar_t*</code> based on the 804 * <code>wide</code> parameter. The array length is determined by a 805 * NULL-valued terminating element. 806 */ 807 public String[] getStringArray(long base, boolean wide) { 808 return getStringArray(base, -1, wide); 809 } 810 811 /** Returns an array of <code>String</code> based on a native array 812 * of <code>char*</code> or <code>wchar_t*</code> based on the 813 * <code>wide</code> parameter, using the given array length. 814 */ 815 public String[] getStringArray(long base, int length, boolean wide) { 816 817 List strings = new ArrayList(); 818 int offset = 0; 819 Pointer p = getPointer(base); 820 if (length != -1) { 821 int count = 0; 822 while (count++ < length) { 823 strings.add(p.getString(0, wide)); 824 offset += SIZE; 825 p = getPointer(base + offset); 826 } 827 } 828 else { 829 while (p != null) { 830 strings.add(p.getString(0, wide)); 831 offset += SIZE; 832 p = getPointer(base + offset); 833 } 834 } 835 return (String[])strings.toArray(new String[strings.size()]); 836 } 837 838 ////////////////////////////////////////////////////////////////////////// 839 // Java type write methods 840 ////////////////////////////////////////////////////////////////////////// 841 842 void setValue(long offset, Object value, Class type) { 843 setValue(offset, 0, 0, value, type); 844 } 845 846 void setValue(long offset, int bitOffset, int bits, Object value, Class type) { 847 848 if (BitFields.setPrimitiveValue(this, offset, bitOffset, bits, value, type)) 849 return; 850 851 if (type == Pointer.class) { 852 setPointer(offset, (Pointer)value); 853 } else if (Structure.class.isAssignableFrom(type)) { 854 Structure s = (Structure)value; 855 if (Structure.ByReference.class.isAssignableFrom(type)) { 856 setPointer(offset, s == null ? null : s.getPointer()); 857 if (s != null) { 858 s.autoWrite(); 859 } 860 } 861 else { 862 s.useMemory(this, (int)offset); 863 s.write(); 864 } 865 } 866 else if (Callback.class.isAssignableFrom(type)) { 867 setPointer(offset, CallbackReference.getFunctionPointer((Callback)value)); 868 } 869 else if (Buffer.class.isAssignableFrom(type)) { 870 Pointer p = value == null ? null 871 : Native.getDirectBufferPointer((Buffer)value); 872 setPointer(offset, p); 873 } 874 else if (NativeMapped.class.isAssignableFrom(type)) { 875 NativeMappedConverter tc = NativeMappedConverter.getInstance(type); 876 Class nativeType = tc.nativeType(); 877 setValue(offset, bitOffset, bits, tc.toNative(value, new ToNativeContext()), nativeType); 878 } 879 else if (type.isArray()) { 880 setArrayValue(offset, value, type.getComponentType()); 881 } 882 else { 883 throw new IllegalArgumentException("Writing " + type + " to memory is not supported"); 884 } 885 } 886 887 private void setArrayValue(long offset, Object value, Class cls) { 888 if (cls == byte.class) { 889 byte[] buf = (byte[])value; 890 write(offset, buf, 0, buf.length); 891 } 892 else if (cls == short.class) { 893 short[] buf = (short[])value; 894 write(offset, buf, 0, buf.length); 895 } 896 else if (cls == char.class) { 897 char[] buf = (char[])value; 898 write(offset, buf, 0, buf.length); 899 } 900 else if (cls == int.class) { 901 int[] buf = (int[])value; 902 write(offset, buf, 0, buf.length); 903 } 904 else if (cls == long.class) { 905 long[] buf = (long[])value; 906 write(offset, buf, 0, buf.length); 907 } 908 else if (cls == float.class) { 909 float[] buf = (float[])value; 910 write(offset, buf, 0, buf.length); 911 } 912 else if (cls == double.class) { 913 double[] buf = (double[])value; 914 write(offset, buf, 0, buf.length); 915 } 916 else if (Pointer.class.isAssignableFrom(cls)) { 917 Pointer[] buf = (Pointer[])value; 918 write(offset, buf, 0, buf.length); 919 } 920 else if (Structure.class.isAssignableFrom(cls)) { 921 Structure[] sbuf = (Structure[])value; 922 if (Structure.ByReference.class.isAssignableFrom(cls)) { 923 Pointer[] buf = new Pointer[sbuf.length]; 924 for (int i=0;i < sbuf.length;i++) { 925 buf[i] = sbuf[i] == null ? null : sbuf[i].getPointer(); 926 sbuf[i].write(); 927 } 928 write(offset, buf, 0, buf.length); 929 } 930 else { 931 for (int i=0;i < sbuf.length;i++) { 932 if (sbuf[i] == null) { 933 sbuf[i] = Structure.newInstance(cls); 934 } 935 sbuf[i].useMemory(this, (int)(offset + i * sbuf[i].size())); 936 sbuf[i].write(); 937 } 938 } 939 } 940 else if (NativeMapped.class.isAssignableFrom(cls)) { 941 NativeMapped[] buf = (NativeMapped[])value; 942 NativeMappedConverter tc = NativeMappedConverter.getInstance(cls); 943 Class nativeType = tc.nativeType(); 944 int size = Native.getNativeSize(value.getClass(), value) / buf.length; 945 for (int i=0;i < buf.length;i++) { 946 Object element = tc.toNative(buf[i], new ToNativeContext()); 947 setValue(offset + i*size, element, nativeType); 948 } 949 } 950 else { 951 throw new IllegalArgumentException("Writing array of " 952 + cls + " to memory not supported"); 953 } 954 } 955 956 /** Write <code>value</code> to the requested bank of memory. 957 * @param offset byte offset from pointer to start 958 * @param length number of bytes to write 959 * @param value value to be written 960 */ 961 public void setMemory(long offset, long length, byte value) { 962 _setMemory(peer + offset, length, value); 963 } 964 965 static native void _setMemory(long addr, long length, byte value); 966 967 /** 968 * Set <code>value</code> at location being pointed to. This is equivalent 969 * to the expression 970 * <code>*((jbyte *)((char *)Pointer + offset)) = value</code>. 971 * 972 * @param offset byte offset from pointer at which <code>value</code> 973 * must be set 974 * @param value <code>byte</code> value to set 975 */ 976 public void setByte(long offset, byte value) { 977 _setByte(peer + offset, value); 978 } 979 980 private static native void _setByte(long addr, byte value); 981 982 /** 983 * Set <code>value</code> at location being pointed to. This is equivalent 984 * to the expression 985 * <code>*((jshort *)((char *)Pointer + offset)) = value</code>. 986 * 987 * @param offset byte offset from pointer at which <code>value</code> 988 * must be set 989 * @param value <code>short</code> value to set 990 */ 991 public void setShort(long offset, short value) { 992 _setShort(peer + offset, value); 993 } 994 995 private static native void _setShort(long addr, short value); 996 997 /** 998 * Set <code>value</code> at location being pointed to. This is equivalent 999 * to the expression 1000 * <code>*((wchar_t *)((char *)Pointer + offset)) = value</code>. 1001 * 1002 * @param offset byte offset from pointer at which <code>value</code> 1003 * must be set 1004 * @param value <code>char</code> value to set 1005 */ 1006 public void setChar(long offset, char value) { 1007 _setChar(peer + offset, value); 1008 } 1009 1010 private static native void _setChar(long addr, char value); 1011 1012 /** 1013 * Set <code>value</code> at location being pointed to. This is equivalent 1014 * to the expression 1015 * <code>*((jint *)((char *)Pointer + offset)) = value</code>. 1016 * 1017 * @param offset byte offset from pointer at which <code>value</code> 1018 * must be set 1019 * @param value <code>int</code> value to set 1020 */ 1021 public void setInt(long offset, int value) { 1022 _setInt(peer + offset, value); 1023 } 1024 1025 private static native void _setInt(long addr, int value); 1026 1027 /** 1028 * Set <code>value</code> at location being pointed to. This is equivalent 1029 * to the expression 1030 * <code>*((jlong *)((char *)Pointer + offset)) = value</code>. 1031 * 1032 * @param offset byte offset from pointer at which <code>value</code> 1033 * must be set 1034 * @param value <code>long</code> value to set 1035 */ 1036 public void setLong(long offset, long value) { 1037 _setLong(peer + offset, value); 1038 } 1039 1040 private static native void _setLong(long addr, long value); 1041 1042 /** 1043 * Set <code>value</code> at location being pointed to. This is equivalent 1044 * to the expression 1045 * <code>*((long *)((char *)Pointer + offset)) = value</code>. 1046 * 1047 * @param offset byte offset from pointer at which <code>value</code> 1048 * must be set 1049 * @param value <code>long</code> value to set 1050 */ 1051 public void setNativeLong(long offset, NativeLong value) { 1052 if (NativeLong.SIZE == 8) { 1053 setLong(offset, value.longValue()); 1054 } else { 1055 setInt(offset, value.intValue()); 1056 } 1057 } 1058 1059 /** 1060 * Set <code>value</code> at location being pointed to. This is equivalent 1061 * to the expression 1062 * <code>*((jfloat *)((char *)Pointer + offset)) = value</code>. 1063 * 1064 * @param offset byte offset from pointer at which <code>value</code> 1065 * must be set 1066 * @param value <code>float</code> value to set 1067 */ 1068 public void setFloat(long offset, float value) { 1069 _setFloat(peer + offset, value); 1070 } 1071 1072 private static native void _setFloat(long addr, float value); 1073 1074 /** 1075 * Set <code>value</code> at location being pointed to. This is equivalent 1076 * to the expression 1077 * <code>*((jdouble *)((char *)Pointer + offset)) = value</code>. 1078 * 1079 * @param offset byte offset from pointer at which <code>value</code> 1080 * must be set 1081 * @param value <code>double</code> value to set 1082 */ 1083 public void setDouble(long offset, double value) { 1084 _setDouble(peer + offset, value); 1085 } 1086 1087 private static native void _setDouble(long addr, double value); 1088 1089 /** 1090 * Set <code>value</code> at location being pointed to. This is equivalent 1091 * to the expression 1092 * <code>*((void **)((char *)Pointer + offset)) = value</code>. 1093 * 1094 * @param offset byte offset from pointer at which <code>value</code> 1095 * must be set 1096 * @param value <code>Pointer</code> holding the actual pointer value to 1097 * set, which may be <code>null</code> to indicate a <code>NULL</code> 1098 * pointer. 1099 */ 1100 public void setPointer(long offset, Pointer value) { 1101 _setPointer(peer + offset, value != null ? value.peer : 0); 1102 } 1103 1104 private static native void _setPointer(long addr, long value); 1105 1106 /** 1107 * Copy string <code>value</code> to the location being pointed to. Copy 1108 * each element in <code>value</code>, converted to native encoding, at an 1109 * <code>offset</code>from the location pointed to by this pointer. 1110 * 1111 * @param offset byte offset from pointer at which characters in 1112 * <code>value</code> must be set 1113 * @param value <code>java.lang.String</code> value to set 1114 * @param wide whether to write the native string as an array of 1115 * <code>wchar_t</code>. If false, writes as a NUL-terminated array of 1116 * <code>char</code> using the default platform encoding. 1117 */ 1118 public void setString(long offset, String value, boolean wide) { 1119 _setString(peer + offset, value, wide); 1120 } 1121 1122 private static native void _setString(long addr, String value, boolean wide); 1123 1124 /** 1125 * Copy string <code>value</code> to the location being pointed to. Copy 1126 * each element in <code>value</code>, converted to native encoding, at an 1127 * <code>offset</code>from the location pointed to by this pointer. 1128 * Uses the value of the system property <code>jna.encoding</code>, if set, 1129 * to determine the appropriate native charset in which to encode the value. 1130 * If the property is not set, uses the default platform encoding. 1131 * 1132 * @param offset byte offset from pointer at which characters in 1133 * <code>value</code> must be set 1134 * @param value <code>java.lang.String</code> value to set 1135 */ 1136 public void setString(long offset, String value) { 1137 byte[] data = Native.getBytes(value); 1138 write(offset, data, 0, data.length); 1139 setByte(offset + data.length, (byte)0); 1140 } 1141 1142 public String toString() { 1143 return "native@0x" + Long.toHexString(peer); 1144 } 1145 1146 /** Pointer which disallows all read/write access. */ 1147 private static class Opaque extends Pointer { 1148 private Opaque(long peer) { super(peer); } 1149 private final String MSG = "This pointer is opaque: " + this; 1150 public long indexOf(long offset, byte value) { 1151 throw new UnsupportedOperationException(MSG); 1152 } 1153 public void read(long bOff, byte[] buf, int index, int length) { 1154 throw new UnsupportedOperationException(MSG); 1155 } 1156 public void read(long bOff, char[] buf, int index, int length) { 1157 throw new UnsupportedOperationException(MSG); 1158 } 1159 public void read(long bOff, short[] buf, int index, int length) { 1160 throw new UnsupportedOperationException(MSG); 1161 } 1162 public void read(long bOff, int[] buf, int index, int length) { 1163 throw new UnsupportedOperationException(MSG); 1164 } 1165 public void read(long bOff, long[] buf, int index, int length) { 1166 throw new UnsupportedOperationException(MSG); 1167 } 1168 public void read(long bOff, float[] buf, int index, int length) { 1169 throw new UnsupportedOperationException(MSG); 1170 } 1171 public void read(long bOff, double[] buf, int index, int length) { 1172 throw new UnsupportedOperationException(MSG); 1173 } 1174 public void write(long bOff, byte[] buf, int index, int length) { 1175 throw new UnsupportedOperationException(MSG); 1176 } 1177 public void write(long bOff, char[] buf, int index, int length) { 1178 throw new UnsupportedOperationException(MSG); 1179 } 1180 public void write(long bOff, short[] buf, int index, int length) { 1181 throw new UnsupportedOperationException(MSG); 1182 } 1183 public void write(long bOff, int[] buf, int index, int length) { 1184 throw new UnsupportedOperationException(MSG); 1185 } 1186 public void write(long bOff, long[] buf, int index, int length) { 1187 throw new UnsupportedOperationException(MSG); 1188 } 1189 public void write(long bOff, float[] buf, int index, int length) { 1190 throw new UnsupportedOperationException(MSG); 1191 } 1192 public void write(long bOff, double[] buf, int index, int length) { 1193 throw new UnsupportedOperationException(MSG); 1194 } 1195 public byte getByte(long bOff) { 1196 throw new UnsupportedOperationException(MSG); 1197 } 1198 public char getChar(long bOff) { 1199 throw new UnsupportedOperationException(MSG); 1200 } 1201 public short getShort(long bOff) { 1202 throw new UnsupportedOperationException(MSG); 1203 } 1204 public int getInt(long bOff) { 1205 throw new UnsupportedOperationException(MSG); 1206 } 1207 public long getLong(long bOff) { 1208 throw new UnsupportedOperationException(MSG); 1209 } 1210 public float getFloat(long bOff) { 1211 throw new UnsupportedOperationException(MSG); 1212 } 1213 public double getDouble(long bOff) { 1214 throw new UnsupportedOperationException(MSG); 1215 } 1216 public Pointer getPointer(long bOff) { 1217 throw new UnsupportedOperationException(MSG); 1218 } 1219 public String getString(long bOff, boolean wide) { 1220 throw new UnsupportedOperationException(MSG); 1221 } 1222 public void setByte(long bOff, byte value) { 1223 throw new UnsupportedOperationException(MSG); 1224 } 1225 public void setChar(long bOff, char value) { 1226 throw new UnsupportedOperationException(MSG); 1227 } 1228 public void setShort(long bOff, short value) { 1229 throw new UnsupportedOperationException(MSG); 1230 } 1231 public void setInt(long bOff, int value) { 1232 throw new UnsupportedOperationException(MSG); 1233 } 1234 public void setLong(long bOff, long value) { 1235 throw new UnsupportedOperationException(MSG); 1236 } 1237 public void setFloat(long bOff, float value) { 1238 throw new UnsupportedOperationException(MSG); 1239 } 1240 public void setDouble(long bOff, double value) { 1241 throw new UnsupportedOperationException(MSG); 1242 } 1243 public void setPointer(long offset, Pointer value) { 1244 throw new UnsupportedOperationException(MSG); 1245 } 1246 public void setString(long offset, String value, boolean wide) { 1247 throw new UnsupportedOperationException(MSG); 1248 } 1249 public String toString() { 1250 return "opaque@0x" + Long.toHexString(peer); 1251 } 1252 } 1253 }