1 /*
   2  * Copyright (c) 2014, 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 package jdk.internal.clang;
  25 
  26 import java.nio.ByteBuffer;
  27 import java.util.ArrayList;
  28 import java.util.List;
  29 import java.util.stream.Stream;
  30 
  31 public class Cursor extends StructType {
  32     public static enum VisitResult {
  33         Break,
  34         Continue,
  35         Recurse;
  36     }
  37 
  38     @FunctionalInterface
  39     public static interface Visitor {
  40         /**
  41          * Callback function for visitChildren
  42          * @param parent
  43          * @param current
  44          * @param data
  45          * @return 0 - break, 1 - continue, 2 - recurse
  46          */
  47         VisitResult visit(Cursor current, Cursor parent, Object data);
  48     }
  49 
  50     private static int visit(Visitor v, ByteBuffer c, ByteBuffer p, Object data) {
  51         return v.visit(new Cursor(c), new Cursor(p), data).ordinal();
  52     }
  53 
  54     Cursor(ByteBuffer buf) {
  55         super(buf);
  56     }
  57 
  58     public native boolean isDeclaration();
  59     public native boolean isPreprocessing();
  60     public native boolean isInvalid();
  61     public native boolean isDefinition();
  62 
  63     // Determine whether the given cursor represents an anonymous record declaration.
  64     // "Anonymous" here is not just about name (spelling) being empty. This is an
  65     // anonymous struct or union embedded in another struct or union.
  66     public native boolean isAnonymousStruct();
  67     public native boolean isMacroFunctionLike();
  68 
  69     public native String spelling();
  70     public native String USR();
  71 
  72     public native int kind1();
  73 
  74     public native int visitChildren(Visitor visitor, Object data);
  75 
  76     public native Type type();
  77     public native Type getEnumDeclIntegerType();
  78 
  79     public native Cursor getDefinition();
  80 
  81     public native SourceLocation getSourceLocation();
  82     public native SourceRange getExtent();
  83 
  84     public native int numberOfArgs();
  85     public native Cursor getArgument(int idx);
  86 
  87     // C long long, 64-bit
  88     public native long getEnumConstantValue();
  89     // C unsigned long long, 64-bit
  90     public native long getEnumConstantUnsignedValue();
  91 
  92     public native boolean isBitField();
  93     public native int getBitFieldWidth();
  94 
  95     native long getTranslationUnit0();
  96     public final TranslationUnit getTranslationUnit() {
  97         return new TranslationUnit(getTranslationUnit0());
  98     }
  99 
 100     public native String getMangling();
 101 
 102     public CursorKind kind() {
 103         int v = kind1();
 104         // FIXME: assert(v == getData().getInt(0));
 105         return CursorKind.valueOf(v);
 106     }
 107 
 108     public Stream<Cursor> children() {
 109         ArrayList<Cursor> ar = new ArrayList<>();
 110         visitChildren((c, p, d) -> {
 111             @SuppressWarnings("unchecked")
 112             List<Cursor> a = (List<Cursor>) d;
 113             a.add(c);
 114             return VisitResult.Continue;
 115         }, ar);
 116         return ar.stream();
 117     }
 118 
 119     public Stream<Cursor> allChildren() {
 120         return children().flatMap(c -> Stream.concat(Stream.of(c), c.children()));
 121     }
 122 
 123     public native boolean equalCursor(Cursor other);
 124 
 125     @Override
 126     public boolean equals(Object other) {
 127         if (this == other) {
 128             return true;
 129         }
 130         if (!(other instanceof Cursor)) {
 131             return false;
 132         }
 133         return equalCursor((Cursor)other);
 134     }
 135 
 136     @Override
 137     public int hashCode() {
 138         return spelling().hashCode();
 139     }
 140 }