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