1 /*
  2  *  Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
  3  *  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  *  This code is free software; you can redistribute it and/or modify it
  6  *  under the terms of the GNU General Public License version 2 only, as
  7  *  published by the Free Software Foundation.
  8  *
  9  *  This code is distributed in the hope that it will be useful, but WITHOUT
 10  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  *  version 2 for more details (a copy is included in the LICENSE file that
 13  *  accompanied this code).
 14  *
 15  *  You should have received a copy of the GNU General Public License version
 16  *  2 along with this work; if not, write to the Free Software Foundation,
 17  *  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  *  Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  *  or visit www.oracle.com if you need additional information or have any
 21  *  questions.
 22  */
 23 
 24 /*
 25  * @test
 26  * @run testng TestMemoryAccessStatics
 27  */
 28 
 29 import jdk.incubator.foreign.MemoryAccess;
 30 import jdk.incubator.foreign.MemoryAddress;
 31 import jdk.incubator.foreign.MemoryLayouts;
 32 import jdk.incubator.foreign.MemorySegment;
 33 
 34 import java.lang.reflect.InvocationTargetException;
 35 import java.lang.reflect.Method;
 36 import java.lang.reflect.Modifier;
 37 import java.nio.ByteBuffer;
 38 import java.nio.ByteOrder;
 39 
 40 import org.testng.annotations.*;
 41 import static org.testng.Assert.*;
 42 
 43 public class TestMemoryAccessStatics {
 44 
 45     static class Accessor<X> {
 46 
 47         interface SegmentGetter<X> {
 48             X get(MemorySegment segment);
 49         }
 50 
 51         interface SegmentSetter<X> {
 52             void set(MemorySegment segment, X o);
 53         }
 54 
 55         interface BufferGetter<X> {
 56             X get(ByteBuffer segment);
 57         }
 58 
 59         interface BufferSetter<X> {
 60             void set(ByteBuffer buffer, X o);
 61         }
 62 
 63         final X value;
 64         final SegmentGetter<X> segmentGetter;
 65         final SegmentSetter<X> segmentSetter;
 66         final BufferGetter<X> bufferGetter;
 67         final BufferSetter<X> bufferSetter;
 68 
 69         Accessor(X value,
 70                  SegmentGetter<X> segmentGetter, SegmentSetter<X> segmentSetter,
 71                  BufferGetter<X> bufferGetter, BufferSetter<X> bufferSetter) {
 72             this.value = value;
 73             this.segmentGetter = segmentGetter;
 74             this.segmentSetter = segmentSetter;
 75             this.bufferGetter = bufferGetter;
 76             this.bufferSetter = bufferSetter;
 77         }
 78 
 79         void test() {
 80             MemorySegment segment = MemorySegment.ofArray(new byte[32]);
 81             ByteBuffer buffer = segment.asByteBuffer();
 82             segmentSetter.set(segment, value);
 83             assertEquals(bufferGetter.get(buffer), value);
 84             bufferSetter.set(buffer, value);
 85             assertEquals(value, segmentGetter.get(segment));
 86         }
 87 
 88         <Z> Accessor<Z> of(Z value,
 89                            SegmentGetter<Z> segmentGetter, SegmentSetter<Z> segmentSetter,
 90                            BufferGetter<Z> bufferGetter, BufferSetter<Z> bufferSetter) {
 91             return new Accessor<>(value, segmentGetter, segmentSetter, bufferGetter, bufferSetter);
 92         }
 93     }
 94 
 95     @Test(dataProvider = "accessors")
 96     public void testMemoryAccess(String testName, Accessor<?> accessor) {
 97         accessor.test();
 98     }
 99 
100     static final ByteOrder BE = ByteOrder.BIG_ENDIAN;
101     static final ByteOrder LE = ByteOrder.LITTLE_ENDIAN;
102     static final ByteOrder NE = ByteOrder.nativeOrder();
103 
104     @DataProvider(name = "accessors")
105     static Object[][] accessors() {
106         return new Object[][]{
107 
108                 {"byte", new Accessor<>((byte) 42,
109                         MemoryAccess::getByte, MemoryAccess::setByte,
110                         (bb) -> bb.get(0), (bb, v) -> bb.put(0, v))
111                 },
112                 {"char", new Accessor<>((char) 42,
113                         MemoryAccess::getChar, MemoryAccess::setChar,
114                         (bb) -> bb.order(NE).getChar(0), (bb, v) -> bb.order(NE).putChar(0, v))
115                 },
116                 {"char/LE", new Accessor<>((char) 42,
117                         s -> MemoryAccess.getChar(s, LE), (s, x) -> MemoryAccess.setChar(s, LE, x),
118                         (bb) -> bb.order(LE).getChar(0), (bb, v) -> bb.order(LE).putChar(0, v))
119                 },
120                 {"char/BE", new Accessor<>((char) 42,
121                         s -> MemoryAccess.getChar(s, BE), (s, x) -> MemoryAccess.setChar(s, BE, x),
122                         (bb) -> bb.order(BE).getChar(0), (bb, v) -> bb.order(BE).putChar(0, v))
123                 },
124                 {"short", new Accessor<>((short) 42,
125                         MemoryAccess::getShort, MemoryAccess::setShort,
126                         (bb) -> bb.order(NE).getShort(0), (bb, v) -> bb.order(NE).putShort(0, v))
127                 },
128                 {"short/LE", new Accessor<>((short) 42,
129                         s -> MemoryAccess.getShort(s, LE), (s, x) -> MemoryAccess.setShort(s, LE, x),
130                         (bb) -> bb.order(LE).getShort(0), (bb, v) -> bb.order(LE).putShort(0, v))
131                 },
132                 {"short/BE", new Accessor<>((short) 42,
133                         s -> MemoryAccess.getShort(s, BE), (s, x) -> MemoryAccess.setShort(s, BE, x),
134                         (bb) -> bb.order(BE).getShort(0), (bb, v) -> bb.order(BE).putShort(0, v))
135                 },
136                 {"int", new Accessor<>(42,
137                         MemoryAccess::getInt, MemoryAccess::setInt,
138                         (bb) -> bb.order(NE).getInt(0), (bb, v) -> bb.order(NE).putInt(0, v))
139                 },
140                 {"int/LE", new Accessor<>(42,
141                         s -> MemoryAccess.getInt(s, LE), (s, x) -> MemoryAccess.setInt(s, LE, x),
142                         (bb) -> bb.order(LE).getInt(0), (bb, v) -> bb.order(LE).putInt(0, v))
143                 },
144                 {"int/BE", new Accessor<>(42,
145                         s -> MemoryAccess.getInt(s, BE), (s, x) -> MemoryAccess.setInt(s, BE, x),
146                         (bb) -> bb.order(BE).getInt(0), (bb, v) -> bb.order(BE).putInt(0, v))
147                 },
148                 // float, no offset
149                 {"float", new Accessor<>(42f,
150                         MemoryAccess::getFloat, MemoryAccess::setFloat,
151                         (bb) -> bb.order(NE).getFloat(0), (bb, v) -> bb.order(NE).putFloat(0, v))
152                 },
153                 {"float/LE", new Accessor<>(42f,
154                         s -> MemoryAccess.getFloat(s, LE), (s, x) -> MemoryAccess.setFloat(s, LE, x),
155                         (bb) -> bb.order(LE).getFloat(0), (bb, v) -> bb.order(LE).putFloat(0, v))
156                 },
157                 {"float/BE", new Accessor<>(42f,
158                         s -> MemoryAccess.getFloat(s, BE), (s, x) -> MemoryAccess.setFloat(s, BE, x),
159                         (bb) -> bb.order(BE).getFloat(0), (bb, v) -> bb.order(BE).putFloat(0, v))
160                 },
161                 // double, no offset
162                 {"double", new Accessor<>(42d,
163                         MemoryAccess::getDouble, MemoryAccess::setDouble,
164                         (bb) -> bb.order(NE).getDouble(0), (bb, v) -> bb.order(NE).putDouble(0, v))
165                 },
166                 {"double/LE", new Accessor<>(42d,
167                         s -> MemoryAccess.getDouble(s, LE), (s, x) -> MemoryAccess.setDouble(s, LE, x),
168                         (bb) -> bb.order(LE).getDouble(0), (bb, v) -> bb.order(LE).putDouble(0, v))
169                 },
170                 {"double/BE", new Accessor<>(42d,
171                         s -> MemoryAccess.getDouble(s, BE), (s, x) -> MemoryAccess.setDouble(s, BE, x),
172                         (bb) -> bb.order(BE).getDouble(0), (bb, v) -> bb.order(BE).putDouble(0, v))
173                 },
174 
175 
176                 // byte, offset
177                 {"byte/offset", new Accessor<>((byte) 42,
178                         s -> MemoryAccess.getByteAtOffset(s, 4), (s, x) -> MemoryAccess.setByteAtOffset(s, 4, x),
179                         (bb) -> bb.get(4), (bb, v) -> bb.put(4, v))
180                 },
181                 // char, offset
182                 {"char/offset", new Accessor<>((char) 42,
183                         s -> MemoryAccess.getCharAtOffset(s, 4), (s, x) -> MemoryAccess.setCharAtOffset(s, 4, x),
184                         (bb) -> bb.order(NE).getChar(4), (bb, v) -> bb.order(NE).putChar(4, v))
185                 },
186                 {"char/offset/LE", new Accessor<>((char) 42,
187                         s -> MemoryAccess.getCharAtOffset(s, 4, LE), (s, x) -> MemoryAccess.setCharAtOffset(s, 4, LE, x),
188                         (bb) -> bb.order(LE).getChar(4), (bb, v) -> bb.order(LE).putChar(4, v))
189                 },
190                 {"char/offset/BE", new Accessor<>((char) 42,
191                         s -> MemoryAccess.getCharAtOffset(s, 4, BE), (s, x) -> MemoryAccess.setCharAtOffset(s, 4, BE, x),
192                         (bb) -> bb.order(BE).getChar(4), (bb, v) -> bb.order(BE).putChar(4, v))
193                 },
194                 // short, offset
195                 {"short/offset", new Accessor<>((short) 42,
196                         s -> MemoryAccess.getShortAtOffset(s, 4), (s, x) -> MemoryAccess.setShortAtOffset(s, 4, x),
197                         (bb) -> bb.order(NE).getShort(4), (bb, v) -> bb.order(NE).putShort(4, v))
198                 },
199                 {"short/offset/LE", new Accessor<>((short) 42,
200                         s -> MemoryAccess.getShortAtOffset(s, 4, LE), (s, x) -> MemoryAccess.setShortAtOffset(s, 4, LE, x),
201                         (bb) -> bb.order(LE).getShort(4), (bb, v) -> bb.order(LE).putShort(4, v))
202                 },
203                 {"short/offset/BE", new Accessor<>((short) 42,
204                         s -> MemoryAccess.getShortAtOffset(s, 4, BE), (s, x) -> MemoryAccess.setShortAtOffset(s, 4, BE, x),
205                         (bb) -> bb.order(BE).getShort(4), (bb, v) -> bb.order(BE).putShort(4, v))
206                 },
207                 // int, offset
208                 {"int/offset", new Accessor<>(42,
209                         s -> MemoryAccess.getIntAtOffset(s, 4), (s, x) -> MemoryAccess.setIntAtOffset(s, 4, x),
210                         (bb) -> bb.order(NE).getInt(4), (bb, v) -> bb.order(NE).putInt(4, v))
211                 },
212                 {"int/offset/LE", new Accessor<>(42,
213                         s -> MemoryAccess.getIntAtOffset(s, 4, LE), (s, x) -> MemoryAccess.setIntAtOffset(s, 4, LE, x),
214                         (bb) -> bb.order(LE).getInt(4), (bb, v) -> bb.order(LE).putInt(4, v))
215                 },
216                 {"int/offset/BE", new Accessor<>(42,
217                         s -> MemoryAccess.getIntAtOffset(s, 4, BE), (s, x) -> MemoryAccess.setIntAtOffset(s, 4, BE, x),
218                         (bb) -> bb.order(BE).getInt(4), (bb, v) -> bb.order(BE).putInt(4, v))
219                 },
220                 // float, offset
221                 {"float/offset", new Accessor<>(42f,
222                         s -> MemoryAccess.getFloatAtOffset(s, 4), (s, x) -> MemoryAccess.setFloatAtOffset(s, 4, x),
223                         (bb) -> bb.order(NE).getFloat(4), (bb, v) -> bb.order(NE).putFloat(4, v))
224                 },
225                 {"float/offset/LE", new Accessor<>(42f,
226                         s -> MemoryAccess.getFloatAtOffset(s, 4, LE), (s, x) -> MemoryAccess.setFloatAtOffset(s, 4, LE, x),
227                         (bb) -> bb.order(LE).getFloat(4), (bb, v) -> bb.order(LE).putFloat(4, v))
228                 },
229                 {"float/offset/BE", new Accessor<>(42f,
230                         s -> MemoryAccess.getFloatAtOffset(s, 4, BE), (s, x) -> MemoryAccess.setFloatAtOffset(s, 4, BE, x),
231                         (bb) -> bb.order(BE).getFloat(4), (bb, v) -> bb.order(BE).putFloat(4, v))
232                 },
233                 // double, offset
234                 {"double/offset", new Accessor<>(42d,
235                         s -> MemoryAccess.getDoubleAtOffset(s, 4), (s, x) -> MemoryAccess.setDoubleAtOffset(s, 4, x),
236                         (bb) -> bb.order(NE).getDouble(4), (bb, v) -> bb.order(NE).putDouble(4, v))
237                 },
238                 {"double/offset/LE", new Accessor<>(42d,
239                         s -> MemoryAccess.getDoubleAtOffset(s, 4, LE), (s, x) -> MemoryAccess.setDoubleAtOffset(s, 4, LE, x),
240                         (bb) -> bb.order(LE).getDouble(4), (bb, v) -> bb.order(LE).putDouble(4, v))
241                 },
242                 {"double/offset/BE", new Accessor<>(42d,
243                         s -> MemoryAccess.getDoubleAtOffset(s, 4, BE), (s, x) -> MemoryAccess.setDoubleAtOffset(s, 4, BE, x),
244                         (bb) -> bb.order(BE).getDouble(4), (bb, v) -> bb.order(BE).putDouble(4, v))
245                 },
246 
247 
248                 // char, index
249                 {"char/index", new Accessor<>((char) 42,
250                         s -> MemoryAccess.getCharAtIndex(s, 2), (s, x) -> MemoryAccess.setCharAtIndex(s, 2, x),
251                         (bb) -> bb.order(NE).asCharBuffer().get(2), (bb, v) -> bb.order(NE).asCharBuffer().put(2, v))
252                 },
253                 {"char/index/LE", new Accessor<>((char) 42,
254                         s -> MemoryAccess.getCharAtIndex(s, 2, LE), (s, x) -> MemoryAccess.setCharAtIndex(s, 2, LE, x),
255                         (bb) -> bb.order(LE).asCharBuffer().get(2), (bb, v) -> bb.order(LE).asCharBuffer().put(2, v))
256                 },
257                 {"char/index/BE", new Accessor<>((char) 42,
258                         s -> MemoryAccess.getCharAtIndex(s, 2, BE), (s, x) -> MemoryAccess.setCharAtIndex(s, 2, BE, x),
259                         (bb) -> bb.order(BE).asCharBuffer().get(2), (bb, v) -> bb.order(BE).asCharBuffer().put(2, v))
260                 },
261                 // short, index
262                 {"short/index", new Accessor<>((short) 42,
263                         s -> MemoryAccess.getShortAtIndex(s, 2), (s, x) -> MemoryAccess.setShortAtIndex(s, 2, x),
264                         (bb) -> bb.order(NE).asShortBuffer().get(2), (bb, v) -> bb.order(NE).asShortBuffer().put(2, v))
265                 },
266                 {"short/index/LE", new Accessor<>((short) 42,
267                         s -> MemoryAccess.getShortAtIndex(s, 2, LE), (s, x) -> MemoryAccess.setShortAtIndex(s, 2, LE, x),
268                         (bb) -> bb.order(LE).asShortBuffer().get(2), (bb, v) -> bb.order(LE).asShortBuffer().put(2, v))
269                 },
270                 {"short/index/BE", new Accessor<>((short) 42,
271                         s -> MemoryAccess.getShortAtIndex(s, 2, BE), (s, x) -> MemoryAccess.setShortAtIndex(s, 2, BE, x),
272                         (bb) -> bb.order(BE).asShortBuffer().get(2), (bb, v) -> bb.order(BE).asShortBuffer().put(2, v))
273                 },
274                 {"int/index", new Accessor<>(42,
275                         s -> MemoryAccess.getIntAtIndex(s, 2), (s, x) -> MemoryAccess.setIntAtIndex(s, 2, x),
276                         (bb) -> bb.order(NE).asIntBuffer().get(2), (bb, v) -> bb.order(NE).asIntBuffer().put(2, v))
277                 },
278                 {"int/index/LE", new Accessor<>(42,
279                         s -> MemoryAccess.getIntAtIndex(s, 2, LE), (s, x) -> MemoryAccess.setIntAtIndex(s, 2, LE, x),
280                         (bb) -> bb.order(LE).asIntBuffer().get(2), (bb, v) -> bb.order(LE).asIntBuffer().put(2, v))
281                 },
282                 {"int/index/BE", new Accessor<>(42,
283                         s -> MemoryAccess.getIntAtIndex(s, 2, BE), (s, x) -> MemoryAccess.setIntAtIndex(s, 2, BE, x),
284                         (bb) -> bb.order(BE).asIntBuffer().get(2), (bb, v) -> bb.order(BE).asIntBuffer().put(2, v))
285                 },
286                 {"float/index", new Accessor<>(42f,
287                         s -> MemoryAccess.getFloatAtIndex(s, 2), (s, x) -> MemoryAccess.setFloatAtIndex(s, 2, x),
288                         (bb) -> bb.order(NE).asFloatBuffer().get(2), (bb, v) -> bb.order(NE).asFloatBuffer().put(2, v))
289                 },
290                 {"float/index/LE", new Accessor<>(42f,
291                         s -> MemoryAccess.getFloatAtIndex(s, 2, LE), (s, x) -> MemoryAccess.setFloatAtIndex(s, 2, LE, x),
292                         (bb) -> bb.order(LE).asFloatBuffer().get(2), (bb, v) -> bb.order(LE).asFloatBuffer().put(2, v))
293                 },
294                 {"float/index/BE", new Accessor<>(42f,
295                         s -> MemoryAccess.getFloatAtIndex(s, 2, BE), (s, x) -> MemoryAccess.setFloatAtIndex(s, 2, BE, x),
296                         (bb) -> bb.order(BE).asFloatBuffer().get(2), (bb, v) -> bb.order(BE).asFloatBuffer().put(2, v))
297                 },
298                 {"double/index", new Accessor<>(42d,
299                         s -> MemoryAccess.getDoubleAtIndex(s, 2), (s, x) -> MemoryAccess.setDoubleAtIndex(s, 2, x),
300                         (bb) -> bb.order(NE).asDoubleBuffer().get(2), (bb, v) -> bb.order(NE).asDoubleBuffer().put(2, v))
301                 },
302                 {"double/index/LE", new Accessor<>(42d,
303                         s -> MemoryAccess.getDoubleAtIndex(s, 2, LE), (s, x) -> MemoryAccess.setDoubleAtIndex(s, 2, LE, x),
304                         (bb) -> bb.order(LE).asDoubleBuffer().get(2), (bb, v) -> bb.order(LE).asDoubleBuffer().put(2, v))
305                 },
306                 {"double/index/BE", new Accessor<>(42d,
307                         s -> MemoryAccess.getDoubleAtIndex(s, 2, BE), (s, x) -> MemoryAccess.setDoubleAtIndex(s, 2, BE, x),
308                         (bb) -> bb.order(BE).asDoubleBuffer().get(2), (bb, v) -> bb.order(BE).asDoubleBuffer().put(2, v))
309                 },
310 
311                 { "address", new Accessor<>(MemoryAddress.ofLong(42),
312                         MemoryAccess::getAddress, MemoryAccess::setAddress,
313                         (bb) -> {
314                             ByteBuffer nb = bb.order(NE);
315                             long addr = MemoryLayouts.ADDRESS.byteSize() == 8 ?
316                                     nb.getLong(0) : nb.getInt(0);
317                             return MemoryAddress.ofLong(addr);
318                         },
319                         (bb, v) -> {
320                             ByteBuffer nb = bb.order(NE);
321                             if (MemoryLayouts.ADDRESS.byteSize() == 8) {
322                                 nb.putLong(0, v.toRawLongValue());
323                             } else {
324                                 nb.putInt(0, (int)v.toRawLongValue());
325                             }
326                         })
327                 },
328                 { "address/offset", new Accessor<>(MemoryAddress.ofLong(42),
329                         s -> MemoryAccess.getAddressAtOffset(s, 4), (s, x) -> MemoryAccess.setAddressAtOffset(s, 4, x),
330                         (bb) -> {
331                             ByteBuffer nb = bb.order(NE);
332                             long addr = MemoryLayouts.ADDRESS.byteSize() == 8 ?
333                                     nb.getLong(4) : nb.getInt(4);
334                             return MemoryAddress.ofLong(addr);
335                         },
336                         (bb, v) -> {
337                             ByteBuffer nb = bb.order(NE);
338                             if (MemoryLayouts.ADDRESS.byteSize() == 8) {
339                                 nb.putLong(4, v.toRawLongValue());
340                             } else {
341                                 nb.putInt(4, (int)v.toRawLongValue());
342                             }
343                         })
344                 },
345                 { "address/index", new Accessor<>(MemoryAddress.ofLong(42),
346                         s -> MemoryAccess.getAddressAtIndex(s, 2), (s, x) -> MemoryAccess.setAddressAtIndex(s, 2, x),
347                         (bb) -> {
348                             ByteBuffer nb = bb.order(NE);
349                             long addr = MemoryLayouts.ADDRESS.byteSize() == 8 ?
350                                     nb.asLongBuffer().get(2) : nb.asIntBuffer().get(2);
351                             return MemoryAddress.ofLong(addr);
352                         },
353                         (bb, v) -> {
354                             ByteBuffer nb = bb.order(NE);
355                             if (MemoryLayouts.ADDRESS.byteSize() == 8) {
356                                 nb.asLongBuffer().put(2, v.toRawLongValue());
357                             } else {
358                                 nb.asIntBuffer().put(2, (int)v.toRawLongValue());
359                             }
360                         })
361                 },
362         };
363     }
364 }