From 405512e1c8a2e24834b0d057f0b020b4a0f4c25b Mon Sep 17 00:00:00 2001
From: Sven Gothel
Date: Wed, 11 Mar 2015 08:48:36 +0100
Subject: Bug 1144 - Add 'DelegateImplementation', manually impl. may delegate
to renamed original
'DelegateImplementation' is a variation of 'ManuallyImplement'.
'ManuallyImplement' emits the interface method, but suppresses
the Java and native-code implementation.
The latter shall be implemented manually by the user.
'DelegateImplementation' emits the interface method,
and the _private_ renamed Java and native-code implementation.
Both can be called from the manual user implementation,
hence delegation.
Configuration:
DelegateImplementation
I.e. delegation model shall apply to
and the Java and native-code implementation renamed to .
The user manual implementation of
may delegate to .
---
src/java/com/jogamp/gluegen/JavaConfiguration.java | 72 ++++++++++++++++++++++
src/java/com/jogamp/gluegen/JavaEmitter.java | 23 ++++---
src/java/com/jogamp/gluegen/MethodBinding.java | 20 +++++-
3 files changed, 106 insertions(+), 9 deletions(-)
(limited to 'src/java/com')
diff --git a/src/java/com/jogamp/gluegen/JavaConfiguration.java b/src/java/com/jogamp/gluegen/JavaConfiguration.java
index 969eaaf..987d27a 100644
--- a/src/java/com/jogamp/gluegen/JavaConfiguration.java
+++ b/src/java/com/jogamp/gluegen/JavaConfiguration.java
@@ -159,6 +159,7 @@ public class JavaConfiguration {
private boolean forceUseNIODirectOnly4All = false;
private final Set useNIODirectOnly = new HashSet();
private final Set manuallyImplement = new HashSet();
+ private final Map delegatedImplementation = new HashMap();
private final Set manualStaticInitCall = new HashSet();
private final Set forceStaticInitCode = new HashSet();
private final Map> customJavaCode = new HashMap>();
@@ -875,6 +876,54 @@ public class JavaConfiguration {
}
}
+ /**
+ * Variant of {@link #getDelegatedImplementation(AliasedSymbol)},
+ * where this method only considers the {@link AliasedSymbol#getName() current-name}
+ * of the given symbol, not the {@link #getJavaSymbolRename(String) renamed-symbol}.
+ */
+ public String getDelegatedImplementation(final String functionName) {
+ final String res = delegatedImplementation.get(functionName);
+ if( null == res ) {
+ return null;
+ }
+ LOG.log(INFO, "DelegatedImplementation: {0}", functionName);
+ return res;
+ }
+
+ /**
+ * Returns the {@code RENAMED-IMPL-SYMBOL} if the implementation of the glue code
+ * of the given function shall be manually delegated by the end user.
+ *
+ * {@code DelegateImplementation }
+ *
+ *
+ * The interface is emitted unchanged.
+ *
+ *
+ * The Java and native-code implementation is renamed to {@code RENAMED-IMPL-SYMBOL}.
+ * The user's manual implementation of {@code ORIG-SYMBOL}
+ * may delegate to {@code RENAMED-IMPL-SYMBOL}.
+ *
+ *
+ * If symbol references a struct field or method, see {@link #canonicalStructFieldSymbol(String, String)},
+ * it describes field's array-length or element-count referenced by a pointer.
+ *
+ */
+ public String getDelegatedImplementation(final AliasedSymbol symbol) {
+ final String name = symbol.getName();
+ final Set aliases = symbol.getAliasedNames();
+
+ String res = delegatedImplementation.get(name);
+ if( null == res ) {
+ res = oneInMap(delegatedImplementation, aliases);
+ if( null == res ) {
+ return null;
+ }
+ }
+ LOG.log(INFO, getASTLocusTag(symbol), "DelegatedImplementation: {0}", symbol.getAliasedString());
+ return res;
+ }
+
/**
* Variant of {@link #shouldIgnoreInInterface(AliasedSymbol)},
* where this method only considers the {@link AliasedSymbol#getName() current-name}
@@ -1078,6 +1127,16 @@ public class JavaConfiguration {
origNames.add(origName);
}
+ /** Programmatically adds a delegate implementation directive for the given symbol. */
+ public void addDelegateImplementation(final String origName, final String renamedImpl) {
+ LOG.log(INFO, "\tDelegateImplementation {0} -> {1}", origName, renamedImpl);
+ final String prevValue = delegatedImplementation.put(origName, renamedImpl);
+ if(null != prevValue && !prevValue.equals(renamedImpl)) {
+ throw new RuntimeException("Rename-Override Attampt: "+origName+" -> "+renamedImpl+
+ ", but "+origName+" -> "+prevValue+" already exist. Run in 'debug' mode to analyze!");
+ }
+ }
+
/** Returns true if the emission style is AllStatic. */
public boolean allStatic() {
return emissionStyle == AllStatic;
@@ -1265,6 +1324,8 @@ public class JavaConfiguration {
readRenameJavaType(tok, filename, lineNo);
} else if (cmd.equalsIgnoreCase("RenameJavaSymbol")) {
readRenameJavaSymbol(tok, filename, lineNo);
+ } else if (cmd.equalsIgnoreCase("DelegateImplementation")) {
+ readDelegateImplementation(tok, filename, lineNo);
} else if (cmd.equalsIgnoreCase("RuntimeExceptionType")) {
runtimeExceptionType = readString("RuntimeExceptionType", tok, filename, lineNo);
} else if (cmd.equalsIgnoreCase("UnsupportedExceptionType")) {
@@ -1798,6 +1859,17 @@ public class JavaConfiguration {
}
}
+ public void readDelegateImplementation(final StringTokenizer tok, final String filename, final int lineNo) {
+ try {
+ final String fromName = tok.nextToken();
+ final String toName = tok.nextToken();
+ addDelegateImplementation(fromName, toName);
+ } catch (final NoSuchElementException e) {
+ throw new RuntimeException("Error parsing \"DelegateImplementation\" command at line " + lineNo +
+ " in file \"" + filename + "\": missing expected parameter", e);
+ }
+ }
+
protected void readJavaPrologueOrEpilogue(final StringTokenizer tok, final String filename, final int lineNo, final boolean prologue) {
try {
String methodName = tok.nextToken();
diff --git a/src/java/com/jogamp/gluegen/JavaEmitter.java b/src/java/com/jogamp/gluegen/JavaEmitter.java
index fa4ecab..2601929 100644
--- a/src/java/com/jogamp/gluegen/JavaEmitter.java
+++ b/src/java/com/jogamp/gluegen/JavaEmitter.java
@@ -568,12 +568,6 @@ public class JavaEmitter implements GlueEmitter {
return;
}
- final MethodAccess accessControl = cfg.accessControl(binding.getName());
- // We should not emit anything except public APIs into interfaces
- if (signatureOnly && (accessControl != PUBLIC)) {
- return;
- }
-
// It's possible we may not need a body even if signatureOnly is
// set to false; for example, if the routine doesn't take any
// arrays or buffers as arguments
@@ -596,6 +590,20 @@ public class JavaEmitter implements GlueEmitter {
final boolean emitBody = !signatureOnly && needsBody;
final boolean isNativeMethod = !isUnimplemented && !needsBody && !signatureOnly;
+ final MethodAccess accessControl;
+
+ if ( !signatureOnly && null != binding.getDelegationImplName() ) {
+ // private access for delegation implementation methods
+ accessControl = PRIVATE;
+ } else {
+ accessControl = cfg.accessControl(binding.getName());
+ }
+
+ // We should not emit anything except public APIs into interfaces
+ if ( signatureOnly && PUBLIC != accessControl ) {
+ return;
+ }
+
final PrintWriter writer = ((signatureOnly || cfg.allStatic()) ? javaWriter() : javaImplWriter());
final JavaMethodBindingEmitter emitter =
@@ -2801,8 +2809,9 @@ public class JavaEmitter implements GlueEmitter {
javaArgumentTypes.add(mappedType);
//System.out.println("During binding of [" + sym + "], added mapping from C type: " + cArgType + " to Java type: " + mappedType);
}
+ final String delegationImplName = null == containingType && null == containingCType ?
+ cfg.getDelegatedImplementation(sym) : null;
final MethodBinding mb = new MethodBinding(sym, delegationImplName,
- final MethodBinding mb = new MethodBinding(sym,
javaReturnType, javaArgumentTypes,
containingType, containingCType);
mangleBinding(mb);
diff --git a/src/java/com/jogamp/gluegen/MethodBinding.java b/src/java/com/jogamp/gluegen/MethodBinding.java
index 5b0290a..278fea0 100644
--- a/src/java/com/jogamp/gluegen/MethodBinding.java
+++ b/src/java/com/jogamp/gluegen/MethodBinding.java
@@ -52,6 +52,7 @@ import java.util.List;
public class MethodBinding {
private final FunctionSymbol sym;
+ private final String delegationImplName;
private final JavaType containingType;
private final Type containingCType;
private String nativeName;
@@ -77,6 +78,7 @@ public class MethodBinding {
*/
public MethodBinding(final MethodBinding bindingToCopy) {
this.sym = bindingToCopy.sym;
+ this.delegationImplName = bindingToCopy.delegationImplName;
this.containingType = bindingToCopy.containingType;
this.containingCType = bindingToCopy.containingCType;
@@ -105,11 +107,13 @@ public class MethodBinding {
*
*/
public MethodBinding(final FunctionSymbol sym,
+ final String delegationImplName,
final JavaType javaReturnType,
final List javaArgumentTypes,
final JavaType containingType,
final Type containingCType) {
this.sym = sym;
+ this.delegationImplName = delegationImplName;
this.containingType = containingType;
this.containingCType = containingCType;
@@ -173,16 +177,28 @@ public class MethodBinding {
public String getName() {
return sym.getName();
}
+ /**
+ * The
+ * {@link JavaConfiguration#getDelegatedImplementation(com.jogamp.gluegen.cgram.types.AliasedSymbol) implementation delegation}
+ * name, or {@code null} for no delegation.
+ * @see #getImplName()
+ */
+ public String getDelegationImplName() {
+ return delegationImplName;
+ }
+
/** Returns the {@link FunctionSymbol}'s current {@link FunctionSymbol#getName() aliased} API name for the interface. */
public String getInterfaceName() {
return sym.getName();
}
/**
* Returns the {@link FunctionSymbol}'s name for the implementation,
- * which is the current {@link FunctionSymbol#getName() aliased} API name per default.
+ * which is the current {@link FunctionSymbol#getName() aliased} API name per default,
+ * or the {@link #getDelegationImplName() delegation} name.
+ * @see #getDelegationImplName()
*/
public String getImplName() {
- return sym.getName();
+ return null != delegationImplName ? delegationImplName : sym.getName();
}
/**
* Returns the {@link FunctionSymbol}'s name for the native function
--
cgit v1.2.3