org.bytedeco.javacpp.tools.DeclarationList Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of javacpp Show documentation
Show all versions of javacpp Show documentation
The missing bridge between Java and native C++
The newest version!
/*
* Copyright (C) 2014-2018 Samuel Audet
*
* Licensed either under the Apache License, Version 2.0, or (at your option)
* under the terms of the GNU General Public License as published by
* the Free Software Foundation (subject to the "Classpath" exception),
* either version 2, or any later version (collectively, the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* http://www.gnu.org/licenses/
* http://www.gnu.org/software/classpath/license.html
*
* or as provided in the LICENSE.txt file that accompanied this code.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.bytedeco.javacpp.tools;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import java.util.Scanner;
/**
*
* @author Samuel Audet
*/
class DeclarationList extends ArrayList {
InfoMap infoMap = null;
Context context = null;
TemplateMap templateMap = null;
ListIterator infoIterator = null;
String spacing = null;
DeclarationList inherited = null;
DeclarationList() { }
DeclarationList(DeclarationList inherited) {
this.inherited = inherited;
}
String rescan(String lines) {
if (spacing == null) {
return lines;
}
String text = "";
try (Scanner scanner = new Scanner(lines)) {
while (scanner.hasNextLine()) {
text += spacing + scanner.nextLine();
int newline = spacing.lastIndexOf('\n');
spacing = newline >= 0 ? spacing.substring(newline) : "\n";
}
}
return text;
}
@Override public boolean add(Declaration decl) {
return add(decl, null);
}
public boolean add(Declaration decl, String fullName) {
boolean add = true;
if (templateMap != null && templateMap.empty() && !decl.custom && (decl.type != null || decl.declarator != null)) {
// method templates cannot be declared in Java, but make sure to make their
// info available on request (when Info.javaNames or Info.define is set) to be able to create instances
// decl.custom is true when info has a javaText and define is false. This allows to apply a javaText
// to a template without instantiating it. define forces instantiation.
if (infoIterator == null) {
Type type = templateMap.type = decl.type;
Declarator dcl = templateMap.declarator = decl.declarator;
for (String name : new String[] {fullName, dcl != null ? (dcl.type.constructor ? Parser.constructorName(dcl.cppName) : dcl.cppName) : type.cppName}) {
if (name == null) {
continue;
}
List infoList = infoMap.get(name);
boolean hasJavaNameOrDefine = false;
for (Info info : infoList) {
hasJavaNameOrDefine |= info.javaNames != null && info.javaNames.length > 0 || info.define;
}
if (!decl.function || hasJavaNameOrDefine) {
infoIterator = infoList.size() > 0 ? new ArrayList<>(infoList).listIterator() : null;
break;
}
}
}
add = false;
} else if (infoMap != null && !decl.incomplete && decl.type != null && decl.type.cppName != null) {
// check if the user gave us different names for the same type with and without const
if (infoIterator == null) {
String constName = null, name = null;
List infoList = infoMap.get(decl.type.cppName);
List constInfoList = infoMap.get("const " + decl.type.cppName);
if (infoList != null && constInfoList != null && !infoList.equals(constInfoList)) {
for (Info info : infoList) {
if (info.pointerTypes != null && info.pointerTypes.length > 0) {
name = info.pointerTypes[0].substring(info.pointerTypes[0].lastIndexOf(" ") + 1);
break;
}
}
for (Info info : constInfoList) {
if (info.pointerTypes != null && info.pointerTypes.length > 0) {
constName = info.pointerTypes[0].substring(info.pointerTypes[0].lastIndexOf(" ") + 1);
break;
}
}
}
if (constName != null && name != null && !constName.equals(name)) {
// if so, let's reparse this twice to create two Java peer classes
infoList.addAll(constInfoList);
infoIterator = infoList.size() > 0 ? infoList.listIterator() : null;
add = false;
}
}
}
if (infoMap != null && decl.declarator != null && decl.declarator.type != null) {
// honor to skip over declarations when tagged as such
Info info = infoMap.getFirst(decl.declarator.type.cppName);
if (info != null && info.skip && info.valueTypes == null && info.pointerTypes == null) {
add = false;
} else if (decl.declarator.parameters != null) {
for (Declarator d : decl.declarator.parameters.declarators) {
if (d != null && d.type != null) {
info = infoMap.getFirst(d.type.cppName);
if (info != null && info.skip && info.valueTypes == null && info.pointerTypes == null) {
add = false;
break;
}
}
}
}
}
if (decl.type != null && decl.type.javaName.equals("Pointer")) {
add = false;
}
if (!add) {
return false;
}
// place all definitions prior to the declarations that need them
List stack = new ArrayList<>();
ListIterator it = stack.listIterator();
it.add(decl); it.previous();
while (it.hasNext()) {
decl = it.next();
Declarator dcl = decl.declarator;
if (dcl != null && dcl.definition != null) {
it.add(dcl.definition); it.previous();
}
if (dcl != null && dcl.parameters != null && dcl.parameters.declarators != null) {
for (Declarator d : dcl.parameters.declarators) {
if (d != null && d.definition != null) {
it.add(d.definition); it.previous();
}
}
}
}
add = false;
while (!stack.isEmpty()) {
decl = stack.remove(stack.size() - 1);
if (context != null) {
decl.inaccessible = context.inaccessible
&& !(context.virtualize && decl.declarator != null && decl.declarator.type != null && decl.declarator.type.virtual);
}
if (decl.text.length() == 0) {
decl.inaccessible = true;
}
it = listIterator();
boolean found = false;
while (it.hasNext()) {
Declaration d = it.next();
if (d != null && d.signature != null && d.signature.length() > 0 && d.signature.equals(decl.signature)) {
if ((d.constMember && !decl.constMember) || (d.inaccessible && !decl.inaccessible) || (d.incomplete && !decl.incomplete)) {
// add preferably non-const accessible complete versions of functions and types
it.remove();
} else {
found = true;
}
}
}
if (inherited != null) {
it = inherited.listIterator();
while (it.hasNext()) {
Declaration d = it.next();
if (d.signature.length() > 0 && d.signature.equals(decl.signature) && !d.incomplete && decl.incomplete) {
// suppress forward declaration if they are found complete in inherited declarations
found = true;
break;
}
}
}
if (!found) {
decl.text = rescan(decl.text);
super.add(decl);
add = true;
}
}
return add;
}
}