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