1 /* This library is free software; you can redistribute it and/or
2 * modify it under the terms of the GNU Lesser General Public
3 * License as published by the Free Software Foundation; either
4 * version 2.1 of the License, or (at your option) any later version.
5 * <p/>
6 * This library is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9 * Lesser General Public License for more details.
10 */
11 package com.sun.jna;
12
13 import com.sun.jna.ptr.ByReference;
14 import java.io.UnsupportedEncodingException;
15 import java.lang.reflect.Array;
16 import java.nio.Buffer;
17 import java.nio.ByteBuffer;
18 import java.nio.ByteOrder;
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23
24 /**
25 * An abstraction for a native pointer data type. A Pointer instance
26 * represents, on the Java side, a native pointer. The native pointer could
27 * be any <em>type</em> of native pointer. Methods such as <code>write</code>,
28 * <code>read</code>, <code>getXXX</code>, and <code>setXXX</code>, provide
29 * means to access memory underlying the native pointer.<p>
30 * The constructors are intentionally package-private, since it's not generally
31 * a good idea to be creating C pointers de novo.
32 *
33 * @author Sheng Liang, originator
34 * @author Todd Fast, suitability modifications
35 * @author Timothy Wall, robust library loading
36 * @see Function
37 */
38 public class Pointer {
39
40 /** Size of a native pointer, in bytes. */
41 public static final int SIZE;
42
43 static {
44 // Force load of native library
45 if ((SIZE = Native.POINTER_SIZE) == 0) {
46 throw new Error("Native library not initialized");
47 }
48 }
49
50 /** Convenience constant, same as <code>null</code>. */
51 public static final Pointer NULL = null;
52
53 /** Convenience constant, equivalent to <code>(void*)-1</code>. */
54 public static final Pointer createConstant(long peer) {
55 return new Opaque(peer);
56 }
57
58 /** Pointer value of the real native pointer. Use long to be 64-bit safe.
59 */
60 protected long peer;
61
62 /** Derived class must assign peer pointer value. */
63 Pointer() { }
64
65 /** Create from native pointer. */
66 Pointer(long peer) {
67 this.peer = peer;
68 }
69
70 public Pointer share(long offset) {
71 return share(offset, 0);
72 }
73
74 /** Provide a view of this pointer with a different peer base. */
75 public Pointer share(long offset, long sz) {
76 if (offset == 0) return this;
77 return new Pointer(peer + offset);
78 }
79
80 /** Zero memory for the given number of bytes. */
81 public void clear(long size) {
82 setMemory(0, size, (byte)0);
83 }
84
85 /**
86 * Compares this <code>Pointer</code> to the specified object.
87 *
88 * @param o
89 * A <code>Pointer</code> instance
90 * @return True if the other object is a <code>Pointer</code>,
91 * and the C pointers being pointed to by these objects are also
92 * equal. Returns false otherwise.
93 */
94 public boolean equals(Object o) {
95 if (o == this) return true;
96 if (o == null) return false;
97 return o instanceof Pointer && ((Pointer)o).peer == peer;
98 }
99
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 }