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