1 /*
   2  * Copyright (c) 2016, 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  * @modules java.base/jdk.internal.misc
  27  */
  28 
  29 import java.lang.invoke.MethodHandles;
  30 import java.nicl.*;
  31 import java.nicl.metadata.*;
  32 import java.nicl.metadata.Array;
  33 import java.nicl.types.*;
  34 
  35 public class PointerTest {
  36     private static final boolean DEBUG = Boolean.getBoolean("PointerTest.DEBUG");
  37 
  38     private static final Library lib;
  39     private static final pointers ptrs;
  40 
  41     private static final String[] VERIFICATION_STRINGS = {
  42         "String A",
  43         "String B",
  44         "String C"
  45     };
  46 
  47     static {
  48         lib = Libraries.loadLibrary(MethodHandles.lookup(), "Pointers");
  49         ptrs = Libraries.bind(pointers.class, lib);
  50     }
  51 
  52     @NativeHeader
  53     static interface pointers {
  54         @NativeLocation(file="dummy", line=47, column=11, USR="c:@F@get_strings")
  55         @NativeType(layout="(p:p:p:cp:i)V", ctype="void (const char***, int*)")
  56         void get_strings(Pointer<Pointer<Pointer<Byte>>> p, Pointer<Integer> pcount);
  57 
  58         @NativeLocation(file="dummy", line=47, column=11, USR="c:@F@get_strings2")
  59         @NativeType(layout="(p:i)p:p:c", ctype="const char **(int *)")
  60         Pointer<Pointer<Byte>> get_strings2(Pointer<Integer> pcount);
  61 
  62         @NativeLocation(file="dummy", line=47, column=11, USR="c:@F@get_structs")
  63         @NativeType(layout="(p:p:p:[3ip:c]p:i)V", ctype="void (const struct MyStruct ***, int *)" )
  64         void get_structs(Pointer<Pointer<Pointer<MyStruct>>> p, Pointer<Integer> pcount);
  65 
  66         @NativeLocation(file="dummy", line=47, column=11, USR="c:@F@get_structs2")
  67         @NativeType(layout="(p:i)p:p:[3ip:c]", ctype="const struct MyStruct **(int *)")
  68         Pointer<Pointer<MyStruct>> get_structs2(Pointer<Integer> pcount);
  69 
  70         @NativeLocation(file="dummy", line=47, column=11, USR="C:@S@MyStruct")
  71         @NativeStruct("[3ip:c]")
  72         static interface MyStruct extends Struct<MyStruct> {
  73             @Offset(offset=0l)
  74             @NativeLocation(file="dummy", line=47, column=11, USR="c:@SA@MyStruct@FI@ia")
  75             @Array(elementType="int", elementSize=4l, length=3l)
  76             @NativeType(layout="3i", ctype="int []")
  77             int[] ia$get();
  78             void ia$set(int[] i);
  79 
  80             @Offset(offset=128l)
  81             @NativeLocation(file="dummy", line=47, column=11, USR="c:@SA@MyStruct@FI@str")
  82             @NativeType(layout="p:c", ctype="const char*")
  83             Pointer<Byte> str$get();
  84             void str$set(Pointer<Byte> str);
  85         }
  86     }
  87 
  88     private static void debug(String str) {
  89         if (DEBUG) {
  90             System.err.println(str);
  91         }
  92     }
  93 
  94     private void verifyStrings(Pointer<Pointer<Byte>> values, Pointer<Integer> pi) {
  95         debug("values: " + values);
  96         debug("nvalues: " + pi.get());
  97 
  98         assertEquals(VERIFICATION_STRINGS.length, pi.get());
  99 
 100         for (int i = 0; i < pi.get(); i++) {
 101             Pointer<Byte> cstr = values.offset(i).get();
 102             String str = Pointer.toString(cstr);
 103 
 104             debug("str[" + i + "] = " + str);
 105 
 106             assertEquals(VERIFICATION_STRINGS[i], str);
 107         }
 108     }
 109 
 110 
 111     void testStrings() {
 112         try (Scope scope = Scope.newNativeScope()) {
 113             LayoutType<Integer> iType = NativeTypes.INT32;
 114             LayoutType<Pointer<Pointer<Byte>>> ppcType = NativeTypes.UINT8.pointer().pointer();
 115 
 116             Pointer<Pointer<Pointer<Byte>>> pppc = scope.allocate(ppcType);
 117             Pointer<Integer> pi = scope.allocate(iType);
 118 
 119             ptrs.get_strings(pppc, pi);
 120 
 121             Pointer<Pointer<Byte>> values = pppc.get();
 122 
 123             verifyStrings(values, pi);
 124         }
 125     }
 126 
 127     void testStrings2() {
 128         try (Scope scope = Scope.newNativeScope()) {
 129             LayoutType<Integer> iType = NativeTypes.UINT32;
 130 
 131             Pointer<Integer> pi = scope.allocate(iType);
 132 
 133             Pointer<Pointer<Byte>> values = ptrs.get_strings2(pi);
 134 
 135             verifyStrings(values, pi);
 136         }
 137     }
 138 
 139     private void verifyStructs(Pointer<Pointer<pointers.MyStruct>> structs, Pointer<Integer> pi) {
 140         debug("structs: " + structs);
 141         debug("nstructs: " + pi.get());
 142 
 143         assertEquals(VERIFICATION_STRINGS.length, pi.get());
 144 
 145         int counter = 1;
 146 
 147         for (int i = 0; i < pi.get(); i++) {
 148             pointers.MyStruct s = structs.offset(i).get().get();
 149             String str = Pointer.toString(s.str$get());
 150             debug("str[" + i + "] = " + str);
 151 
 152             assertEquals(VERIFICATION_STRINGS[i], str);
 153             int[] ia = s.ia$get();
 154 
 155             assertEquals(3, ia.length);
 156 
 157             for (int j = 0; j < ia.length; j++) {
 158                 assertEquals(counter++, ia[j]);
 159             }
 160         }
 161     }
 162 
 163     void testStructs() {
 164         try (Scope scope = Scope.newNativeScope()) {
 165             LayoutType<Integer> iType = NativeTypes.INT32;
 166             LayoutType<Pointer<Pointer<pointers.MyStruct>>> ppsType = LayoutType.ofStruct(pointers.MyStruct.class).pointer().pointer();
 167 
 168             Pointer<Pointer<Pointer<pointers.MyStruct>>> ppps = scope.allocate(ppsType);
 169             Pointer<Integer> pi = scope.allocate(iType);
 170 
 171             ptrs.get_structs(ppps, pi);
 172 
 173             Pointer<Pointer<pointers.MyStruct>> pps = ppps.get();
 174 
 175             verifyStructs(pps, pi);
 176         }
 177     }
 178 
 179     void testStructs2() {
 180         try (Scope scope = Scope.newNativeScope()) {
 181             LayoutType<Integer> iType = NativeTypes.INT32;
 182 
 183             Pointer<Integer> pi = scope.allocate(iType);
 184 
 185             Pointer<Pointer<pointers.MyStruct>> pps = ptrs.get_structs2(pi);
 186 
 187             verifyStructs(pps, pi);
 188         }
 189     }
 190 
 191     public void test() {
 192         testStrings();
 193         testStrings2();
 194         testStructs();
 195         testStructs2();
 196     }
 197 
 198     static void assertEquals(Object expected, Object actual) {
 199         if (!expected.equals(actual)) {
 200             throw new RuntimeException("expected: " + expected + " does not match actual: " + actual);
 201         }
 202     }
 203 
 204     public static void main(String[] args) {
 205         PointerTest pt = new PointerTest();
 206         pt.test();
 207     }
 208 }