GlueGen v2.6.0-rc-20250712
GlueGen, Native Binding Generator for Java™ (public API).
PointerBuffer.java
Go to the documentation of this file.
1/**
2 * Copyright 2010-2023 JogAmp Community. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without modification, are
5 * permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice, this list of
8 * conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice, this list
11 * of conditions and the following disclaimer in the documentation and/or other materials
12 * provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY JogAmp Community ``AS IS'' AND ANY EXPRESS OR IMPLIED
15 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JogAmp Community OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 *
24 * The views and conclusions contained in the software and documentation are those of the
25 * authors and should not be interpreted as representing official policies, either expressed
26 * or implied, of JogAmp Community.
27 */
28
29/*
30 * Created on Saturday, March 27 2010 11:55
31 */
32package com.jogamp.common.nio;
33
34import java.nio.Buffer;
35import java.nio.ByteBuffer;
36import java.nio.IntBuffer;
37import java.nio.LongBuffer;
38
39import com.jogamp.common.os.Platform;
40import com.jogamp.common.util.LongObjectHashMap;
41
42/**
43 * Hardware independent container holding an array of native pointer,
44 * while its {@link #getDirectBufferAddress()} is-a pointer-pointer type value.
45 * <p>
46 * An instance maps an array of pointers of referenced Buffer objects, represented as longs.
47 * </p>
48 * <p>
49 * The native values (NIO direct ByteBuffer) might be 32bit or 64bit wide,
50 * depending of the CPU pointer width, see {@link #POINTER_SIZE}.
51 * </p>
52 * @author Sven Gothel
53 * @author Michael Bien
54 */
55public class PointerBuffer extends AbstractBuffer<PointerBuffer> {
56 protected LongObjectHashMap dataMap = null;
57
58 /** no backup array, use for direct usage only */
59 static PointerBuffer create(final ByteBuffer bb) {
60 return Platform.is32Bit() ? new PointerBuffer( bb.asIntBuffer() ) : new PointerBuffer( bb.asLongBuffer() );
61 }
62
63 /** supports backup array */
64 PointerBuffer(final IntBuffer b) {
65 super(b, POINTER_SIZE, b.capacity());
66 }
67
68 /** supports backup array */
69 PointerBuffer(final LongBuffer b) {
70 super(b, POINTER_SIZE, b.capacity());
71 }
72
73 private final void validateDataMap() {
74 if(null == dataMap) {
75 dataMap = new LongObjectHashMap();
77 }
78 }
79
80 /** Returns a non direct PointerBuffer, having a backup array */
81 public static PointerBuffer allocate(final int size) {
82 if (Platform.is32Bit()) {
83 return new PointerBuffer(IntBuffer.wrap(new int[size]));
84 } else {
85 return new PointerBuffer(LongBuffer.wrap(new long[size]));
86 }
87 }
88
89 /** Returns a direct PointerBuffer in native order, w/o backup array */
90 public static PointerBuffer allocateDirect(final int size) {
91 return create(Buffers.newDirectByteBuffer(POINTER_SIZE * size));
92 }
93
94 /** Wraps given {@link ByteBuffer} {@code src} up to it {@link ByteBuffer#capacity()}/{@link #POINTER_SIZE} pointers. */
95 public static PointerBuffer wrap(final ByteBuffer src) {
96 return create(src);
97 }
98 /**
99 * Wraps given {@link ByteBuffer} {@code src} @ {@code srcByteOffset} to contain {@code elemCount} pointers.
100 * @param src
101 * @param srcByteOffset
102 * @param elemCount
103 * @return
104 */
105 public static PointerBuffer wrap(final ByteBuffer src, final int srcByteOffset, final int elemCount) {
106 final int oldPos = src.position();
107 final int oldLimit = src.limit();
108 src.position(srcByteOffset);
109 src.limit(srcByteOffset + POINTER_SIZE*elemCount);
110 final ByteBuffer ref = src.slice().order(src.order()); // slice and duplicate may change byte order
111 src.position(oldPos);
112 src.limit(oldLimit);
113 return create(ref);
114 }
115
116 public static PointerBuffer derefPointer(final long aptr, final int elemCount) {
117 if( 0 == aptr ) {
118 throw new NullPointerException("aptr is null");
119 }
120 final ByteBuffer bb = Buffers.getDirectByteBuffer(aptr, elemCount * POINTER_SIZE);
121 if( null == bb ) {
122 throw new InternalError("Couldn't dereference aptr 0x"+Long.toHexString(aptr)+", size "+elemCount+" * "+POINTER_SIZE);
123 }
124 return create(bb);
125 }
126 public static PointerBuffer derefPointer(final ByteBuffer ptrSrc, final int ptrSrcByteOffset, final int elemCount) {
127 return derefPointer(wrap(ptrSrc, ptrSrcByteOffset, 1).get(0), elemCount);
128 }
129
130 /**
131 * @return new PointerBuffer sharing the same buffer data of this instance (identity),
132 * but having an independent position.
133 */
134 public final PointerBuffer duplicate() {
135 PointerBuffer npb;
136 if (Platform.is32Bit()) {
137 npb = new PointerBuffer((IntBuffer)buffer);
138 } else {
139 npb = new PointerBuffer((LongBuffer)buffer);
140 }
141 if(null != dataMap) {
142 npb.dataMap = (LongObjectHashMap) dataMap.clone();
143 }
144 npb.position = position;
145 return npb;
146 }
147
148 @Override
149 public final PointerBuffer put(final PointerBuffer src) {
150 if (remaining() < src.remaining()) {
151 throw new IndexOutOfBoundsException("remaining[this "+remaining()+" < src "+src.remaining()+"], this "+this+", src "+src);
152 }
153 if( null == src.dataMap && null == dataMap ) {
154 // fast path no dataMap usage on both
155 while (src.hasRemaining()) {
156 put(src.get());
157 }
158 } else {
159 while (src.hasRemaining()) {
160 final long addr = src.get();
161 put(addr);
162 if( null != src.dataMap) {
163 final Buffer bb = (Buffer) src.dataMap.get(addr);
164 if(null!=bb) {
165 validateDataMap();
166 dataMap.put(addr, bb);
167 } else if( null != dataMap ) {
168 dataMap.remove(addr);
169 }
170 } else if( null != dataMap ) {
171 dataMap.remove(addr);
172 }
173 }
174 }
175 return this;
176 }
177
178 /** Absolute get method. Get the pointer value at the given index */
179 public final long get(final int idx) {
180 if (0 > idx || idx >= limit()) {
181 throw new IndexOutOfBoundsException("idx "+idx+" not within [0.."+limit()+"), "+this);
182 }
183 if (Platform.is32Bit()) {
184 return ((IntBuffer) buffer).get(idx) & 0x00000000FFFFFFFFL;
185 } else {
186 return ((LongBuffer) buffer).get(idx);
187 }
188 }
189 /** Relative get method. Get the pointer value at the current position and increment the position by one. */
190 public final long get() {
191 final long r = get(position);
192 position++;
193 return r;
194 }
195
196 /** Absolute get method. Get element-bytes for `elemCount` elements from this buffer at `srcElemPos` into `dest` at the given element-index `destElemPos` */
197 public final PointerBuffer get(final int srcElemPos, final long[] dest, final int destElemPos, final int elemCount) {
198 if (0 > srcElemPos || srcElemPos + elemCount > limit() || 0 > elemCount ||
199 0 > destElemPos || destElemPos + elemCount > dest.length )
200 {
201 throw new IndexOutOfBoundsException("destElemPos "+destElemPos+", srcElemPos "+srcElemPos+", elemCount "+elemCount+
202 ", srcLimit "+limit()+", destLimit "+dest.length+", "+this);
203 }
204 if (Platform.is32Bit()) {
205 final IntBuffer src = (IntBuffer) buffer;
206 for(int i=0; i<elemCount; ++i) {
207 dest[destElemPos+i] = src.get(srcElemPos+i) & 0x00000000FFFFFFFFL;
208 }
209 } else {
210 final LongBuffer src = (LongBuffer) buffer;
211 final int oldSrcLim = src.limit();
212 final int oldSrcPos = src.position();
213 src.position( srcElemPos ).limit( srcElemPos + elemCount ); // remaining = elemCount
214 src.get(dest, destElemPos, elemCount);
215 src.limit(oldSrcLim).position(oldSrcPos);
216 }
217 return this;
218 }
219
220 /**
221 * Relative bulk get method. Copy the pointer values <code> [ position .. position+elemCount [</code>
222 * to the destination array <code> [ dest[destElemPos] .. dest[destElemPos+elemCount] [ </code>
223 * and increment the position by <code>elemCount</code>. */
224 public final PointerBuffer get(final long[] dest, final int destElemPos, final int elemCount) {
225 get(position, dest, destElemPos, elemCount);
226 position += elemCount;
227 return this;
228 }
229
230 /** Absolute put method. Put the pointer value at the given index */
231 public final PointerBuffer put(final int idx, final long v) {
232 if (0 > idx || idx >= limit()) {
233 throw new IndexOutOfBoundsException("idx "+idx+" not within [0.."+limit()+"), "+this);
234 }
235 if (Platform.is32Bit()) {
236 ((IntBuffer) buffer).put(idx, (int) v);
237 } else {
238 ((LongBuffer) buffer).put(idx, v);
239 }
240 return this;
241 }
242 /** Relative put method. Put the pointer value at the current position and increment the position by one. */
243 public final PointerBuffer put(final long value) {
244 put(position, value);
245 position++;
246 return this;
247 }
248
249 /** Absolute put method. Put element-bytes for `elemCount` elements from `src` at `srcElemPos` into this buffer at the given element-index `destElemPos` */
250 public final PointerBuffer put(final long[] src, final int srcElemPos, final int destElemPos, final int elemCount) {
251 if (0 > destElemPos || destElemPos + elemCount > limit() || 0 > elemCount ||
252 0 > srcElemPos || srcElemPos + elemCount > src.length )
253 {
254 throw new IndexOutOfBoundsException("srcElemPos "+srcElemPos+", destElemPos "+destElemPos+", elemCount "+elemCount+
255 ", destLimit "+limit()+", srcLimit "+src.length+", "+this);
256 }
257 if (Platform.is32Bit()) {
258 final IntBuffer dest = (IntBuffer) buffer;
259 for(int i=0; i<elemCount; ++i) {
260 dest.put(destElemPos+i, (int) src[srcElemPos+i]);
261 }
262 } else {
263 final LongBuffer dest = (LongBuffer) buffer;
264 final int oldDestLim = dest.limit();
265 final int oldDestPos = dest.position();
266 dest.position( destElemPos ).limit( destElemPos + elemCount ); // remaining = elemCount
267 dest.put(src, srcElemPos, elemCount); // remaining = elemCount
268 dest.limit(oldDestLim).position(oldDestPos);
269 }
270 return this;
271 }
272 /**
273 * Relative bulk put method. Put the pointer values <code> [ src[srcElemPos] .. src[srcElemPos+elemCount] [</code>
274 * at the current position and increment the position by <code>elemCount</code>. */
275 public final PointerBuffer put(final long[] src, final int srcElemPos, final int elemCount) {
276 put(src, srcElemPos, position, elemCount);
277 position += elemCount;
278 return this;
279 }
280
281 /** Put the address of the given direct Buffer at the given position
282 of this pointer array.
283 Adding a reference of the given direct Buffer to this object.
284
285 @throws IllegalArgumentException if bb is null or not a direct buffer
286 */
287 public final PointerBuffer referenceBuffer(final int index, final Buffer bb) {
288 if(null==bb) {
289 throw new IllegalArgumentException("Buffer is null");
290 }
291 if(!Buffers.isDirect(bb)) {
292 throw new IllegalArgumentException("Buffer is not direct");
293 }
294 final long mask = Platform.is32Bit() ? 0x00000000FFFFFFFFL : 0xFFFFFFFFFFFFFFFFL ;
295 final long bbAddr = Buffers.getDirectBufferAddressImpl(bb) & mask;
296 if(0==bbAddr) {
297 throw new RuntimeException("Couldn't determine native address of given Buffer: "+bb);
298 }
299 validateDataMap();
300 put(index, bbAddr);
301 dataMap.put(bbAddr, bb);
302 return this;
303 }
304
305 /** Put the address of the given direct Buffer at the end
306 of this pointer array.
307 Adding a reference of the given direct Buffer to this object. */
308 public final PointerBuffer referenceBuffer(final Buffer bb) {
310 position++;
311 return this;
312 }
313
314 public final Buffer getReferencedBuffer(final int index) {
315 if(null != dataMap) {
316 final long addr = get(index);
317 return (Buffer) dataMap.get(addr);
318 }
319 return null;
320 }
321
322 public final Buffer getReferencedBuffer() {
323 final Buffer bb = getReferencedBuffer(position);
324 position++;
325 return bb;
326 }
327
328 @Override
329 public String toString() {
330 return "PointerBuffer"+toSubString();
331 }
332}
static final int POINTER_SIZE
Platform dependent pointer size in bytes, i.e.
Utility methods allowing easy java.nio.Buffer manipulations.
Definition: Buffers.java:70
static ByteBuffer newDirectByteBuffer(final int numElements)
Allocates a new direct ByteBuffer with the specified number of elements.
Definition: Buffers.java:92
static boolean isDirect(final Object buf)
Helper routine to tell whether a buffer is direct or not.
Definition: Buffers.java:392
Hardware independent container holding an array of native pointer, while its getDirectBufferAddress()...
final PointerBuffer put(final long[] src, final int srcElemPos, final int elemCount)
Relative bulk put method.
final Buffer getReferencedBuffer(final int index)
static PointerBuffer allocateDirect(final int size)
Returns a direct PointerBuffer in native order, w/o backup array.
static PointerBuffer wrap(final ByteBuffer src, final int srcByteOffset, final int elemCount)
Wraps given ByteBuffer src @ srcByteOffset to contain elemCount pointers.
final PointerBuffer put(final int idx, final long v)
Absolute put method.
static PointerBuffer allocate(final int size)
Returns a non direct PointerBuffer, having a backup array.
static PointerBuffer derefPointer(final ByteBuffer ptrSrc, final int ptrSrcByteOffset, final int elemCount)
static PointerBuffer derefPointer(final long aptr, final int elemCount)
static PointerBuffer wrap(final ByteBuffer src)
Wraps given ByteBuffer src up to it ByteBuffer#capacity()/POINTER_SIZE pointers.
final PointerBuffer referenceBuffer(final int index, final Buffer bb)
Put the address of the given direct Buffer at the given position of this pointer array.
final PointerBuffer put(final PointerBuffer src)
final PointerBuffer put(final long value)
Relative put method.
final PointerBuffer referenceBuffer(final Buffer bb)
Put the address of the given direct Buffer at the end of this pointer array.
final PointerBuffer put(final long[] src, final int srcElemPos, final int destElemPos, final int elemCount)
Absolute put method.
final long get(final int idx)
Absolute get method.
Utility class for querying platform specific properties.
Definition: Platform.java:58
static boolean is32Bit()
Returns true if this JVM/ARCH is 32bit.
Definition: Platform.java:423
Fast HashMap for primitive data.
Object clone()
Disclaimer: If the value type doesn't implement clone(), only the reference is copied.
Object get(final long key)
Returns the value to which the specified key is mapped, or getKeyNotFoundValue if this map contains n...
Object put(final long key, final Object value)
Maps the key to the specified value.
Object remove(final long key)
Removes the key-value mapping from this map.
Object setKeyNotFoundValue(final Object newKeyNotFoundValue)
Sets the new key not found value.