View Javadoc

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 }