41package com.jogamp.gluegen;
43import static com.jogamp.gluegen.JavaEmitter.MethodAccess.PACKAGE_PRIVATE;
44import static com.jogamp.gluegen.JavaEmitter.MethodAccess.PRIVATE;
45import static com.jogamp.gluegen.JavaEmitter.MethodAccess.PROTECTED;
46import static com.jogamp.gluegen.JavaEmitter.MethodAccess.PUBLIC;
47import static com.jogamp.gluegen.JavaEmitter.MethodAccess.PUBLIC_ABSTRACT;
48import static java.util.logging.Level.FINE;
49import static java.util.logging.Level.INFO;
50import static java.util.logging.Level.WARNING;
51import static java.util.logging.Level.SEVERE;
54import java.io.IOException;
55import java.io.PrintWriter;
56import java.nio.Buffer;
57import java.nio.ByteBuffer;
58import java.text.MessageFormat;
59import java.util.ArrayList;
60import java.util.Arrays;
61import java.util.Collection;
62import java.util.Collections;
63import java.util.Comparator;
64import java.util.HashMap;
65import java.util.HashSet;
66import java.util.Iterator;
69import java.util.Optional;
72import jogamp.common.os.MachineDataInfoRuntime;
74import com.jogamp.common.nio.Buffers;
75import com.jogamp.common.os.DynamicLookupHelper;
76import com.jogamp.common.os.MachineDataInfo;
77import com.jogamp.common.util.ArrayHashMap;
78import com.jogamp.common.util.HashUtil;
79import com.jogamp.gluegen.ASTLocusTag.ASTLocusTagProvider;
80import com.jogamp.gluegen.JavaConfiguration.JavaCallbackDef;
81import com.jogamp.gluegen.JavaConfiguration.JavaCallbackInfo;
82import com.jogamp.gluegen.JavaType.PascalStringElem;
83import com.jogamp.gluegen.Logging.LoggerIf;
84import com.jogamp.gluegen.cgram.types.AliasedSymbol;
85import com.jogamp.gluegen.cgram.types.ArrayType;
86import com.jogamp.gluegen.cgram.types.CompoundType;
87import com.jogamp.gluegen.cgram.types.Field;
88import com.jogamp.gluegen.cgram.types.FunctionSymbol;
89import com.jogamp.gluegen.cgram.types.FunctionType;
90import com.jogamp.gluegen.cgram.types.PointerType;
91import com.jogamp.gluegen.cgram.types.SizeThunk;
92import com.jogamp.gluegen.cgram.types.StructLayout;
93import com.jogamp.gluegen.cgram.types.Type;
94import com.jogamp.gluegen.cgram.types.TypeComparator.AliasedSemanticSymbol;
95import com.jogamp.gluegen.cgram.types.TypeDictionary;
110 private Map<Type, Type> canonMap;
125 PUBLIC(
"public"), PROTECTED(
"protected"), PRIVATE(
"private"),
PACKAGE_PRIVATE(
"/* pp */"), PUBLIC_ABSTRACT(
"abstract");
130 this.javaName = javaName;
132 private final String javaName;
176 private List<ConstantDefinition> constants;
177 private List<FunctionSymbol> functions;
180 public List<ConstantDefinition> getConstants() {
184 public List<FunctionSymbol> getFunctions() {
188 private <T extends AliasedSemanticSymbol> List<T> filterSymbolsInt(
final List<T> inList,
189 final boolean preserveOrder,
190 final List<T> outList) {
192 final ArrayHashMap<String, T> symMap =
193 new ArrayHashMap<String, T>(
false, 100, ArrayHashMap.DEFAULT_LOAD_FACTOR);
194 for (
final T sym : inList) {
195 final String origName = sym.getName();
198 if(
null != newName ) {
200 dupSym = symMap.get(newName);
201 if(
null != dupSym ) {
207 dupSym = symMap.get(origName);
209 if(
null != dupSym ) {
211 if( !dupSym.equalSemantics(sym) ) {
212 final ASTLocusTag loc;
214 if( sym instanceof ASTLocusTagProvider ) {
215 loc = ((ASTLocusTagProvider)sym).getASTLocusTag();
219 if( dupSym instanceof ASTLocusTagProvider ) {
220 preLoc = String.format(
",%n %s: previous definition is here",
221 ((ASTLocusTagProvider)dupSym).getASTLocusTag().toString(
new StringBuilder(),
"note",
true));
225 final String mode =
null != newName ?
"alias" :
"orig";
226 final String message =
227 String.format(
"Duplicate Name (%s) w/ incompatible value:%n this '%s',%n have '%s'%s",
228 mode, sym.getAliasedString(), dupSym.getAliasedString(), preLoc);
229 throw new GlueGenException(message, loc);
232 if(
null != newName ) {
234 if(
null != dupSym ) {
236 dupSym.addAliasedName(origName);
240 symMap.put(newName, sym);
244 if(
null != dupSym ) {
248 symMap.put(origName, sym);
252 outList.addAll(symMap.getData());
253 if( !preserveOrder ) {
255 Collections.sort(outList,
new Comparator<T>() {
257 public int compare(
final T o1,
final T o2) {
258 return o1.getName().compareTo(o2.getName());
266 public void filterSymbols(
final List<ConstantDefinition> inConstList,
final List<FunctionSymbol> inFuncList) {
267 constants = filterSymbolsInt(inConstList,
true,
new ArrayList<ConstantDefinition>(100));
268 functions = filterSymbolsInt(inFuncList,
true,
new ArrayList<FunctionSymbol>(100));
275 controls.runSymbolFilter(
new ConstFuncRenamer());
278 for (
final String structs :
cfg.forcedStructs()) {
279 controls.forceStructEmission(structs);
285 }
catch (
final Exception e) {
286 throw new RuntimeException(
"Unable to open files for writing", e);
299 }
catch (
final Exception e) {
300 throw new RuntimeException(
"Unable to close open files", e);
314 return name.replaceAll(
"_",
"_1").replace(
'.',
'_');
337 final ConstantDefinition.JavaExpr constExpr = def.computeJavaExpr(constMap);
338 constMap.put(def.getName(), constExpr);
339 javaUnit().
emit(
" /** ");
340 if (optionalComment !=
null && optionalComment.length() != 0) {
341 javaUnit().
emit(optionalComment);
342 javaUnit().
emit(
", ");
344 javaUnit().
emit(
"CType: ");
345 if( constExpr.resultType.isUnsigned ) {
346 javaUnit().
emit(
"unsigned ");
348 javaUnit().
emit(constExpr.resultJavaTypeName);
350 javaUnit().
emitln(
" public static final " + constExpr.resultJavaTypeName +
351 " " + def.getName() +
" = " + constExpr.javaExpression +
";");
363 final Map<Type, Type> canonMap,
364 final List<FunctionSymbol> cFunctions)
throws Exception {
367 this.canonMap = canonMap;
374 final Type funcPtr = typedefDictionary.get(jcbd.cbFuncTypeName);
376 final Optional<FunctionSymbol> setter = cFunctions.stream()
377 .filter( cFunction -> jcbd.setFuncName.equals(cFunction.getName()) )
379 if( setter.isPresent() ) {
382 LOG.
log(WARNING,
"JavaCallback '{0}' setter not available", jcbd);
385 LOG.
log(WARNING,
"JavaCallback '{0}' function-pointer type not available", jcbd);
393 public Iterator<FunctionSymbol>
emitFunctions(
final List<FunctionSymbol> funcsToBind)
throws Exception {
396 final ArrayList<FunctionEmitter> methodBindingEmitters =
new ArrayList<FunctionEmitter>(2*funcsToBind.size());
403 LOG.
log(INFO, cFunc.getASTLocusTag(),
"Non-Ignored Impl[{0}]: {1}", i++, cFunc);
417 emitter.getUnit().emitln();
420 }
catch (
final Exception e) {
422 "Error while emitting binding for \"" + emitter.getCSymbol().getAliasedString() +
"\"",
423 emitter.getCSymbol().getASTLocusTag(), e);
429 return funcsToBind.iterator();
449 final boolean signatureOnly) {
451 if ( !signatureOnly &&
cfg.manuallyImplement(cSymbol) ) {
461 accessControl = PRIVATE;
463 accessControl =
cfg.accessControl(binding.
getName());
467 if ( signatureOnly && PUBLIC != accessControl ) {
477 final boolean needsJavaCallbackCode =
cfg.requiresJavaCallbackCode( binding.
getName() );
478 final boolean needsBody = isUnimplemented ||
480 binding.signatureUsesJavaPrimitiveArrays() ||
481 needsJavaCallbackCode ||
485 final boolean emitBody = !signatureOnly && needsBody;
486 final boolean isNativeMethod = !isUnimplemented && !needsBody && !signatureOnly;
493 cfg.runtimeExceptionType(),
494 cfg.unsupportedExceptionType(),
496 cfg.tagNativeBinding(),
507 switch (accessControl) {
516 if (isNativeMethod) {
522 allEmitters.add(emitter);
535 final List<FunctionEmitter> allEmitters) {
537 if (
cfg.manuallyImplement(cSymbol)) {
542 final boolean hasPrologueOrEpilogue =
545 final boolean needsJavaCallbackCode =
cfg.requiresJavaCallbackCode( binding.
getName() );
555 if ( !binding.signatureUsesJavaPrimitiveArrays() &&
565 cfg.runtimeExceptionType(),
566 cfg.unsupportedExceptionType(),
568 cfg.tagNativeBinding(),
585 allEmitters.add(emitter);
594 if ( !binding.signatureUsesJavaPrimitiveArrays() ) {
599 cfg.implPackageName(),
607 allEmitters.add(cEmitter);
620 if (capacity !=
null) {
623 }
else if (javaReturnType.
isArray() ||
630 throw new RuntimeException(
"Primitive array return types not yet supported");
648 final ArrayList<FunctionEmitter> allEmitters =
new ArrayList<FunctionEmitter>();
651 generateMethodBindingEmittersImpl(allEmitters, sym,
true);
654 generateMethodBindingEmittersImpl(allEmitters, sym,
false);
656 }
catch (
final Exception e) {
657 throw new GlueGenException(
"Error while generating bindings for \"" + sym +
"\"", sym.getASTLocusTag(), e);
662 private void generateMethodBindingEmittersImpl(
final ArrayList<FunctionEmitter> allEmitters,
664 final boolean forInterface)
throws Exception
667 final MethodBinding mb = bindFunction(sym, forInterface, machDescJava,
null,
null);
673 final HashSet<MethodBinding> methodBindingSet =
new HashSet<MethodBinding>();
677 if(!methodBindingSet.add(binding)) {
684 throw new IllegalArgumentException(
"Cannot create binding in AllStatic mode because method has containing type: \"" +
735 if ( forInterface ) {
773 final Map<Type, Type> canonMap)
throws Exception {
775 this.canonMap = canonMap;
780 final String structCTypeName, typedefedName;
781 final boolean immutableStruct;
783 final String _name = structCType.getName();
784 if (
null != structCTypedefPtr &&
null != structCTypedefPtr.getName() ) {
786 typedefedName = structCTypedefPtr.getName();
787 structCTypeName = typedefedName;
790 typedefedName =
null;
791 structCTypeName = _name;
793 LOG.
log(INFO, structCType.getASTLocusTag(),
"Struct emission of structCType {0}", structCType);
794 LOG.
log(INFO, structCType.getASTLocusTag(),
" structCTypedefPtr {0}", structCTypedefPtr);
795 LOG.
log(INFO, structCType.getASTLocusTag(),
" : structCTypeName \"{0}\" -> typedefedName \"{1}\" -> \"{2}\"",
796 _name, typedefedName, structCTypeName);
797 if (
null == structCTypeName ) {
798 LOG.
log(INFO, structCType.getASTLocusTag(),
799 "skipping emission of unnamed struct {0} w/o typedef", structCType);
804 aliases.addAliasedName(typedefedName);
806 LOG.
log(INFO, structCType.getASTLocusTag(),
807 "skipping emission of ignored \"{0}\": {1}", aliases, structCType);
813 if(
null != structCTypedefPtr && isOpaque(structCTypedefPtr) ) {
814 LOG.
log(INFO, structCType.getASTLocusTag(),
815 "skipping emission of opaque typedef {0}", structCTypedefPtr);
818 if( isOpaque(structCType) ) {
819 LOG.
log(INFO, structCType.getASTLocusTag(),
820 "skipping emission of opaque c-struct {0}", structCType);
824 final Type containingCType;
829 if(
null != typedefedName ) {
830 aptr = structCTypedefPtr;
837 containingCType = canonicalize(aptr);
838 LOG.
log(INFO, structCType.getASTLocusTag(),
"containingCType[{0}]: {1} -canon-> {2}", mode, aptr, containingCType);
840 final JavaType containingJType = typeToJavaType(containingCType,
null);
842 LOG.
log(INFO, structCType.getASTLocusTag(),
843 "skipping emission of opaque {0}, {1}", containingJType, structCType);
847 LOG.
log(WARNING, structCType.getASTLocusTag(),
848 "skipping emission of non-compound {0}, {1}", containingJType, structCType);
851 final String containingJTypeName = containingJType.
getName();
852 LOG.
log(INFO, structCType.getASTLocusTag(),
853 "perform emission of \"{0}\" -> \"{1}\": {2}", structCTypeName, containingJTypeName, structCType);
855 if( 0 == structCType.getNumFields() ) {
856 LOG.
log(INFO, structCType.getASTLocusTag(),
857 "emission of \"{0}\" with zero fields {1}", containingJTypeName, structCType);
882 for (
int i = 0; i < structCType.getNumFields(); i++) {
883 final Field field = structCType.getField(i);
889 final String fieldName = renamed==
null ? field.
getName() : renamed;
892 final boolean isOpaqueField =
null != opaqueField;
895 needsNativeCode =
true;
906 final String javaFileName =
cfg.javaOutputDir() + File.separator +
908 File.separator + containingJTypeName +
".java";
910 javaUnit =
openJavaUnit(javaFileName, structClassPkgName, containingJTypeName);
913 if(
null == javaUnit ) {
917 if (needsNativeCode) {
918 String nRoot =
cfg.nativeOutputDir();
919 if (
cfg.nativeOutputUsesJavaHierarchy()) {
922 final String cUnitName = containingJTypeName +
"_JNI.c";
923 final String fname = nRoot + File.separator + cUnitName;
926 jniUnit.
emitHeader(structClassPkgName, containingJTypeName,
cfg.customCCode());
930 }
catch(
final Exception e) {
931 throw new RuntimeException(
"Unable to open files for emission of struct class", e);
935 javaUnit.
emitln(
"package " + structClassPkgName +
";");
937 javaUnit.
emitln(
"import java.nio.*;");
938 javaUnit.
emitln(
"import java.nio.charset.Charset;");
939 javaUnit.
emitln(
"import java.nio.charset.StandardCharsets;");
942 javaUnit.
emitln(
"import " +
cfg.gluegenRuntimePackage() +
".*;");
944 javaUnit.
emitln(
"import " +
Buffers.class.getPackage().getName() +
".*;");
945 javaUnit.
emitln(
"import " + MachineDataInfoRuntime.class.getName() +
";");
947 final List<String> imports =
cfg.imports();
948 for (
final String str : imports) {
949 javaUnit.
emit(
"import ");
955 for (
final String doc : javadoc) {
958 javaUnit.
emit(
"public class " + containingJTypeName +
" ");
959 boolean firstIteration =
true;
960 final List<String> userSpecifiedInterfaces =
cfg.implementedInterfaces(containingJTypeName);
961 for (
final String userInterface : userSpecifiedInterfaces) {
962 if (firstIteration) {
963 javaUnit.
emit(
"implements ");
965 firstIteration =
false;
966 javaUnit.
emit(userInterface);
971 javaUnit.
emitln(
" StructAccessor accessor;");
974 final String machDescrIdxCode =
null != cfgMachDescrIdxCode ? cfgMachDescrIdxCode :
"private static final int mdIdx = MachineDataInfoRuntime.getStatic().ordinal();";
975 javaUnit.
emitln(
" "+machDescrIdxCode);
976 javaUnit.
emitln(
" private final MachineDataInfo md;");
979 generateOffsetAndSizeArrays(javaUnit,
" ", containingJTypeName, structCType,
null,
null);
981 System.err.printf(
"SE.__: structCType %s%n", structCType.getDebugString());
982 System.err.printf(
"SE.__: contCTypeName %s%n", containingCType.
getDebugString());
983 System.err.printf(
"SE.__: contJTypeName %s%n", containingJType.
getDebugString());
985 for (
int i = 0; i < structCType.getNumFields(); i++) {
986 final Field field = structCType.getField(i);
991 final String fieldName =
null==renamed ? field.
getName() : renamed;
995 System.err.printf(
"SE.os.%02d: %s / %s, %s (%s)%n", (i+1), field, cfgFieldName1, fieldType.
getDebugString(),
"FuncPtr");
997 generateOffsetAndSizeArrays(javaUnit,
" ", fieldName,
null, field,
null);
998 generateOffsetAndSizeArrays(javaUnit,
"//", fieldName, fieldType,
null,
null);
1003 if (fieldType.
getName() ==
null) {
1004 throw new GlueGenException(
"Anonymous structs as fields not supported yet, field \"" +
1008 System.err.printf(
"SE.os.%02d: %s / %s, %s (%s)%n", (i+1), field, cfgFieldName1, fieldType.
getDebugString(),
"compound");
1010 generateOffsetAndSizeArrays(javaUnit,
" ", fieldName, fieldType, field,
null);
1011 }
else if (fieldType.
isArray()) {
1014 System.err.printf(
"SE.os.%02d: %s / %s, %s (%s)%n", (i+1), field, cfgFieldName1, fieldType.
getDebugString(),
"array");
1015 System.err.printf(
"SE.os.%02d: baseType %s%n", (i+1), baseElementType.
getDebugString());
1017 generateOffsetAndSizeArrays(javaUnit,
" ", fieldName,
null, field,
null);
1018 generateOffsetAndSizeArrays(javaUnit,
"//", fieldName, fieldType,
null,
null);
1022 externalJavaType = typeToJavaType(fieldType, machDescJava);
1023 }
catch (
final Exception e) {
1024 throw new GlueGenException(
"Error occurred while creating accessor for field \"" +
1028 System.err.printf(
"SE.os.%02d: %s / %s, %s (%s)%n", (i+1), field, cfgFieldName1, fieldType.
getDebugString(),
"MISC");
1029 System.err.printf(
"SE.os.%02d: javaType %s%n", (i+1), externalJavaType.
getDebugString());
1033 generateOffsetAndSizeArrays(javaUnit,
" ", fieldName,
null, field,
null);
1034 generateOffsetAndSizeArrays(javaUnit,
"//", fieldName, fieldType,
null,
null);
1036 if( requiresGetCStringLength(fieldType, cfgFieldName1) ) {
1037 generateOffsetAndSizeArrays(javaUnit,
" ", fieldName,
null, field,
null);
1038 generateOffsetAndSizeArrays(javaUnit,
"//", fieldName, fieldType,
null,
"// "+externalJavaType.
getDebugString());
1040 generateOffsetAndSizeArrays(javaUnit,
" ", fieldName,
null, field,
null);
1041 generateOffsetAndSizeArrays(javaUnit,
"//", fieldName, fieldType, field,
"// "+externalJavaType.
getDebugString());
1044 generateOffsetAndSizeArrays(javaUnit,
" ", fieldName,
null, field,
null);
1045 generateOffsetAndSizeArrays(javaUnit,
"//", fieldName, fieldType,
null,
"// "+externalJavaType.
getDebugString());
1048 }
else if(
GlueGen.debug() ) {
1049 System.err.printf(
"SE.os.%02d: %s, %s (IGNORED)%n", (i+1), field, fieldType.
getDebugString());
1053 javaUnit.
emitln(
" /** Returns true if this generated implementation uses native code, otherwise false. */");
1054 javaUnit.
emitln(
" public static boolean usesNativeCode() {");
1055 javaUnit.
emitln(
" return "+needsNativeCode+
";");
1061 javaUnit.
emitln(
" /** Returns the aligned total size of a native instance. */");
1062 javaUnit.
emitln(
" public static int size() {");
1063 javaUnit.
emitln(
" return "+containingJTypeName+
"_size[mdIdx];");
1068 javaUnit.
emitln(
" /** Returns a new instance with all bytes set to zero. */");
1069 javaUnit.
emitln(
" public static " + containingJTypeName +
" create() {");
1070 javaUnit.
emitln(
" return create(Buffers.newDirectByteBuffer(size()));");
1073 javaUnit.
emitln(
" /** Returns a new instance using the given ByteBuffer having at least {#link size()} bytes capacity. The ByteBuffer will be {@link ByteBuffer#rewind()} and native-order set. */");
1074 javaUnit.
emitln(
" public static " + containingJTypeName +
" create(java.nio.ByteBuffer buf) {");
1075 javaUnit.
emitln(
" return new " + containingJTypeName +
"(buf);");
1079 javaUnit.
emitln(
" /** Returns new instance dereferencing ByteBuffer at given native address `addr` with size {@link #size()}. */");
1080 javaUnit.
emitln(
" public static " + containingJTypeName +
" derefPointer(final long addr) {");
1081 javaUnit.
emitln(
" return create( ElementBuffer.derefPointer(size(), addr, 1).getByteBuffer() );");
1085 javaUnit.
emitln(
" " + containingJTypeName +
"(java.nio.ByteBuffer buf) {");
1086 javaUnit.
emitln(
" md = MachineDataInfo.StaticConfig.values()[mdIdx].md;");
1087 javaUnit.
emitln(
" accessor = new StructAccessor(buf);");
1091 javaUnit.
emitln(
" /** Return the underlying native direct ByteBuffer */");
1092 javaUnit.
emitln(
" public final java.nio.ByteBuffer getBuffer() {");
1093 javaUnit.
emitln(
" return accessor.getBuffer();");
1096 javaUnit.
emitln(
" /** Returns the native address of the underlying native ByteBuffer {@link #getBuffer()} */");
1097 javaUnit.
emitln(
" public final long getDirectBufferAddress() {");
1098 javaUnit.
emitln(
" return accessor.getDirectBufferAddress();");
1102 final Set<MethodBinding> methodBindingSet =
new HashSet<MethodBinding>();
1104 for (
int i = 0; i < structCType.getNumFields(); i++) {
1105 final Field field = structCType.getField(i);
1111 final String fieldName = renamed==
null ? field.
getName() : renamed;
1114 final boolean isOpaqueFieldType =
null != opaqueFieldType;
1116 final boolean isOpaqueField =
null != opaqueField;
1117 final boolean immutableField = immutableStruct ||
cfg.
immutableAccess(fqStructFieldName1);
1120 System.err.printf(
"SE.ac.%02d: field %s / %s / rename %s -> %s / opaque %b, fieldType %s (opaque %b), immutable[struct %b, field %b]%n", (i+1),
1121 field, fqStructFieldName1, renamed, fieldName, isOpaqueField, fieldType.
getDebugString(), isOpaqueFieldType,
1122 immutableStruct, immutableField);
1123 System.err.printf(
"SE.ac.%02d: opaqueFieldType %s%n", (i+1), opaqueFieldType);
1128 final String javaTypeName =
"long";
1130 if( !immutableField && !fieldType.
isConst() ) {
1132 generateSetterSignature(javaUnit,
MethodAccess.
PUBLIC,
false,
false, fieldName, fieldType,
Ownership.
Parent, containingJTypeName, capFieldName,
null, javaTypeName,
null,
false,
false,
null,
null,
null);
1134 javaUnit.
emitln(
" accessor.setLongAt(" + fieldName+
"_offset[mdIdx], src, md.pointerSizeInBytes());");
1135 javaUnit.
emitln(
" return this;");
1140 generateGetterSignature(javaUnit,
false,
false, fieldName, fieldType,
Ownership.
Parent, javaTypeName, capFieldName,
null,
false,
false,
null,
null);
1142 javaUnit.
emitln(
" return accessor.getLongAt(" + fieldName+
"_offset[mdIdx], md.pointerSizeInBytes());");
1145 generateFunctionPointerCode(methodBindingSet, javaUnit, jniUnit, structCTypeName,
1146 containingCType, containingJType, i, func, fqStructFieldName1);
1147 }
else if ( fieldType.
isCompound() && !isOpaqueField ) {
1150 if (fieldType.
getName() ==
null) {
1151 throw new GlueGenException(
"Anonymous structs as fields not supported yet (field \"" +
1152 field +
"\" in type \"" + structCTypeName +
"\")",
1155 if( !immutableField && !fieldType.
isConst() ) {
1157 generateSetterSignature(javaUnit,
MethodAccess.
PUBLIC,
false,
false, fieldName, fieldType,
Ownership.
Parent, containingJTypeName,
CodeGenUtils.
capitalizeString(fieldName),
null, fieldType.
getName(),
null,
false,
false,
null,
null,
null);
1159 javaUnit.
emitln(
" final ByteBuffer bb = src.getBuffer();");
1160 javaUnit.
emitln(
" final int size = "+fieldName+
"_size[mdIdx];");
1161 javaUnit.
emitln(
" final byte[] content = new byte[size];");
1162 javaUnit.
emitln(
" bb.get(content, 0, size);");
1163 javaUnit.
emitln(
" accessor.setBytesAt("+fieldName+
"_offset[mdIdx], content);");
1164 javaUnit.
emitln(
" return this;");
1169 generateGetterSignature(javaUnit,
false,
false, fieldName, fieldType,
Ownership.
Parent, fieldType.
getName(),
CodeGenUtils.
capitalizeString(fieldName),
null,
false,
false,
null,
null);
1171 javaUnit.
emitln(
" return " + fieldType.
getName() +
".create( accessor.slice( " +
1172 fieldName+
"_offset[mdIdx], "+fieldName+
"_size[mdIdx] ) );");
1175 }
else if ( ( fieldType.
isArray() || fieldType.
isPointer() ) && !isOpaqueField ) {
1176 generateArrayGetterSetterCode(javaUnit, structCType, containingJType,
1177 i, field, fieldName, immutableField, fqStructFieldName1);
1181 javaType = typeToJavaType(fieldType, machDescJava);
1182 }
catch (
final Exception e) {
1183 throw new GlueGenException(
"Error occurred while creating accessor for field \"" +
1186 if ( isOpaqueFieldType || isOpaqueField || javaType.
isPrimitive()) {
1189 final String javaTypeName;
1190 if ( isOpaqueFieldType ) {
1191 javaTypeName = opaqueFieldType.javaType().
getName();
1192 }
else if ( isOpaqueField ) {
1193 javaTypeName = opaqueField.javaType().
getName();
1196 javaTypeName = javaType.
getName();
1200 final String sizeDenominator = fieldType.
isPointer() ?
"pointer" : javaTypeName ;
1202 LOG.
log(FINE, structCType.getASTLocusTag(),
1203 "Java.StructEmitter.Primitive: "+field.
getName()+
", "+fieldType+
", "+javaTypeName+
", "+
1204 ", fixedSize "+fieldTypeNativeSizeFixed+
", opaque[t "+isOpaqueFieldType+
", f "+isOpaqueField+
"], sizeDenominator "+sizeDenominator);
1206 if( !immutableField && !fieldType.
isConst() ) {
1208 generateSetterSignature(javaUnit,
MethodAccess.
PUBLIC,
false,
false, fieldName, fieldType,
Ownership.
Parent, containingJTypeName, capFieldName,
null, javaTypeName,
null,
false,
false,
null,
null,
null);
1210 if( fieldTypeNativeSizeFixed ) {
1211 javaUnit.
emitln(
" accessor.set" + capJavaTypeName +
"At(" + fieldName+
"_offset[mdIdx], src);");
1213 javaUnit.
emitln(
" accessor.set" + capJavaTypeName +
"At(" + fieldName+
"_offset[mdIdx], src, md."+sizeDenominator+
"SizeInBytes());");
1215 javaUnit.
emitln(
" return this;");
1221 generateGetterSignature(javaUnit,
false,
false, fieldName, fieldType,
Ownership.
Parent, javaTypeName, capFieldName,
null,
false,
false,
null,
null);
1223 javaUnit.emit (
" return ");
1224 if( fieldTypeNativeSizeFixed ) {
1225 javaUnit.
emitln(
"accessor.get" + capJavaTypeName +
"At(" + fieldName+
"_offset[mdIdx]);");
1227 javaUnit.
emitln(
"accessor.get" + capJavaTypeName +
"At(" + fieldName+
"_offset[mdIdx], md."+sizeDenominator+
"SizeInBytes());");
1241 if (needsNativeCode) {
1246 System.err.printf(
"SE.XX: structCType %s%n", structCType.getDebugString());
1247 System.err.printf(
"SE.XX: contCTypeName %s%n", containingCType.
getDebugString());
1248 System.err.printf(
"SE.XX: contJTypeName %s%n", containingJType.
getDebugString());
1254 public static int addStrings2Buffer(StringBuilder buf,
final String sep,
final String first,
final Collection<String> col) {
1257 buf =
new StringBuilder();
1260 final Iterator<String> iter = col.iterator();
1263 if( iter.hasNext() ) {
1268 while( iter.hasNext() ) {
1269 buf.append(iter.next());
1270 if( iter.hasNext() ) {
1281 private void generateArrayFieldNote(
final CodeUnit unit,
final String leadIn,
final String leadOut,
1282 final String fieldName,
final Type fieldType,
final Ownership ownership,
1283 final boolean constElemCount,
final boolean maxOneElem,
final String elemCountExpr,
1284 final boolean multiline,
final boolean startNewPara) {
1285 final boolean isArray;
1286 final Type referencedType;
1287 final String relationship;
1291 referencedType =
null;
1292 relationship =
"being";
1296 relationship =
"referencing";
1297 }
else if( fieldType.
isArray() ) {
1300 if( t != fieldType && t.isPointer() ) {
1303 referencedType =
null;
1305 relationship =
"being";
1308 referencedType =
null;
1309 relationship =
"being";
1314 if( startNewPara ) {
1319 if(
null != leadIn ) {
1320 unit.
emit(leadIn+
" ");
1322 final String ownershipTerm;
1323 switch( ownership ) {
1324 case Parent: ownershipTerm =
"a <i>struct</i> owned";
break;
1325 case Java: ownershipTerm =
"a <i>Java</i> owned";
break;
1326 case Native: ownershipTerm =
"a <i>natively</i> owned";
break;
1327 default: ownershipTerm =
"a <i>mixed and ambigously</i> owned (<b>warning</b>)";
break;
1331 what =
"function pointer";
1332 }
else if( isArray ) {
1335 what = fieldType.getClass().getSimpleName();
1337 unit.
emit(
"native field <code>"+fieldName+
"</code>, "+relationship+
" "+ownershipTerm+
" "+what);
1339 unit.
emit(
" with "+(constElemCount?
"fixed":
"variable")+
" element count");
1340 if(
null != elemCountExpr ) {
1341 if( elemCountExpr.startsWith(
"get") && elemCountExpr.endsWith(
"()") ) {
1342 unit.
emit(
" of {@link #"+elemCountExpr+
"} ");
1344 unit.
emit(
" of <code>"+elemCountExpr+
"</code> ");
1346 if( constElemCount || Ownership.Mixed == ownership ) {
1347 unit.
emit(
"elements.");
1349 unit.
emit(
"initial elements.");
1359 if( startNewPara ) {
1366 unit.
emitln(
" * Maximum element count is <code>1</code>.");
1369 unit.
emit(
" Maximum element count is <code>1</code>.");
1374 if(
null == referencedType ) {
1375 unit.
emitln(
" * Native Field Signature <code>"+fieldType.
getSignature(
null).toString()+
"</code>");
1377 unit.
emitln(
" * Native Signature:");
1379 unit.
emitln(
" * <li>field-type <code>"+fieldType.
getSignature(
null).toString()+
"</code></li>");
1380 unit.
emitln(
" * <li>referenced <code>"+referencedType.
getSignature(
null).toString()+
"</code></li>");
1385 unit.
emit(
" NativeSig <code>"+fieldType.
getSignature(
null).toString()+
"</code>");
1387 if(
null != leadOut ) {
1388 unit.
emit(
" "+leadOut);
1394 private void generateIsNullSignature(
final CodeUnit unit,
final boolean abstractMethod,
1395 final String fieldName,
final Type fieldType,
final Ownership ownership,
1396 final String capitalizedFieldName,
final boolean constElemCount,
final boolean maxOneElem,
final String elemCountExpr) {
1397 unit.emitln(
" /**");
1398 unit.emitln(
" * Returns `true` if native pointer <code>"+fieldName+
"</code> is `null`, otherwise `false`.");
1399 generateArrayFieldNote(unit,
"Corresponds to",
null, fieldName, fieldType, ownership, constElemCount, maxOneElem, elemCountExpr,
true,
true);
1401 unit.emit(
" public " + (abstractMethod ?
"abstract " :
"final ") +
"boolean is" + capitalizedFieldName +
"Null()");
1403 private void generateReleaseSignature(
final CodeUnit unit,
final boolean abstractMethod,
1404 final String fieldName,
final Type fieldType,
final Ownership ownership,
final String returnTypeName,
1405 final String capitalizedFieldName,
final boolean constElemCount,
final boolean maxOneElement,
final String elemCountExpr) {
1406 unit.emitln(
" /**");
1407 generateArrayFieldNote(unit,
"Releases memory referenced by",
null, fieldName, fieldType, ownership, constElemCount, maxOneElement, elemCountExpr,
true,
false);
1409 unit.emit(
" public " + (abstractMethod ?
"abstract " :
"final ") + returnTypeName +
" release" + capitalizedFieldName +
"()");
1411 private void generateGetterSignature(
final CodeUnit unit,
final boolean staticMethod,
final boolean abstractMethod,
1412 final String fieldName,
final Type fieldType,
final Ownership ownership,
final String returnTypeName,
1413 final String capitalizedFieldName,
final String customArgs,
final boolean constElemCount,
1414 final boolean maxOneElem,
final String elemCountExpr,
final String apiDocTail) {
1415 unit.emitln(
" /**");
1416 generateArrayFieldNote(unit,
"Getter for",
null, fieldName, fieldType, ownership, constElemCount, maxOneElem, elemCountExpr,
true,
false);
1417 if(
null != apiDocTail ) {
1418 unit.emitln(
" * "+apiDocTail);
1421 unit.emit(
" public " + (staticMethod ?
"static " :
"final ") + (abstractMethod ?
"abstract " :
"") + returnTypeName +
" get" + capitalizedFieldName +
"(");
1422 if(
null != customArgs ) {
1423 unit.emit(customArgs);
1427 private void generateSetterSignature(
final CodeUnit unit,
final MethodAccess accessMod,
final boolean staticMethod,
final boolean abstractMethod,
1428 final String fieldName,
final Type fieldType,
final Ownership ownership,
final String returnTypeName,
1429 final String capitalizedFieldName,
final String customArgsPre,
final String paramTypeName,
1430 final String customArgsPost,
final boolean constElemCount,
final boolean maxOneElem,
final String elemCountExpr,
1431 final String apiDocDetail,
final String apiDocArgs) {
1432 unit.emitln(
" /**");
1433 generateArrayFieldNote(unit,
"Setter for",
null, fieldName, fieldType, ownership, constElemCount, maxOneElem, elemCountExpr,
true,
false);
1434 if(
null != apiDocDetail ) {
1435 unit.emitln(
" * <p>");
1436 unit.emitln(
" * "+apiDocDetail);
1437 unit.emitln(
" * </p>");
1439 if(
null != apiDocArgs ) {
1440 unit.emitln(apiDocArgs);
1443 unit.emit(
" "+accessMod.getJavaName() +
" " + (staticMethod ?
"static " :
"final ") + (abstractMethod ?
"abstract " :
"") + returnTypeName +
" set" + capitalizedFieldName +
"(");
1444 if(
null != customArgsPre ) {
1445 unit.emit(customArgsPre+
", ");
1447 unit.emit(paramTypeName +
" src");
1448 if(
null != customArgsPost ) {
1449 unit.emit(
", "+customArgsPost);
1454 private void generateOffsetAndSizeArrays(
final CodeUnit unit,
final String prefix,
1455 final String fieldName,
final Type fieldType,
1456 final Field field,
final String postfix) {
1458 unit.emit(prefix+
"private static final int[] "+fieldName+
"_offset = new int[] { ");
1459 for(
int i=0; i < machDescTargetConfigs.length; i++ ) {
1463 unit.emit(field.getOffset(machDescTargetConfigs[i].md) +
1464 " /* " + machDescTargetConfigs[i].name() +
" */");
1468 if(
null!=fieldType) {
1469 unit.emit(prefix+
"private static final int[] "+fieldName+
"_size = new int[] { ");
1470 for(
int i=0; i < machDescTargetConfigs.length; i++ ) {
1474 unit.emit(fieldType.getSize(machDescTargetConfigs[i].md) +
1475 " /* " + machDescTargetConfigs[i].name() +
" */");
1478 if(
null != postfix ) {
1479 unit.emitln(postfix);
1486 private void generateJavaCallbackCode(
final JavaCallbackDef jcbd,
final FunctionType funcType) {
1487 final FunctionSymbol funcSym =
new FunctionSymbol(
"callback", funcType);
1488 funcSym.addAliasedName(jcbd.cbFuncTypeName);
1489 LOG.
log(INFO,
"JavaCallback: fSym {0}, {1}", funcSym.getAliasedString(), jcbd);
1491 final String cbSimpleClazzName = CodeGenUtils.capitalizeString(jcbd.cbFuncTypeName);
1492 final String cbFQClazzName =
cfg.packageName()+
"."+
cfg.className()+
"."+cbSimpleClazzName;
1494 final JavaCallbackInfo jcbi0 = javaCallbackInterfaceMap.get(cbFQClazzName);
1495 if(
null != jcbi0 ) {
1497 if( jcbi0.cbFuncUserParamIdx != jcbd.cbFuncUserParamIdx ) {
1498 throw new UnsupportedOperationException(
"Reused FuncTypeName "+jcbd.cbFuncTypeName+
" used with different FuncUserParamIdx "+jcbi0.cbFuncUserParamIdx+
" -> "+jcbd.cbFuncUserParamIdx+
". Func "+
1499 funcType.toString(jcbd.cbFuncTypeName,
false,
true));
1501 final JavaCallbackInfo jcbi1 =
new JavaCallbackInfo(jcbd.cbFuncTypeName, cbSimpleClazzName, cbFQClazzName, jcbi0.staticCBMethodSignature,
1502 funcType, jcbi0.cbFuncBinding, jcbi0.cbFuncUserParamIdx, jcbd.cbFuncKeyIndices,
1503 jcbd.setFuncName, jcbd.setFuncUserParamIdx, jcbd.setFuncKeyIndices,
1504 jcbd.userParamClassName, jcbd.customKeyClassName);
1505 cfg.setFuncToJavaCallbackMap.put(jcbd.setFuncName, jcbi1);
1506 LOG.
log(INFO,
"JavaCallbackInfo: Reusing {0} -> {1}", jcbd.setFuncName, jcbi0);
1508 final StringBuilder cbMethodSignature =
new StringBuilder();
1509 final List<MethodBinding> mbs;
1511 javaUnit.
emitln(
" /** JavaCallback interface: "+jcbd.cbFuncTypeName+
" -> "+funcType.toString(jcbd.cbFuncTypeName,
false,
true)+
" */");
1512 javaUnit.
emitln(
" public static interface "+cbSimpleClazzName+
" {");
1513 mbs = generateFunctionInterfaceCode(javaUnit, funcSym, jcbd, cbMethodSignature);
1517 LOG.
log(WARNING,
"JavaCallbackInfo: Java Configuration indicate current JavaCallback must be ignored so assume JavaCallback meet presents requirements of {0}", jcbd.setFuncName);
1518 mbs = generateFunctionInterfaceCode(
null, funcSym, jcbd, cbMethodSignature);
1520 if( 1 != mbs.size() ) {
1521 throw new UnsupportedOperationException(
"Multiple bindings generated where only 1 is allowed for func "+funcType.toString(jcbd.cbFuncTypeName,
false,
true));
1523 final MethodBinding cbFuncBinding = mbs.get(0);
1524 if( !cbFuncBinding.getJavaReturnType().isVoid() && !cbFuncBinding.getJavaReturnType().isPrimitive() ) {
1525 throw new UnsupportedOperationException(
"Non void or non-primitive callback return types not suppored. Java "+
1526 cbFuncBinding.getJavaReturnType()+
", func "+funcType.toString(jcbd.cbFuncTypeName,
false,
true));
1528 final JavaCallbackInfo jcbi1 =
new JavaCallbackInfo(jcbd.cbFuncTypeName, cbSimpleClazzName, cbFQClazzName, cbMethodSignature.toString(),
1529 funcType, cbFuncBinding, jcbd.cbFuncUserParamIdx, jcbd.cbFuncKeyIndices,
1530 jcbd.setFuncName, jcbd.setFuncUserParamIdx, jcbd.setFuncKeyIndices,
1531 jcbd.userParamClassName, jcbd.customKeyClassName);
1532 cfg.setFuncToJavaCallbackMap.put(jcbd.setFuncName, jcbi1);
1533 javaCallbackInterfaceMap.put(cbFQClazzName, jcbi1);
1534 LOG.
log(INFO,
"JavaCallbackInfo: Added {0} -> {1}", jcbd.setFuncName, jcbi1);
1537 private final Map<String, JavaCallbackInfo> javaCallbackInterfaceMap =
new HashMap<String, JavaCallbackInfo>();
1539 private List<MethodBinding> generateFunctionInterfaceCode(
final JavaCodeUnit javaUnit,
final FunctionSymbol funcSym,
final JavaCallbackDef jcbd,
final StringBuilder methodSignature) {
1541 MethodBinding mb = bindFunction(funcSym,
true , machDescJava,
null,
null);
1544 final int userParamIdx = jcbd.cbFuncUserParamIdx;
1545 if( 0 <= userParamIdx && userParamIdx < mb.getNumArguments() ) {
1546 final JavaType t = mb.getJavaArgumentType(userParamIdx);
1547 if ( t.isCVoidPointerType() ) {
1548 final JavaType mappedType;
1549 if(
null != jcbd.userParamClassName ) {
1550 mappedType = JavaType.createForNamedClass( jcbd.userParamClassName );
1551 mb = mb.replaceJavaArgumentType(userParamIdx, JavaType.forObjectClass());
1553 mappedType = JavaType.forObjectClass();
1555 mb = mb.replaceJavaArgumentType(userParamIdx, mappedType);
1560 methodSignature.append(
"(");
1561 for(
int i=0; i<mb.getNumArguments(); ++i) {
1562 final JavaType t = mb.getJavaArgumentType(i);
1563 methodSignature.append(t.getDescriptor(
cfg));
1565 methodSignature.append(
")");
1566 final JavaType rt = mb.getJavaReturnType();
1567 methodSignature.append(rt.getDescriptor(
cfg));
1574 final boolean useNIOOnly =
true;
1575 final boolean useNIODirectOnly =
true;
1577 if(
null != javaUnit) {
1578 for (
final MethodBinding binding : bindings) {
1580 final JavaMethodBindingEmitter emitter =
new JavaMethodBindingEmitter(binding,
1582 cfg.runtimeExceptionType(),
1583 cfg.unsupportedExceptionType(),
1585 cfg.tagNativeBinding(),
1597 protected String getBaseIndentString() {
return " "; }
1599 emitter.addModifier(JavaMethodBindingEmitter.PUBLIC);
1606 private void generateFunctionPointerCode(
final Set<MethodBinding> methodBindingSet,
1607 final JavaCodeUnit javaUnit,
final CCodeUnit jniUnit,
1608 final String structCTypeName,
final Type containingCType,
final JavaType containingJType,
1609 final int i,
final FunctionSymbol funcSym,
final String returnSizeLookupName) {
1611 final MethodBinding mb = bindFunction(funcSym,
true , machDescJava, containingJType, containingCType);
1612 mb.findThisPointer();
1618 final boolean useNIOOnly =
true;
1619 final boolean useNIODirectOnly =
true;
1621 for (
final MethodBinding binding : bindings) {
1622 if(!methodBindingSet.add(binding)) {
1627 JavaMethodBindingEmitter emitter =
1628 new JavaMethodBindingEmitter(binding,
1630 cfg.runtimeExceptionType(),
1631 cfg.unsupportedExceptionType(),
1633 cfg.tagNativeBinding(),
1644 emitter.addModifier(JavaMethodBindingEmitter.PUBLIC);
1645 emitter.addModifier(JavaMethodBindingEmitter.FINAL);
1651 new JavaMethodBindingEmitter(binding,
1653 cfg.runtimeExceptionType(),
1654 cfg.unsupportedExceptionType(),
1656 cfg.tagNativeBinding(),
1666 emitter.addModifier(JavaMethodBindingEmitter.PRIVATE);
1667 emitter.addModifier(JavaMethodBindingEmitter.NATIVE);
1672 final CMethodBindingEmitter cEmitter =
1673 new CMethodBindingEmitter(binding,
1676 containingJType.getName(),
1682 cEmitter.setIsCStructFunctionPointer(
true);
1683 prepCEmitter(returnSizeLookupName, binding.getJavaReturnType(), cEmitter);
1689 private String getArrayArrayLengthExpr(
final ArrayType type,
final String returnSizeLookupName,
final boolean hasFixedTypeLen[],
final int[][] lengthRes) {
1690 final int[] length =
new int[type.arrayDimension()];
1691 lengthRes[0] = length;
1692 final StringBuilder lengthExpr =
new StringBuilder();
1693 hasFixedTypeLen[0] =
true;
1694 ArrayType typeIter = type;
1695 for(
int i=0; i<length.length; i++) {
1696 if(
null!=typeIter && typeIter.hasLength() ) {
1697 length[i] = typeIter.getLength();
1699 lengthExpr.append(
"*");
1701 lengthExpr.append(length[i]);
1704 hasFixedTypeLen[0] =
false;
1706 if(
null != typeIter ) {
1707 typeIter = typeIter.getTargetType().asArray();
1711 if(
null != cfgVal ) {
1712 if( hasFixedTypeLen[0] ) {
1713 LOG.
log(WARNING, type.getASTLocusTag(),
1714 "struct array field '"+returnSizeLookupName+
"' of '"+type+
"' length '"+Arrays.toString(length)+
"' overwritten by cfg-expression: "+cfgVal);
1718 if( hasFixedTypeLen[0] ) {
1719 return lengthExpr.toString();
1721 LOG.
log(WARNING, type.getASTLocusTag(),
1722 "struct array field '"+returnSizeLookupName+
"' length '"+Arrays.toString(length)+
"' without fixed- nor configured-size: {0}", type);
1727 private boolean requiresGetCStringLength(
final Type fieldType,
final String returnSizeLookupName) {
1728 if( !
cfg.returnsString(returnSizeLookupName) && !
cfg.returnsStringOnly(returnSizeLookupName) ) {
1731 final PointerType pointerType = fieldType.asPointer();
1732 if(
null != pointerType ) {
1738 private static final String GetElemValueApiDocTail =
"@return element value of the corresponding field-array";
1739 private static final String GetElemCountApiDocTail =
"@return element count of the corresponding field-array";
1741 private static final String SetSubArrayArgsPost =
"final int srcPos, final int destPos, final int length";
1742 private static final String SetSubArrayArgsCheck =
" if( 0 > srcPos || 0 > destPos || 0 > length || srcPos + length > src.length ) { throw new IndexOutOfBoundsException(\"src[pos \"+srcPos+\", length \"+src.length+\"], destPos \"+destPos+\", length \"+length); }";
1743 private static final String SetSubArrayApiDocDetail =
"Copies the given source elements into the respective field's existing memory.";
1744 private static final String SetSubArrayApiDocArgs =
1745 " * @param src the source array of elements\n"+
1746 " * @param srcPos starting element position within the source array with 'srcPos >= 0` && `srcPos + length <= src.length`, otherwise an {@link IndexOutOfBoundsException} is thrown\n"+
1747 " * @param destPos starting element position within the destination with 'destPos >= 0` && `destPos + length <= elemCount`, otherwise an exception is thrown\n"+
1748 " * @param length the element count to be copied with 'length >= 0` && `srcPos + length <= src.length` && `destPos + length <= elemCount`, otherwise an {@link IndexOutOfBoundsException} is thrown\n"+
1749 " * @return this instance of chaining";
1751 private static final String SetArrayArgsPre =
"final boolean subset";
1752 private static final String SetArrayArgsPost =
"final int srcPos, final int destPos, final int length";
1753 private static final String SetArrayArgsCheck =
" if( 0 > srcPos || 0 > destPos || 0 > length || srcPos + length > src.length ) { throw new IndexOutOfBoundsException(\"subset \"+subset+\", src[pos \"+srcPos+\", length \"+src.length+\"], destPos \"+destPos+\", length \"+length); }";
1754 private static final String SetArrayApiDocDetail =
"Copies the given source elements into the respective field, either writing into the existing memory or creating a new memory and referencing it.";
1755 private static final String SetArrayApiDocArgs =
1756 " * @param subset if `true` keeps the underlying memory and only allows to set up to `elemCount` elements. Otherwise may replace the underlying memory if `destPos + length != elemCount`.\n"+
1757 " * @param src the source array of elements\n"+
1758 " * @param srcPos starting element position within the source array with 'srcPos >= 0` && `srcPos + length <= src.length`, otherwise an {@link IndexOutOfBoundsException} is thrown\n"+
1759 " * @param destPos starting element position within the destination with 'destPos >= 0`. If `subset == true`, `destPos + length <= elemCount` also must be be `true`. Otherwise an exception is thrown\n"+
1760 " * @param length the element count to be copied with 'length >= 0` && `srcPos + length <= src.length`, otherwise an {@link IndexOutOfBoundsException} is thrown\n"+
1761 " * @return this instance of chaining";
1763 private static final String SetReplaceArrayArgsPost =
"final int srcPos, final int length";
1764 private static final String SetReplaceArrayArgsCheck =
" if( 0 > srcPos || 0 > length || srcPos + length > src.length ) { throw new IndexOutOfBoundsException(\"src[pos \"+srcPos+\", length \"+src.length+\"], length \"+length); }";
1765 private static final String SetReplaceArrayApiDocDetail =
"Replaces the respective field's memory with a new memory segment containing given source elements and referencing it.";
1766 private static final String SetReplaceArrayApiDocArgs =
1767 " * @param src the source array of elements\n"+
1768 " * @param srcPos starting element position within the source array with 'srcPos >= 0` && `srcPos + length <= src.length`, otherwise an {@link IndexOutOfBoundsException} is thrown\n"+
1769 " * @param length the element count to be copied with 'length >= 0` && `srcPos + length <= src.length`, otherwise an {@link IndexOutOfBoundsException} is thrown\n"+
1770 " * @return this instance of chaining";
1772 private static final String GetArrayArgs =
"final int destPos, final int length";
1773 private static final String GetArrayArgsCheck =
" if( 0 > srcPos || 0 > destPos || 0 > length || destPos + length > dest.length ) { throw new IndexOutOfBoundsException(\"dest[pos \"+destPos+\", length \"+dest.length+\"], srcPos \"+srcPos+\", length \"+length); }";
1776 private void generateArrayGetterSetterCode(
final JavaCodeUnit unit,
1777 final CompoundType structCType,
1778 final JavaType containingJType,
1779 final int i,
final Field field,
final String fieldName,
1780 final boolean immutableAccess,
1781 final String fqStructFieldName)
throws Exception {
1782 final Type fieldType = field.getType();
1783 final TypeInfo opaqueTypeInfo =
cfg.
typeInfo(fieldType);
1784 final boolean isOpaque =
null != opaqueTypeInfo;
1785 final Type baseElemType = fieldType.getArrayBaseOrPointerTargetType();
1786 if( GlueGen.debug() ) {
1787 System.err.printf(
"SE.ac.%02d: fieldName %s, fqName %s%n", (i+1), fieldName, fqStructFieldName);
1788 System.err.printf(
"SE.ac.%02d: structCType %s, %s%n", (i+1), structCType.toString(), structCType.getSignature(
null).toString());
1789 System.err.printf(
"SE.ac.%02d: fieldType %s, %s%n", (i+1), fieldType.toString(), fieldType.getSignature(
null).toString());
1790 System.err.printf(
"SE.ac.%02d: opaqueInfo %b, %s%n", (i+1), isOpaque, opaqueTypeInfo);
1791 System.err.printf(
"SE.ac.%02d: baseElemType %s, %s%n", (i+1), baseElemType.toString(), baseElemType.getSignature(
null).toString());
1797 final String containingJTypeName = containingJType.getName();
1798 final boolean isStringOnly =
cfg.returnsStringOnly(fqStructFieldName);
1799 final boolean isString = isStringOnly ||
cfg.returnsString(fqStructFieldName);
1801 unit.addTailCode(optStringCharsetCode);
1803 final boolean isPointer;
1804 final boolean isPrimitive;
1805 final boolean isConstValue;
1806 final MethodAccess accessMod = MethodAccess.PUBLIC;
1807 final Ownership ownership;
1808 final String elemCountExpr;
1809 final boolean constElemCount;
1810 final boolean staticElemCount;
1811 final JavaType baseJElemType;
1812 final String baseJElemTypeName;
1813 final boolean primElemFixedSize;
1814 final boolean baseIsPointer;
1815 final String baseElemSizeDenominator;
1816 final boolean useGetCStringLength;
1817 final boolean maxOneElement;
1818 if( isOpaque && opaqueTypeInfo.pointerDepth() <= 1 ||
1819 ( fieldType.isPrimitive() && !baseElemType.isFunctionPointer() ) ||
1820 ( fieldType.isPointer() && baseElemType.isVoid() )
1826 isConstValue = fieldType.isConst();
1827 elemCountExpr =
"1";
1828 constElemCount =
true;
1829 ownership = Ownership.Parent;
1830 staticElemCount =
true;
1831 baseJElemType =
null;
1832 baseJElemTypeName = compatiblePrimitiveJavaTypeName(fieldType, machDescJava);
1833 primElemFixedSize =
false;
1834 baseIsPointer = fieldType.isPointer();
1835 baseElemSizeDenominator = baseIsPointer ?
"pointer" : baseJElemTypeName ;
1836 useGetCStringLength =
false;
1837 maxOneElement =
true;
1839 if( fieldType.arrayDimension() > 0 ) {
1840 final int[][] arrayLengthRes =
new int[1][];
1841 final boolean[] _useFixedArrayLen = {
false };
1842 elemCountExpr = getArrayArrayLengthExpr(fieldType.asArray(), fqStructFieldName, _useFixedArrayLen, arrayLengthRes);
1843 if(
null == elemCountExpr ) {
1844 final String msg =
"SKIP unsized array in struct: "+fqStructFieldName+
": "+fieldType.getSignature(
null).toString();
1845 unit.emitln(
" // "+msg);
1847 LOG.
log(WARNING, structCType.getASTLocusTag(), msg);
1851 constElemCount = _useFixedArrayLen[0];
1852 ownership = Ownership.Parent;
1853 staticElemCount = constElemCount;
1856 useGetCStringLength =
false;
1860 if(
null == _elemCountExpr && isString ) {
1861 useGetCStringLength =
true;
1862 unit.addTailCode(optStringMaxStrnlenCode);
1863 elemCountExpr =
"Buffers.strnlen(pString, _max_strnlen)+1";
1864 constElemCount =
false;
1865 ownership = Ownership.Java;
1866 staticElemCount = constElemCount;
1867 }
else if(
null == _elemCountExpr ) {
1868 useGetCStringLength =
false;
1869 elemCountExpr =
"0";
1870 constElemCount =
false;
1871 ownership = Ownership.Java;
1872 staticElemCount = constElemCount;
1875 useGetCStringLength =
false;
1876 elemCountExpr = _elemCountExpr;
1877 boolean _constElemCount =
false;
1878 boolean _staticElemCount =
false;
1882 Integer.parseInt(elemCountExpr);
1883 _constElemCount =
true;
1884 _staticElemCount =
true;
1885 }
catch (
final Exception e ) {}
1886 if( !_constElemCount ) {
1888 if( elemCountExpr.startsWith(
"get") && elemCountExpr.endsWith(
"()") ) {
1889 final String baseLenFieldName = elemCountExpr.substring(3, elemCountExpr.length()-2);
1890 String lenFieldName = CodeGenUtils.decapitalizeString( baseLenFieldName );
1891 Field lenField = structCType.getField(lenFieldName);
1892 if(
null == lenField ) {
1893 lenFieldName = baseLenFieldName;
1894 lenField = structCType.getField(lenFieldName);
1896 if(
null == lenField ) {
1897 throw new GlueGenException(
"Unable to creating array accessors for field \"" +
1898 fqStructFieldName +
"\", because elemCountExpr specify following getter \"" +
1899 elemCountExpr +
"\" and host structure doesn't contain following field \"" +
1900 CodeGenUtils.decapitalizeString( baseLenFieldName ) +
"\" or \"" +
1901 baseLenFieldName +
"\"",
1902 fieldType.getASTLocusTag());
1904 _constElemCount = lenField.getType().isConst();
1905 LOG.
log(INFO, structCType.getASTLocusTag(),
1906 unit.className+
": elemCountExpr "+elemCountExpr+
", lenFieldName "+lenFieldName+
" -> "+lenField.toString()+
", isConst "+_constElemCount);
1909 constElemCount = _constElemCount;
1910 if( constElemCount ) {
1911 ownership = Ownership.Native;
1913 ownership = Ownership.Mixed;
1915 staticElemCount = _staticElemCount;
1918 boolean _maxOneElement =
cfg.maxOneElement(fqStructFieldName);
1919 if( !_maxOneElement ) {
1921 _maxOneElement = 1 == Integer.parseInt(elemCountExpr);
1922 }
catch (
final Exception e ) {}
1924 maxOneElement = _maxOneElement;
1925 if( GlueGen.debug() ) {
1926 System.err.printf(
"SE.ac.%02d: ownership %s%n", (i+1), ownership);
1928 baseIsPointer = baseElemType.isPointer();
1929 isConstValue = baseElemType.isConst();
1930 if( baseIsPointer ) {
1931 baseJElemType = javaType(Long.TYPE);
1934 baseJElemType = typeToJavaType(baseElemType, machDescJava);
1935 }
catch (
final Exception e ) {
1936 throw new GlueGenException(
"Error occurred while creating array/pointer accessor for field \"" +
1937 fqStructFieldName +
"\", baseType "+baseElemType.getDebugString()+
", topType "+fieldType.getDebugString(),
1938 fieldType.getASTLocusTag(), e);
1941 baseJElemTypeName = baseJElemType.getName();
1942 isPrimitive = baseJElemType.isPrimitive() || baseElemType.isPrimitive() || baseElemType.isFunctionPointer();
1943 primElemFixedSize = isPrimitive ? baseElemType.getSize().hasFixedNativeSize() :
false;
1944 baseElemSizeDenominator = baseIsPointer ?
"pointer" : baseJElemTypeName ;
1946 if( GlueGen.debug() ) {
1947 System.err.printf(
"SE.ac.%02d: baseJElemType %s%n", (i+1), (
null != baseJElemType ? baseJElemType.getDebugString() :
null));
1950 final String primJElemTypeBufferName;
1951 final int primElemSize;
1952 final String primElemSizeExpr;
1953 final boolean isByteBuffer;
1955 final Class<? extends Buffer> primJElemTypeBufferClazz = Buffers.typeNameToBufferClass(baseJElemTypeName);
1956 if(
null == primJElemTypeBufferClazz ) {
1957 final String msg =
"Failed to map '"+baseJElemTypeName+
"' to Buffer class, field "+field+
", j-type "+baseJElemType;
1958 unit.emitln(
" // ERROR: "+msg);
1960 LOG.
log(SEVERE, structCType.getASTLocusTag(), msg);
1961 throw new InternalError(msg);
1963 primJElemTypeBufferName = primJElemTypeBufferClazz.getSimpleName();
1964 primElemSize = Buffers.sizeOfBufferElem(primJElemTypeBufferClazz);
1965 isByteBuffer =
null != primJElemTypeBufferClazz ? ByteBuffer.class.isAssignableFrom(primJElemTypeBufferClazz) :
false;
1966 if( primElemFixedSize ) {
1967 primElemSizeExpr = String.valueOf(primElemSize);
1969 primElemSizeExpr =
"md."+baseElemSizeDenominator+
"SizeInBytes()";
1972 primJElemTypeBufferName =
null;
1974 isByteBuffer =
false;
1975 primElemSizeExpr =
null;
1978 final String capitalFieldName = CodeGenUtils.capitalizeString(fieldName);
1979 final boolean ownElemCountHandling;
1980 final String getElemCountFuncExpr, setElemCountLengthFunc;
1981 if( constElemCount ) {
1982 ownElemCountHandling =
true;
1983 getElemCountFuncExpr =
"get"+capitalFieldName+
"ElemCount()";
1984 setElemCountLengthFunc =
null;
1986 if( useGetCStringLength ) {
1987 ownElemCountHandling =
true;
1988 getElemCountFuncExpr =
"get"+capitalFieldName+
"ElemCount()";
1989 setElemCountLengthFunc =
null;
1990 }
else if( elemCountExpr.startsWith(
"get") && elemCountExpr.endsWith(
"()") ) {
1991 ownElemCountHandling =
false;
1992 getElemCountFuncExpr = elemCountExpr;
1993 setElemCountLengthFunc =
"set" + elemCountExpr.substring(3, elemCountExpr.length()-2);
1995 ownElemCountHandling =
true;
1996 getElemCountFuncExpr =
"get"+capitalFieldName+
"ElemCount()";
1997 setElemCountLengthFunc =
"set"+capitalFieldName+
"ElemCount";
2000 if( GlueGen.debug() ) {
2001 System.err.printf(
"SE.ac.%02d: baseJElemTypeName %s%n", (i+1), baseJElemTypeName);
2002 System.err.printf(
"SE.ac.%02d: elemCountExpr: %s (const %b, ownership %s), ownArrayLenCpde %b, maxOneElement %b, "+
2003 "Primitive[is %b, aptr %b, buffer %s, fixedSize %b, elemSize %d, sizeDenom %s, sizeExpr %s, isByteBuffer %b], "+
2004 "isString[%b, only %b, strnlen %b], isPointer %b, isOpaque %b, constVal %b, immutableAccess %b%n",
2005 (i+1), elemCountExpr, constElemCount, ownership, ownElemCountHandling, maxOneElement,
2006 isPrimitive, baseIsPointer, primJElemTypeBufferName, primElemFixedSize, primElemSize, baseElemSizeDenominator, primElemSizeExpr, isByteBuffer,
2007 isString, isStringOnly, useGetCStringLength,
2008 isPointer, isOpaque, isConstValue, immutableAccess);
2014 if( ownElemCountHandling ) {
2015 if( constElemCount ) {
2016 if( !( isPrimitive && !isPointer && staticElemCount && maxOneElement ) ) {
2017 generateGetterSignature(unit, staticElemCount,
false, fieldName, fieldType, ownership,
"int", capitalFieldName+
"ElemCount",
null, constElemCount, maxOneElement, elemCountExpr, GetElemCountApiDocTail);
2018 unit.emitln(
" { return "+elemCountExpr+
"; }");
2020 }
else if( useGetCStringLength ) {
2021 generateGetterSignature(unit, staticElemCount,
false, fieldName, fieldType, ownership,
"int", capitalFieldName+
"ElemCount",
null, constElemCount, maxOneElement, elemCountExpr, GetElemCountApiDocTail);
2023 unit.emitln(
" final long pString = PointerBuffer.wrap( accessor.slice(" + fieldName+
"_offset[mdIdx], PointerBuffer.POINTER_SIZE) ).get(0);");
2024 unit.emitln(
" return 0 != pString ? "+elemCountExpr+
" : 0;");
2027 unit.emitln(
" private int _"+fieldName+
"ArrayLen = "+elemCountExpr+
"; // "+(constElemCount ?
"const" :
"initial")+
" array length");
2028 generateGetterSignature(unit, staticElemCount,
false, fieldName, fieldType, ownership,
"int", capitalFieldName+
"ElemCount",
null, constElemCount, maxOneElement, elemCountExpr, GetElemCountApiDocTail);
2029 unit.emitln(
" { return _"+fieldName+
"ArrayLen; }");
2030 if( !immutableAccess ) {
2031 generateSetterSignature(unit, MethodAccess.PRIVATE, staticElemCount,
false, fieldName, fieldType, ownership,
"void", capitalFieldName+
"ElemCount",
null,
"int",
2032 null, constElemCount, maxOneElement, elemCountExpr,
null,
null);
2033 unit.emitln(
" { _"+fieldName+
"ArrayLen = src; }");
2041 generateIsNullSignature(unit,
false, fieldName, fieldType, ownership, capitalFieldName, constElemCount, maxOneElement, elemCountExpr);
2043 unit.emitln(
" return 0 == PointerBuffer.wrap(getBuffer(), "+fieldName+
"_offset[mdIdx], 1).get(0);");
2046 if( !constElemCount && !immutableAccess ) {
2047 generateReleaseSignature(unit,
false, fieldName, fieldType, ownership, containingJTypeName, capitalFieldName, constElemCount, maxOneElement, elemCountExpr);
2049 unit.emitln(
" accessor.setLongAt("+fieldName+
"_offset[mdIdx], 0, md.pointerSizeInBytes()); // write nullptr");
2050 unit.emitln(
" _eb"+capitalFieldName+
" = null;");
2051 emitSetElemCount(unit, setElemCountLengthFunc,
"0", !useGetCStringLength, capitalFieldName, structCType,
" ");
2052 unit.emitln(
" return this;");
2054 unit.emitln(
" @SuppressWarnings(\"unused\")");
2055 if( baseIsPointer ) {
2056 unit.emitln(
" private PointerBuffer _eb"+capitalFieldName+
"; // cache new memory buffer ensuring same lifecycle");
2058 unit.emitln(
" private ElementBuffer _eb"+capitalFieldName+
"; // cache new memory buffer ensuring same lifecycle");
2065 if( immutableAccess ) {
2066 generateArrayFieldNote(unit,
" /** SKIP setter for immutable",
" */", fieldName, fieldType, ownership, constElemCount, maxOneElement, elemCountExpr,
false,
false);
2068 }
else if( isPointer && isConstValue && ( Ownership.Native == ownership || constElemCount ) ) {
2069 generateArrayFieldNote(unit,
" /** SKIP setter for constValue constElemCount Pointer w/ native ownership",
" */", fieldName, fieldType, ownership, constElemCount, maxOneElement, elemCountExpr,
false,
false);
2071 }
else if( !isPointer && isConstValue ) {
2072 generateArrayFieldNote(unit,
" /** SKIP setter for constValue Array",
" */", fieldName, fieldType, ownership, constElemCount, maxOneElement, elemCountExpr,
false,
false);
2074 }
else if( isPrimitive ) {
2076 if( maxOneElement ) {
2079 generateSetterSignature(unit, accessMod,
false,
false, fieldName, fieldType, ownership, containingJTypeName, capitalFieldName,
null, baseJElemTypeName,
2080 null, constElemCount, maxOneElement, elemCountExpr,
null,
null);
2081 if( isConstValue ) {
2083 if( Ownership.Native == ownership ) {
2084 throw new InternalError(
"Native ownership but adding potential memory-replacement for '"+fqStructFieldName+
"': "+fieldType.getSignature(
null).toString());
2087 if( baseIsPointer ) {
2088 unit.emitln(
" final PointerBuffer eb = PointerBuffer.allocateDirect(1);");
2089 unit.emitln(
" eb.put(0, src);");
2091 unit.emitln(
" final ElementBuffer eb = ElementBuffer.allocateDirect("+primElemSizeExpr+
", 1);");
2092 unit.emit (
" eb.getByteBuffer()");
2093 if( !isByteBuffer ) {
2094 unit.emit(
".as"+primJElemTypeBufferName+
"()");
2096 unit.emitln(
".put(0, src);");
2098 unit.emitln(
" eb.storeDirectAddress(getBuffer(), "+fieldName+
"_offset[mdIdx]);");
2099 unit.emitln(
" _eb"+capitalFieldName+
" = eb;");
2100 emitSetElemCount(unit, setElemCountLengthFunc,
"1", !useGetCStringLength, capitalFieldName, structCType,
" ");
2101 unit.emitln(
" return this;");
2105 unit.emitln(
" final int elemCount = "+getElemCountFuncExpr+
";");
2106 unit.emitln(
" if( 1 == elemCount ) {");
2107 if( baseIsPointer ) {
2108 unit.emitln(
" PointerBuffer.derefPointer(getBuffer(), "+fieldName+
"_offset[mdIdx], 1)");
2109 unit.emitln(
" .put(0, src);");
2111 unit.emitln(
" ElementBuffer.derefPointer("+primElemSizeExpr+
", getBuffer(), "+fieldName+
"_offset[mdIdx], 1)");
2112 unit.emit (
" .getByteBuffer()");
2113 if( !isByteBuffer ) {
2114 unit.emit(
".as"+primJElemTypeBufferName+
"()");
2116 unit.emitln(
".put(0, src);");
2118 unit.emitln(
" } else {");
2119 if( constElemCount || Ownership.Native == ownership ) {
2120 unit.emitln(
" throw new RuntimeException(\"Primitive '"+fieldName+
"' of "+ownership+
" ownership and maxOneElement has "
2121 +(constElemCount?
"const":
"")+
"elemCount \"+elemCount);");
2123 unit.emitln(
" return this;");
2126 if( baseIsPointer ) {
2127 unit.emitln(
" final PointerBuffer eb = PointerBuffer.allocateDirect(1);");
2128 unit.emitln(
" eb.put(0, src);");
2130 unit.emitln(
" final ElementBuffer eb = ElementBuffer.allocateDirect("+primElemSizeExpr+
", 1);");
2131 unit.emit (
" eb.getByteBuffer()");
2132 if( !isByteBuffer ) {
2133 unit.emit(
".as"+primJElemTypeBufferName+
"()");
2135 unit.emitln(
".put(0, src);");
2137 unit.emitln(
" eb.storeDirectAddress(getBuffer(), "+fieldName+
"_offset[mdIdx]);");
2138 unit.emitln(
" _eb"+capitalFieldName+
" = eb;");
2139 emitSetElemCount(unit, setElemCountLengthFunc,
"1", !useGetCStringLength, capitalFieldName, structCType,
" ");
2141 unit.emitln(
" return this;");
2146 generateSetterSignature(unit, accessMod,
false,
false, fieldName, fieldType, ownership, containingJTypeName, capitalFieldName,
null, baseJElemTypeName,
2147 null, constElemCount, maxOneElement, elemCountExpr,
null,
null);
2149 if( baseIsPointer ) {
2150 unit.emitln(
" PointerBuffer.wrap(getBuffer(), "+fieldName+
"_offset[mdIdx], 1).put(0, src);");
2152 unit.emitln(
" ElementBuffer.wrap("+primElemSizeExpr+
", getBuffer(), "+fieldName+
"_offset[mdIdx], 1)");
2153 unit.emit (
" .getByteBuffer()");
2154 if( !isByteBuffer ) {
2155 unit.emit(
".as"+primJElemTypeBufferName+
"()");
2157 unit.emitln(
".put(0, src);");
2159 unit.emitln(
" return this;");
2165 boolean doneString =
false;
2167 if( isString && isByteBuffer && isPointer ) {
2169 generateSetterSignature(unit, accessMod,
false,
false, fieldName, fieldType, ownership, containingJTypeName, capitalFieldName,
null,
"String",
2170 null, constElemCount, maxOneElement, elemCountExpr,
null,
null);
2172 unit.emitln(
" final byte[] srcBytes = src.getBytes(_charset);");
2173 if( constElemCount || Ownership.Native == ownership ) {
2174 unit.emitln(
" final int elemCount = "+getElemCountFuncExpr+
";");
2175 unit.emitln(
" if( srcBytes.length + 1 != elemCount ) { throw new IllegalArgumentException(\"strlen+1 \"+(srcBytes.length+1)+\" != "
2176 +(constElemCount?
"const":
"")+
" elemCount \"+elemCount+\" of "+ownership+
" ownership\"); };");
2177 unit.emitln(
" final ElementBuffer eb = ElementBuffer.derefPointer("+primElemSizeExpr+
", getBuffer(), "+fieldName+
"_offset[mdIdx], elemCount);");
2179 unit.emitln(
" final ElementBuffer eb = ElementBuffer.allocateDirect("+primElemSizeExpr+
", srcBytes.length + 1);");
2181 unit.emitln(
" eb.getByteBuffer().put(srcBytes, 0, srcBytes.length).put((byte)0).rewind(); // w/ EOS");
2182 if( !constElemCount ) {
2183 unit.emitln(
" eb.storeDirectAddress(getBuffer(), "+fieldName+
"_offset[mdIdx]);");
2184 unit.emitln(
" _eb"+capitalFieldName+
" = eb;");
2185 emitSetElemCount(unit, setElemCountLengthFunc,
"srcBytes.length + 1", !useGetCStringLength, capitalFieldName, structCType,
" ");
2187 unit.emitln(
" return this;");
2192 if( doneString && isStringOnly ) {
2193 generateArrayFieldNote(unit,
" /** SKIP setter for String alternative (ByteBuffer)",
" */", fieldName, fieldType, ownership, constElemCount, maxOneElement, elemCountExpr,
false,
false);
2194 }
else if( isConstValue ) {
2197 generateSetterSignature(unit, accessMod,
false,
false, fieldName, fieldType, ownership, containingJTypeName, capitalFieldName,
null,
2198 baseJElemTypeName+
"[]", SetReplaceArrayArgsPost, constElemCount, maxOneElement, elemCountExpr, SetReplaceArrayApiDocDetail, SetReplaceArrayApiDocArgs);
2199 if( Ownership.Native == ownership ) {
2200 throw new InternalError(
"Native ownership but adding potential memory-replacement for '"+fqStructFieldName+
"': "+fieldType.getSignature(
null).toString());
2204 if( baseIsPointer ) {
2205 unit.emitln(
" final PointerBuffer eb = PointerBuffer.allocateDirect(length);");
2207 unit.emitln(
" final ElementBuffer eb = ElementBuffer.allocateDirect("+primElemSizeExpr+
", length);");
2209 unit.emitln(
" eb.put(src, srcPos, 0, length).storeDirectAddress(getBuffer(), "+fieldName+
"_offset[mdIdx]);");
2210 unit.emitln(
" _eb"+capitalFieldName+
" = eb;");
2211 emitSetElemCount(unit, setElemCountLengthFunc,
"length", !useGetCStringLength, capitalFieldName, structCType,
" ");
2212 unit.emitln(
" return this;");
2215 }
else if( constElemCount || !isPointer ) {
2216 generateSetterSignature(unit, accessMod,
false,
false, fieldName, fieldType, ownership, containingJTypeName, capitalFieldName,
null,
2217 baseJElemTypeName+
"[]", SetSubArrayArgsPost, constElemCount, maxOneElement, elemCountExpr, SetSubArrayApiDocDetail, SetSubArrayApiDocArgs);
2220 unit.emitln(
" final int elemCount = "+getElemCountFuncExpr+
";");
2222 if( baseIsPointer ) {
2224 unit.emitln(
" final PointerBuffer eb = PointerBuffer.derefPointer(getBuffer(), "+fieldName+
"_offset[mdIdx], elemCount);");
2226 unit.emitln(
" final PointerBuffer eb = PointerBuffer.wrap(getBuffer(), "+fieldName+
"_offset[mdIdx], elemCount);");
2230 unit.emitln(
" final ElementBuffer eb = ElementBuffer.derefPointer("+primElemSizeExpr+
", getBuffer(), "+fieldName+
"_offset[mdIdx], elemCount);");
2232 unit.emitln(
" final ElementBuffer eb = ElementBuffer.wrap("+primElemSizeExpr+
", getBuffer(), "+fieldName+
"_offset[mdIdx], elemCount);");
2235 unit.emitln(
" eb.put(src, srcPos, destPos, length);");
2236 unit.emitln(
" return this;");
2239 generateSetterSignature(unit, accessMod,
false,
false, fieldName, fieldType, ownership, containingJTypeName, capitalFieldName, SetArrayArgsPre,
2240 baseJElemTypeName+
"[]", SetArrayArgsPost, constElemCount, maxOneElement, elemCountExpr, SetArrayApiDocDetail, SetArrayApiDocArgs);
2241 if( Ownership.Native == ownership ) {
2242 throw new InternalError(
"Native ownership but adding potential memory-replacement for '"+fqStructFieldName+
"': "+fieldType.getSignature(
null).toString());
2246 unit.emitln(
" final int elemCount = "+getElemCountFuncExpr+
";");
2247 unit.emitln(
" if( subset || destPos + length == elemCount ) {");
2249 if( baseIsPointer ) {
2250 unit.emitln(
" final PointerBuffer eb = PointerBuffer.derefPointer(getBuffer(), "+fieldName+
"_offset[mdIdx], elemCount);");
2252 unit.emitln(
" final ElementBuffer eb = ElementBuffer.derefPointer("+primElemSizeExpr+
", getBuffer(), "+fieldName+
"_offset[mdIdx], elemCount);");
2254 unit.emitln(
" eb.put(src, srcPos, destPos, length);");
2255 unit.emitln(
" } else {");
2256 unit.emitln(
" final int newElemCount = destPos + length;");
2257 if( baseIsPointer ) {
2258 unit.emitln(
" final PointerBuffer eb = PointerBuffer.allocateDirect(newElemCount);");
2259 unit.emitln(
" if( 0 < destPos ) {");
2260 unit.emitln(
" final PointerBuffer pre_eb = PointerBuffer.derefPointer(getBuffer(), "+fieldName+
"_offset[mdIdx], elemCount);");
2261 unit.emitln(
" pre_eb.position(0).limit(destPos);");
2262 unit.emitln(
" eb.put(pre_eb).rewind();");
2265 unit.emitln(
" final ElementBuffer eb = ElementBuffer.allocateDirect("+primElemSizeExpr+
", newElemCount);");
2266 unit.emitln(
" if( 0 < destPos ) {");
2267 unit.emitln(
" final ElementBuffer pre_eb = ElementBuffer.derefPointer("+primElemSizeExpr+
", getBuffer(), "+fieldName+
"_offset[mdIdx], elemCount);");
2268 unit.emitln(
" eb.put(pre_eb.getByteBuffer(), 0, 0, destPos);");
2271 unit.emitln(
" eb.put(src, srcPos, destPos, length);");
2272 unit.emitln(
" eb.storeDirectAddress(getBuffer(), "+fieldName+
"_offset[mdIdx]);");
2273 unit.emitln(
" _eb"+capitalFieldName+
" = eb;");
2274 emitSetElemCount(unit, setElemCountLengthFunc,
"newElemCount", !useGetCStringLength, capitalFieldName, structCType,
" ");
2276 unit.emitln(
" return this;");
2283 if( maxOneElement ) {
2286 generateSetterSignature(unit, accessMod,
false,
false, fieldName, fieldType, ownership, containingJTypeName, capitalFieldName,
null, baseJElemTypeName,
2287 null, constElemCount, maxOneElement, elemCountExpr,
null,
null);
2288 if( isConstValue ) {
2290 if( Ownership.Native == ownership ) {
2291 throw new InternalError(
"Native ownership but adding potential memory-replacement for '"+fqStructFieldName+
"': "+fieldType.getSignature(
null).toString());
2294 unit.emitln(
" final ElementBuffer eb = ElementBuffer.allocateDirect("+baseJElemTypeName+
".size(), 1);");
2295 unit.emitln(
" eb.put(0, src.getBuffer());");
2296 unit.emitln(
" eb.storeDirectAddress(getBuffer(), "+fieldName+
"_offset[mdIdx]);");
2297 unit.emitln(
" _eb"+capitalFieldName+
" = eb;");
2298 emitSetElemCount(unit, setElemCountLengthFunc,
"1", !useGetCStringLength, capitalFieldName, structCType,
" ");
2299 unit.emitln(
" return this;");
2303 unit.emitln(
" final int elemCount = "+getElemCountFuncExpr+
";");
2304 unit.emitln(
" if( 1 == elemCount ) {");
2305 unit.emitln(
" ElementBuffer.derefPointer("+baseJElemTypeName+
".size(), getBuffer(), "+fieldName+
"_offset[mdIdx], 1)");
2306 unit.emitln(
" .put(0, src.getBuffer());");
2307 unit.emitln(
" } else {");
2308 if( constElemCount || Ownership.Native == ownership ) {
2309 unit.emitln(
" throw new RuntimeException(\"Primitive '"+fieldName+
"' of "+ownership+
" ownership and maxOneElement has "
2310 +(constElemCount?
"const":
"")+
"elemCount \"+elemCount);");
2312 unit.emitln(
" return this;");
2315 unit.emitln(
" final ElementBuffer eb = ElementBuffer.allocateDirect("+baseJElemTypeName+
".size(), 1);");
2316 unit.emitln(
" eb.put(0, src.getBuffer());");
2317 unit.emitln(
" eb.storeDirectAddress(getBuffer(), "+fieldName+
"_offset[mdIdx]);");
2318 unit.emitln(
" _eb"+capitalFieldName+
" = eb;");
2319 emitSetElemCount(unit, setElemCountLengthFunc,
"1", !useGetCStringLength, capitalFieldName, structCType,
" ");
2321 unit.emitln(
" return this;");
2325 }
else if( !isConstValue ) {
2326 generateSetterSignature(unit, accessMod,
false,
false, fieldName, fieldType, ownership, containingJTypeName, capitalFieldName,
null, baseJElemTypeName,
2327 null, constElemCount, maxOneElement, elemCountExpr,
null,
null);
2329 unit.emitln(
" ElementBuffer.wrap("+baseJElemTypeName+
".size(), getBuffer(), "+fieldName+
"_offset[mdIdx], 1)");
2330 unit.emitln(
" .put(0, src.getBuffer());");
2331 unit.emitln(
" return this;");
2337 if( isConstValue ) {
2340 generateSetterSignature(unit, accessMod,
false,
false, fieldName, fieldType, ownership, containingJTypeName, capitalFieldName,
null,
2341 baseJElemTypeName+
"[]", SetReplaceArrayArgsPost, constElemCount, maxOneElement, elemCountExpr, SetReplaceArrayApiDocDetail, SetReplaceArrayApiDocArgs);
2342 if( Ownership.Native == ownership ) {
2343 throw new InternalError(
"Native ownership but adding potential memory-replacement for '"+fqStructFieldName+
"': "+fieldType.getSignature(
null).toString());
2346 unit.emitln(SetReplaceArrayArgsCheck);
2347 unit.emitln(
" final ElementBuffer eb = ElementBuffer.allocateDirect("+baseJElemTypeName+
".size(), length);");
2348 unit.emitln(
" for(int i=0; i<length; ++i) {");
2349 unit.emitln(
" eb.put(i, src[srcPos+i].getBuffer());");
2351 unit.emitln(
" eb.storeDirectAddress(getBuffer(), "+fieldName+
"_offset[mdIdx]);");
2352 unit.emitln(
" _eb"+capitalFieldName+
" = eb;");
2353 emitSetElemCount(unit, setElemCountLengthFunc,
"length", !useGetCStringLength, capitalFieldName, structCType,
" ");
2354 unit.emitln(
" return this;");
2357 }
else if( constElemCount || !isPointer ) {
2358 generateSetterSignature(unit, accessMod,
false,
false, fieldName, fieldType, ownership, containingJTypeName, capitalFieldName,
null,
2359 baseJElemTypeName+
"[]", SetSubArrayArgsPost, constElemCount, maxOneElement, elemCountExpr, SetSubArrayApiDocDetail, SetSubArrayApiDocArgs);
2361 unit.emitln(SetSubArrayArgsCheck);
2362 unit.emitln(
" final int elemCount = "+getElemCountFuncExpr+
";");
2363 unit.emitln(
" if( destPos + length > elemCount ) { throw new IndexOutOfBoundsException(\"destPos \"+destPos+\" + length \"+length+\" > elemCount \"+elemCount); };");
2365 unit.emitln(
" final ElementBuffer eb = ElementBuffer.derefPointer("+baseJElemTypeName+
".size(), getBuffer(), "+fieldName+
"_offset[mdIdx], elemCount);");
2367 unit.emitln(
" final ElementBuffer eb = ElementBuffer.wrap("+baseJElemTypeName+
".size(), getBuffer(), "+fieldName+
"_offset[mdIdx], elemCount);");
2369 unit.emitln(
" for(int i=0; i<length; ++i) {");
2370 unit.emitln(
" eb.put(destPos+i, src[srcPos+i].getBuffer());");
2372 unit.emitln(
" return this;");
2375 generateSetterSignature(unit, accessMod,
false,
false, fieldName, fieldType, ownership, containingJTypeName, capitalFieldName, SetArrayArgsPre,
2376 baseJElemTypeName+
"[]", SetArrayArgsPost, constElemCount, maxOneElement, elemCountExpr, SetArrayApiDocDetail, SetArrayApiDocArgs);
2377 if( Ownership.Native == ownership ) {
2378 throw new InternalError(
"Native ownership but adding potential memory-replacement for '"+fqStructFieldName+
"': "+fieldType.getSignature(
null).toString());
2381 unit.emitln(SetArrayArgsCheck);
2382 unit.emitln(
" final int elemCount = "+getElemCountFuncExpr+
";");
2383 unit.emitln(
" if( subset || destPos + length == elemCount ) {");
2384 unit.emitln(
" if( destPos + length > elemCount ) { throw new IndexOutOfBoundsException(\"subset \"+subset+\", destPos \"+destPos+\" + length \"+length+\" > elemCount \"+elemCount); };");
2385 unit.emitln(
" final ElementBuffer eb = ElementBuffer.derefPointer("+baseJElemTypeName+
".size(), getBuffer(), "+fieldName+
"_offset[mdIdx], elemCount);");
2386 unit.emitln(
" for(int i=0; i<length; ++i) {");
2387 unit.emitln(
" eb.put(destPos+i, src[srcPos+i].getBuffer());");
2389 unit.emitln(
" } else {");
2390 unit.emitln(
" final int newElemCount = destPos + length;");
2391 unit.emitln(
" final ElementBuffer eb = ElementBuffer.allocateDirect("+baseJElemTypeName+
".size(), newElemCount);");
2393 unit.emitln(
" if( 0 < destPos ) {");
2394 unit.emitln(
" final ElementBuffer pre_eb = ElementBuffer.derefPointer("+baseJElemTypeName+
".size(), getBuffer(), "+fieldName+
"_offset[mdIdx], elemCount);");
2395 unit.emitln(
" eb.put(pre_eb.getByteBuffer(), 0, 0, destPos);");
2397 unit.emitln(
" for(int i=0; i<length; ++i) {");
2398 unit.emitln(
" eb.put(destPos+i, src[srcPos+i].getBuffer());");
2400 unit.emitln(
" eb.storeDirectAddress(getBuffer(), "+fieldName+
"_offset[mdIdx]);");
2401 unit.emitln(
" _eb"+capitalFieldName+
" = eb;");
2402 emitSetElemCount(unit, setElemCountLengthFunc,
"newElemCount", !useGetCStringLength, capitalFieldName, structCType,
" ");
2404 unit.emitln(
" return this;");
2408 if( !isConstValue ) {
2409 generateSetterSignature(unit, accessMod,
false,
false, fieldName, fieldType, ownership, containingJTypeName, capitalFieldName,
"final int destPos", baseJElemTypeName,
2410 null, constElemCount, maxOneElement, elemCountExpr,
null,
null);
2412 unit.emitln(
" final int elemCount = "+getElemCountFuncExpr+
";");
2413 unit.emitln(
" if( destPos + 1 > elemCount ) { throw new IndexOutOfBoundsException(\"destPos \"+destPos+\" + 1 > elemCount \"+elemCount); };");
2415 unit.emitln(
" ElementBuffer.derefPointer("+baseJElemTypeName+
".size(), getBuffer(), "+fieldName+
"_offset[mdIdx], elemCount)");
2417 unit.emitln(
" ElementBuffer.wrap("+baseJElemTypeName+
".size(), getBuffer(), "+fieldName+
"_offset[mdIdx], elemCount)");
2419 unit.emitln(
" .put(destPos, src.getBuffer());");
2420 unit.emitln(
" return this;");
2430 if( maxOneElement ) {
2431 generateGetterSignature(unit,
false,
false, fieldName, fieldType, ownership, baseJElemTypeName, capitalFieldName,
2432 null, constElemCount, maxOneElement, elemCountExpr, GetElemValueApiDocTail);
2434 if( baseIsPointer ) {
2436 unit.emit (
" return PointerBuffer.derefPointer(getBuffer(), "+fieldName+
"_offset[mdIdx], 1)");
2438 unit.emit (
" return PointerBuffer.wrap(getBuffer(), "+fieldName+
"_offset[mdIdx], 1)");
2442 unit.emitln(
" return ElementBuffer.derefPointer("+primElemSizeExpr+
", getBuffer(), "+fieldName+
"_offset[mdIdx], 1)");
2444 unit.emitln(
" return ElementBuffer.wrap("+primElemSizeExpr+
", getBuffer(), "+fieldName+
"_offset[mdIdx], 1)");
2446 unit.emit (
" .getByteBuffer()");
2447 if( !isByteBuffer ) {
2448 unit.emit(
".as"+primJElemTypeBufferName+
"()");
2451 unit.emitln(
".get(0);");
2455 boolean doneString =
false;
2456 if( isString && isByteBuffer ) {
2457 generateGetterSignature(unit,
false,
false, fieldName, fieldType, ownership,
"String", capitalFieldName+(isStringOnly?
"":
"AsString"),
2458 null, constElemCount, maxOneElement, elemCountExpr, GetElemValueApiDocTail);
2460 unit.emitln(
" final int elemCount = "+getElemCountFuncExpr+
";");
2462 unit.emitln(
" final ByteBuffer bb = ElementBuffer.derefPointer("+primElemSizeExpr+
", getBuffer(), "+fieldName+
"_offset[mdIdx], elemCount).getByteBuffer();");
2464 unit.emitln(
" final ByteBuffer bb = ElementBuffer.wrap("+primElemSizeExpr+
", getBuffer(), "+fieldName+
"_offset[mdIdx], elemCount).getByteBuffer();");
2466 unit.emitln(
" final byte[] ba = new byte[elemCount];");
2467 unit.emitln(
" int i = -1;");
2468 unit.emitln(
" while( ++i < elemCount ) {");
2469 unit.emitln(
" ba[i] = bb.get(i);");
2470 unit.emitln(
" if( (byte)0 == ba[i] ) break;");
2472 unit.emitln(
" return new String(ba, 0, i, _charset);");
2477 if( doneString && isStringOnly ) {
2478 generateArrayFieldNote(unit,
" /** SKIP getter for String alternative (ByteBuffer)",
" */", fieldName, fieldType, ownership, constElemCount, maxOneElement, elemCountExpr,
false,
false);
2480 }
else if( !baseIsPointer ) {
2481 generateGetterSignature(unit,
false,
false, fieldName, fieldType, ownership, primJElemTypeBufferName, capitalFieldName,
2482 null, constElemCount, maxOneElement, elemCountExpr, GetElemValueApiDocTail);
2485 unit.emitln(
" return ElementBuffer.derefPointer("+primElemSizeExpr+
", getBuffer(), "+fieldName+
"_offset[mdIdx], "+getElemCountFuncExpr+
")");
2487 unit.emitln(
" return ElementBuffer.wrap("+primElemSizeExpr+
", getBuffer(), "+fieldName+
"_offset[mdIdx], "+getElemCountFuncExpr+
")");
2489 unit.emit (
" .getByteBuffer()");
2490 if( !isByteBuffer ) {
2491 unit.emit(
".as"+primJElemTypeBufferName+
"()");
2498 generateGetterSignature(unit,
false,
false, fieldName, fieldType, ownership, baseJElemTypeName+
"[]", capitalFieldName,
2499 "final int srcPos, "+baseJElemTypeName+
" dest[], "+GetArrayArgs, constElemCount, maxOneElement, elemCountExpr, GetElemValueApiDocTail);
2501 unit.emitln(
" final int elemCount = "+getElemCountFuncExpr+
";");
2502 if( baseIsPointer ) {
2504 unit.emit (
" PointerBuffer.derefPointer(getBuffer(), "+fieldName+
"_offset[mdIdx], elemCount)");
2506 unit.emit (
" PointerBuffer.wrap(getBuffer(), "+fieldName+
"_offset[mdIdx], elemCount)");
2510 unit.emit(
" ElementBuffer.derefPointer("+primElemSizeExpr+
", getBuffer(), "+fieldName+
"_offset[mdIdx], elemCount)");
2512 unit.emit(
" ElementBuffer.wrap("+primElemSizeExpr+
", getBuffer(), "+fieldName+
"_offset[mdIdx], elemCount)");
2515 unit.emitln(
".get(srcPos, dest, destPos, length);");
2516 unit.emitln(
" return dest;");
2523 if( maxOneElement ) {
2524 generateGetterSignature(unit,
false,
false, fieldName, fieldType, ownership, baseJElemTypeName, capitalFieldName,
2525 null, constElemCount, maxOneElement, elemCountExpr, GetElemValueApiDocTail);
2527 unit.emitln(
" return "+baseJElemTypeName+
".create(");
2529 unit.emitln(
" ElementBuffer.derefPointer("+baseJElemTypeName+
".size(), getBuffer(), "+fieldName+
"_offset[mdIdx], 1).getByteBuffer() );");
2531 unit.emitln(
" ElementBuffer.wrap("+baseJElemTypeName+
".size(), getBuffer(), "+fieldName+
"_offset[mdIdx], 1).getByteBuffer() );");
2536 generateGetterSignature(unit,
false,
false, fieldName, fieldType, ownership, baseJElemTypeName+
"[]", capitalFieldName,
2537 "final int srcPos, "+baseJElemTypeName+
" dest[], "+GetArrayArgs, constElemCount, maxOneElement, elemCountExpr, GetElemValueApiDocTail);
2539 unit.emitln(GetArrayArgsCheck);
2540 unit.emitln(
" final int elemCount = "+getElemCountFuncExpr+
";");
2541 unit.emitln(
" if( srcPos + length > elemCount ) { throw new IndexOutOfBoundsException(\"srcPos \"+srcPos+\" + length \"+length+\" > elemCount \"+elemCount); };");
2543 unit.emitln(
" final ElementBuffer eb = ElementBuffer.derefPointer("+baseJElemTypeName+
".size(), getBuffer(), "+fieldName+
"_offset[mdIdx], elemCount);");
2545 unit.emitln(
" final ElementBuffer eb = ElementBuffer.wrap("+baseJElemTypeName+
".size(), getBuffer(), "+fieldName+
"_offset[mdIdx], elemCount);");
2547 unit.emitln(
" for(int i=0; i<length; ++i) {");
2548 unit.emitln(
" dest[destPos+i] = "+baseJElemTypeName+
".create( eb.slice(srcPos+i, 1) );");
2550 unit.emitln(
" return dest;");
2556 private void emitSetElemCount(
final JavaCodeUnit unit,
final String setElemCountFunc,
final String newElemCountExpr,
final boolean mandatory,
final String capitalFieldName,
final Type structCType,
final String indentation) {
2557 if(
null != setElemCountFunc ) {
2558 unit.emitln(indentation+setElemCountFunc+
"( "+newElemCountExpr+
" );");
2559 }
else if( mandatory ) {
2560 final String msg =
"Missing set"+capitalFieldName+
"ElemCount( "+newElemCountExpr+
" )";
2561 unit.emitln(indentation+
"// ERROR: "+msg);
2563 LOG.
log(SEVERE, structCType.getASTLocusTag(), msg);
2564 throw new RuntimeException(msg);
2568 private JavaType typeToJavaType(
final Type cType,
final MachineDataInfo curMachDesc) {
2569 final JavaType jt = typeToJavaTypeImpl(cType, curMachDesc);
2570 LOG.
log(FINE, cType.getASTLocusTag(),
"typeToJavaType: {0} -> {1}", cType, jt);
2573 private boolean isJNIEnvPointer(
final Type cType) {
2574 final PointerType opt = cType.asPointer();
2575 return (opt !=
null) &&
2576 (opt.getTargetType().getName() !=
null) &&
2577 (opt.getTargetType().getName().equals(
"JNIEnv"));
2579 private JavaType typeToJavaTypeImpl(
final Type cType,
final MachineDataInfo curMachDesc) {
2581 if( isJNIEnvPointer(cType) ) {
2582 return JavaType.createForJNIEnv();
2588 boolean isPointerPointer =
false;
2589 if (cType.pointerDepth() > 0 || cType.arrayDimension() > 0) {
2591 final Type targetType = cType.getArrayBaseOrPointerTargetType();
2592 if (cType.pointerDepth() == 2 || cType.arrayDimension() == 2) {
2596 if (targetType.isPointer()) {
2597 isPointerPointer =
true;
2598 if( GlueGen.debug() ) {
2600 final Type bottomType = targetType.asPointer().getTargetType();
2601 LOG.
log(INFO, cType.getASTLocusTag(),
"Opaque Type: {0}, targetType: {1}, bottomType: {2} is ptr-ptr",
2602 cType, targetType, bottomType);
2607 if( !isPointerPointer ) {
2608 return info.javaType();
2612 if (cType.isInt() || cType.isEnum()) {
2613 switch ((
int) cType.getSize(curMachDesc)) {
2614 case 1:
return javaType(Byte.TYPE);
2615 case 2:
return javaType(Short.TYPE);
2616 case 4:
return javaType(Integer.TYPE);
2617 case 8:
return javaType(Long.TYPE);
2618 default:
throw new GlueGenException(
"Unknown integer type of size " +
2619 cType.getSize(curMachDesc) +
" and name " + cType.getName(),
2620 cType.getASTLocusTag());
2622 }
else if (cType.isFloat()) {
2623 return javaType(Float.TYPE);
2624 }
else if (cType.isDouble()) {
2625 return javaType(Double.TYPE);
2626 }
else if (cType.isVoid()) {
2627 return javaType(Void.TYPE);
2628 }
else if (cType.pointerDepth() > 0 || cType.arrayDimension() > 0) {
2630 final Type targetType = cType.getArrayBaseOrPointerTargetType();
2635 if (cType.pointerDepth() == 1 || cType.arrayDimension() == 1) {
2636 if (targetType.isVoid()) {
2637 return JavaType.createForCVoidPointer();
2638 }
else if( targetType.isFunctionPointer() ) {
2639 return javaType(Long.TYPE);
2640 }
else if (targetType.isInt()) {
2641 final SizeThunk targetSizeThunk = targetType.getSize();
2642 if(
null != targetSizeThunk && SizeThunk.POINTER == targetSizeThunk ) {
2644 return JavaType.forNIOPointerBufferClass();
2646 switch ((
int) targetType.getSize(curMachDesc)) {
2647 case 1:
return JavaType.createForCCharPointer();
2648 case 2:
return JavaType.createForCShortPointer();
2649 case 4:
return JavaType.createForCInt32Pointer();
2650 case 8:
return JavaType.createForCInt64Pointer();
2651 default:
throw new GlueGenException(
"Unknown integer array type of size " +
2652 cType.getSize(curMachDesc) +
" and name " + cType.getName()+
", "+cType.getDebugString()+
2653 ", target "+targetType.getDebugString(),
2654 cType.getASTLocusTag());
2656 }
else if (targetType.isFloat()) {
2657 return JavaType.createForCFloatPointer();
2658 }
else if (targetType.isDouble()) {
2659 return JavaType.createForCDoublePointer();
2660 }
else if (targetType.isCompound()) {
2661 if (cType.isArray()) {
2662 return JavaType.createForCArray(targetType);
2665 if (cType.getName() !=
null &&
2666 cType.getName().equals(
"jobject")) {
2667 return javaType(java.lang.Object.class);
2671 if( !targetType.isTypedef() && cType.isTypedef() ) {
2673 name = cType.getName();
2676 name = targetType.getName();
2677 if(
null == name ) {
2679 name = cType.getName();
2681 throw new GlueGenException(
"Couldn't find a proper type name for pointer type " + cType.getDebugString()+
2682 ", target "+targetType.getDebugString(),
2683 cType.getASTLocusTag());
2689 throw new GlueGenException(
"Don't know how to convert pointer/array type " +
2690 cType.getDebugString() +
", target "+targetType.getDebugString(),
2691 cType.getASTLocusTag());
2696 else if (cType.pointerDepth() == 2 || cType.arrayDimension() == 2) {
2701 if (targetType.isPointer()) {
2703 bottomType = targetType.asPointer().getTargetType();
2704 if( GlueGen.debug() ) {
2705 LOG.
log(INFO, cType.getASTLocusTag(),
"typeToJavaType(ptr-ptr): {0}, targetType: {1}, bottomType: {2}",
2706 cType.getDebugString(), targetType.getDebugString(), bottomType.getDebugString());
2708 return JavaType.forNIOPointerBufferClass();
2709 }
else if(targetType.isArray()) {
2711 bottomType = targetType.getBaseType();
2712 if( GlueGen.debug() ) {
2713 LOG.
log(INFO, cType.getASTLocusTag(),
"typeToJavaType(ptr-ptr.array): {0}, targetType: {1}, bottomType: {2}",
2714 cType.getDebugString(), targetType.getDebugString(), bottomType.getDebugString());
2717 bottomType = targetType;
2718 if( GlueGen.debug() ) {
2719 LOG.
log(INFO, cType.getASTLocusTag(),
"typeToJavaType(ptr-ptr.primitive): {0}, targetType: {1}, bottomType: {2}",
2720 cType.getDebugString(), targetType.getDebugString(), bottomType.getDebugString());
2727 if (bottomType.isPrimitive()) {
2728 if (bottomType.isInt()) {
2729 switch ((
int) bottomType.getSize(curMachDesc)) {
2730 case 1:
return javaType(ArrayTypes.byteBufferArrayClass);
2731 case 2:
return javaType(ArrayTypes.shortBufferArrayClass);
2732 case 4:
return javaType(ArrayTypes.intBufferArrayClass);
2733 case 8:
return javaType(ArrayTypes.longBufferArrayClass);
2734 default:
throw new GlueGenException(
"Unknown two-dimensional integer array type of element size " +
2735 bottomType.getSize(curMachDesc) +
" and name " + bottomType.getName()+
", "+bottomType.getDebugString(),
2736 bottomType.getASTLocusTag());
2738 }
else if (bottomType.isFloat()) {
2739 return javaType(ArrayTypes.floatBufferArrayClass);
2740 }
else if (bottomType.isDouble()) {
2741 return javaType(ArrayTypes.doubleBufferArrayClass);
2743 throw new GlueGenException(
"Unexpected primitive type " + bottomType.getDebugString() +
2744 " in two-dimensional array", bottomType.getASTLocusTag());
2746 }
else if (bottomType.isVoid()) {
2747 return javaType(ArrayTypes.bufferArrayClass);
2748 }
else if (targetType.isPointer() && (targetType.pointerDepth() == 1) &&
2749 targetType.asPointer().getTargetType().isCompound()) {
2751 return JavaType.createForCArray(bottomType);
2753 throw new GlueGenException(
2754 "Could not convert C type " + cType.getDebugString() +
" " +
2755 "to appropriate Java type; need to add more support for " +
2756 "depth=2 pointer/array types [debug info: targetType=" +
2757 targetType.getDebugString() +
"]", cType.getASTLocusTag());
2761 throw new GlueGenException(
2762 "Could not convert C pointer/array " + cType.getDebugString() +
" to " +
2763 "appropriate Java type; types with pointer/array depth " +
2764 "greater than 2 are not yet supported [debug info: " +
2765 "pointerDepth=" + cType.pointerDepth() +
" arrayDimension=" +
2766 cType.arrayDimension() +
" targetType=" + targetType.getDebugString() +
"]",
2767 cType.getASTLocusTag());
2770 }
else if( cType.isCompound() ) {
2771 String name = cType.getName();
2773 name = cType.asCompound().getStructName();
2775 throw new GlueGenException(
"Couldn't find a proper type name for pointer type " + cType.getDebugString(),
2776 cType.getASTLocusTag());
2781 throw new GlueGenException(
2782 "Could not convert C type " + cType.getDebugString() +
" (class " +
2783 cType.getClass().getName() +
") to appropriate Java type",
2784 cType.getASTLocusTag());
2788 private StructLayout getLayout() {
2789 if (layout ==
null) {
2790 layout = StructLayout.
create(0);
2802 return new CCodeUnit(filename, cUnitName,
this);
2812 protected JavaCodeUnit openJavaUnit(
final String filename,
final String packageName,
final String simpleClassName)
throws IOException {
2813 return new JavaCodeUnit(filename, packageName, simpleClassName,
this);
2816 private boolean isOpaque(
final Type type) {
2820 private String compatiblePrimitiveJavaTypeName(
final Type fieldType,
2821 final MachineDataInfo curMachDesc) {
2822 if ( !fieldType.isInt() && !fieldType.isPointer() && !fieldType.isArray() ) {
2823 throw new GlueGenException(
"Can't yet handle opaque definitions of structs' fields to non-integer types (byte, short, int, long, etc.): type: "+
2824 fieldType, fieldType.getASTLocusTag());
2826 switch ((
int) fieldType.getSize(curMachDesc)) {
2827 case 1:
return "byte";
2828 case 2:
return "short";
2829 case 4:
return "int";
2830 case 8:
return "long";
2831 default:
throw new GlueGenException(
"Can't handle opaque definitions if the starting type isn't compatible with integral types, type "+
2832 fieldType.getDebugString(), fieldType.getASTLocusTag());
2836 private void openCodeUnits() throws IOException {
2837 String jRoot =
null;
2839 jRoot =
cfg.javaOutputDir() + File.separator +
2840 CodeGenUtils.packageAsPath(
cfg.packageName());
2842 String jImplRoot =
null;
2845 cfg.javaOutputDir() + File.separator +
2846 CodeGenUtils.packageAsPath(
cfg.implPackageName());
2848 String nRoot =
cfg.nativeOutputDir();
2849 if (
cfg.nativeOutputUsesJavaHierarchy())
2852 File.separator + CodeGenUtils.packageAsPath(
cfg.packageName());
2856 final String javaFileName = jRoot + File.separator +
cfg.className() +
".java";
2860 final String javaFileName = jImplRoot + File.separator +
cfg.implClassName() +
".java";
2861 javaImplUnit =
openJavaUnit(javaFileName,
cfg.implPackageName(),
cfg.implClassName());
2864 final String cUnitName =
cfg.implClassName() +
"_JNI.c";
2865 final String cFileName = nRoot + File.separator + cUnitName;
2866 cUnit =
openCUnit(cFileName, cUnitName);
2872 throw new InternalError(
"Should not call this");
2879 throw new InternalError(
"Should not call this");
2881 return javaImplUnit;
2886 throw new InternalError(
"Should not call this");
2891 private void closeWriters() throws IOException {
2892 if( javaUnit !=
null ) {
2896 if( javaImplUnit !=
null ) {
2897 javaImplUnit.
close();
2898 javaImplUnit =
null;
2900 if( cUnit !=
null ) {
2911 return cfg.javaOutputDir();
2919 return cfg.packageName();
2927 return cfg.implPackageName();
2940 unit.emitln(
" // --- Begin CustomJavaCode .cfg declarations");
2941 for (
final String line : code) {
2944 unit.emitln(
" // ---- End CustomJavaCode .cfg declarations");
2957 unit.emitln(
" // --- Begin CustomJNICode .cfg declarations");
2958 for (
final String line : code) {
2961 unit.emitln(
" // ---- End CustomJNICode .cfg declarations");
2965 String[] accessModifiers;
2967 if( PUBLIC_ABSTRACT == acc ) {
2968 accessModifiers =
new String[] { PUBLIC.getJavaName(), PUBLIC_ABSTRACT.getJavaName() };
2969 }
else if( PACKAGE_PRIVATE == acc ) {
2970 accessModifiers =
new String[] { PACKAGE_PRIVATE.getJavaName() };
2971 }
else if( PRIVATE == acc ) {
2972 throw new IllegalArgumentException(
"Class access "+classFQName+
" cannot be private");
2973 }
else if( PROTECTED == acc ) {
2974 accessModifiers =
new String[] { PROTECTED.getJavaName() };
2976 accessModifiers =
new String[] { PUBLIC.getJavaName() };
2978 return accessModifiers;
2987 final List<String> imports =
new ArrayList<String>(
cfg.imports());
2988 imports.add(
cfg.gluegenRuntimePackage()+
".*");
2990 imports.add(
Buffers.class.getPackage().getName()+
".*");
2991 imports.add(Buffer.class.getPackage().getName()+
".*");
2992 imports.add(
HashUtil.class.getPackage().getName()+
".*");
2993 imports.add(
"java.util.Set");
2994 imports.add(
"java.util.Map");
2995 imports.add(
"java.util.HashMap");
2996 imports.add(
"java.nio.charset.Charset");
2997 imports.add(
"java.nio.charset.StandardCharsets");
3001 String[] interfaces;
3002 List<String> userSpecifiedInterfaces =
null;
3004 userSpecifiedInterfaces =
cfg.extendedInterfaces(
cfg.className());
3006 userSpecifiedInterfaces =
cfg.implementedInterfaces(
cfg.className());
3008 interfaces =
new String[userSpecifiedInterfaces.size()];
3009 userSpecifiedInterfaces.toArray(interfaces);
3012 final CodeGenUtils.EmissionCallback docEmitter =
3015 public void emit(
final PrintWriter w) {
3016 for (
final Iterator<String> iter = intfDocs.iterator(); iter.hasNext(); ) {
3017 w.println(iter.next());
3037 final CodeGenUtils.EmissionCallback docEmitter =
3040 public void emit(
final PrintWriter w) {
3041 for (
final Iterator<String> iter = implDocs.iterator(); iter.hasNext(); ) {
3042 w.println(iter.next());
3047 String[] interfaces;
3048 List<String> userSpecifiedInterfaces =
null;
3049 userSpecifiedInterfaces =
cfg.implementedInterfaces(
cfg.implClassName());
3050 int additionalNum = 0;
3051 if (
cfg.className() !=
null) {
3054 interfaces =
new String[additionalNum + userSpecifiedInterfaces.size()];
3055 userSpecifiedInterfaces.toArray(interfaces);
3056 if (additionalNum == 1) {
3057 interfaces[userSpecifiedInterfaces.size()] =
cfg.className();
3062 javaImplUnit().output,
3063 cfg.implPackageName(),
3064 cfg.implClassName(),
3075 LOG.
log(WARNING,
"JavaCallback used, but no 'LibraryOnLoad' basename specified for JNI_OnLoad(..). Exactly one native code-unit for the library must specify 'LibraryOnLoad' basename");
3079 }
catch (
final Exception e) {
3080 throw new RuntimeException(
3081 "Error emitting all file headers: cfg.allStatic()=" +
cfg.
allStatic() +
3093 javaUnit.emitTailCode();
3094 javaUnit().emitln(
"} // end of class " +
cfg.className());
3098 javaImplUnit().
emitln(
"} // end of class " +
cfg.implClassName());
3105 private JavaType javaType(
final Class<?> c) {
3108 private JavaType javaStringType(
final Class<?> c,
final PascalStringElem pascalStrElem) {
3118 private MethodBinding bindFunction(FunctionSymbol sym,
3119 final boolean forInterface,
3120 final MachineDataInfo curMachDesc,
3121 final JavaType containingType,
final Type containingCType) {
3123 final String delegationImplName =
null == containingType &&
null == containingCType ?
3125 if( !forInterface &&
null != delegationImplName ) {
3128 sym = FunctionSymbol.cloneWithDeepAliases(sym);
3129 sym.addAliasedName(delegationImplName);
3131 final JavaType javaReturnType;
3133 if (
cfg.returnsString(sym)) {
3134 final PointerType prt = sym.getReturnType().asPointer();
3136 prt.getTargetType().asInt() ==
null ||
3137 prt.getTargetType().getSize(curMachDesc) != 1) {
3138 throw new GlueGenException(
3139 "Cannot apply ReturnsString configuration directive to \"" + sym +
3140 "\". ReturnsString requires native method to have return type \"char *\"",
3141 sym.getASTLocusTag());
3143 javaReturnType = javaStringType(java.lang.String.class,
null);
3149 javaReturnType = typeToJavaType(sym.getReturnType(), curMachDesc);
3155 final List<JavaType> javaArgumentTypes =
new ArrayList<JavaType>();
3158 if(
null != pascalStringArgs ) {
3159 stringValueIndices = JavaType.PascalStringElem.pushValueIndex(pascalStringArgs, stringValueIndices);
3161 final JavaCallbackInfo jcbi =
cfg.setFuncToJavaCallbackMap.get( sym.getName() );
3162 int jcbiSetFuncCBParamIdx=-1;
3164 for (
int i = 0; i < sym.getNumArguments(); i++) {
3165 final Type cArgType = sym.getArgumentType(i);
3166 final String cArgName = sym.getArgumentName(i);
3167 JavaType mappedType = typeToJavaType(cArgType, curMachDesc);
3170 if(
null != jcbi && jcbi.cbFuncTypeName.equals( cArgType.getName() ) &&
3171 ( !jcbi.setFuncProcessed || i == jcbi.setFuncCBParamIdx ) )
3174 jcbiSetFuncCBParamIdx=i;
3175 mappedType = JavaType.createForNamedClass( jcbi.cbFQClazzName );
3177 }
else if(
null != jcbi && i == jcbi.setFuncUserParamIdx && cArgType.isPointer() ) {
3179 if( cArgType.getTargetType().isVoid() ) {
3180 if( jcbi.cbFuncUserParamType.isCompound() ) {
3181 mappedType = JavaType.createForClass(
long.
class);
3183 }
else if(
null != jcbi.userParamClassName ) {
3184 mappedType = JavaType.createForNamedClass( jcbi.userParamClassName );
3187 mappedType = JavaType.forObjectClass();
3194 if( 0 == mapMode ) {
3195 if ( stringValueIndices !=
null && stringValueIndices.contains(i) ) {
3198 if ( mappedType.isCVoidPointerType() ||
3199 mappedType.isCCharPointerType() ||
3200 mappedType.isCShortPointerType() ||
3201 mappedType.isNIOPointerBuffer() ||
3202 ( mappedType.isArray() &&
3203 ( mappedType.getJavaClass() == ArrayTypes.byteBufferArrayClass ) ||
3204 ( mappedType.getJavaClass() == ArrayTypes.shortBufferArrayClass ) ) )
3209 final JavaType.PascalStringElem pascalStrElem = JavaType.PascalStringElem.getByValueIdx(pascalStringArgs, i);
3210 if (mappedType.isArray() || mappedType.isNIOPointerBuffer()) {
3211 mappedType = javaStringType(ArrayTypes.stringArrayClass, pascalStrElem);
3214 mappedType = javaStringType(String.class, pascalStrElem);
3219 throw new GlueGenException(
3220 "Cannot apply ArgumentIsString configuration directive to " +
3221 "argument " + i +
" of \"" + sym +
"\": argument type is not " +
3222 "a \"void*\", \"char *\", \"short *\", \"char**\", or \"short**\" equivalent",
3223 sym.getASTLocusTag());
3225 }
else if ( ( mappedType.isInt() || mappedType.isLong() ) &&
null != pascalStringArgs ) {
3226 final JavaType.PascalStringElem pascalStrElem = JavaType.PascalStringElem.getByLengthIdx(pascalStringArgs, i);
3227 if(
null != pascalStrElem ) {
3230 mappedType =
new JavaType(mappedType, pascalStrElem);
3234 javaArgumentTypes.add(mappedType);
3235 LOG.
log(INFO,
"BindFunc: {0}: added mapping ({1}) for {2} from C type: {3} to Java type: {4}",
3236 sym.getName(), mapMode, cArgName, cArgType, mappedType);
3238 if(
null != jcbi ) {
3239 jcbi.setFuncProcessed(sym.getType(), jcbiSetFuncCBParamIdx);
3240 LOG.
log(INFO,
"BindFunc.JavaCallback: {0}: set[cbParamIdx {1}], {3}, {4}",
3241 sym.getName(), jcbiSetFuncCBParamIdx, sym.getType().toString(sym.getName(),
false,
true), jcbi);
3243 final MethodBinding mb =
new MethodBinding(sym, delegationImplName,
3244 javaReturnType, javaArgumentTypes,
3245 containingType, containingCType);
3250 private MethodBinding lowerMethodBindingPointerTypes(
final MethodBinding inputBinding,
3251 final boolean convertToArrays,
3252 final boolean[] canProduceArrayVariant) {
3253 MethodBinding result = inputBinding;
3254 boolean arrayPossible =
false;
3258 for (
int i = 0; i < inputBinding.getNumArguments(); i++) {
3259 final JavaType t = inputBinding.getJavaArgumentType(i);
3260 if (t.isCPrimitivePointerType()) {
3261 if (t.isCVoidPointerType()) {
3263 result = result.replaceJavaArgumentType(i, JavaType.forNIOBufferClass());
3264 }
else if (t.isCCharPointerType()) {
3265 arrayPossible =
true;
3266 if (convertToArrays) {
3267 result = result.replaceJavaArgumentType(i, javaType(ArrayTypes.byteArrayClass));
3269 result = result.replaceJavaArgumentType(i, JavaType.forNIOByteBufferClass());
3271 }
else if (t.isCShortPointerType()) {
3272 arrayPossible =
true;
3273 if (convertToArrays) {
3274 result = result.replaceJavaArgumentType(i, javaType(ArrayTypes.shortArrayClass));
3276 result = result.replaceJavaArgumentType(i, JavaType.forNIOShortBufferClass());
3278 }
else if (t.isCInt32PointerType()) {
3279 arrayPossible =
true;
3280 if (convertToArrays) {
3281 result = result.replaceJavaArgumentType(i, javaType(ArrayTypes.intArrayClass));
3283 result = result.replaceJavaArgumentType(i, JavaType.forNIOIntBufferClass());
3285 }
else if (t.isCInt64PointerType()) {
3286 arrayPossible =
true;
3287 if (convertToArrays) {
3288 result = result.replaceJavaArgumentType(i, javaType(ArrayTypes.longArrayClass));
3290 result = result.replaceJavaArgumentType(i, JavaType.forNIOLongBufferClass());
3292 }
else if (t.isCFloatPointerType()) {
3293 arrayPossible =
true;
3294 if (convertToArrays) {
3295 result = result.replaceJavaArgumentType(i, javaType(ArrayTypes.floatArrayClass));
3297 result = result.replaceJavaArgumentType(i, JavaType.forNIOFloatBufferClass());
3299 }
else if (t.isCDoublePointerType()) {
3300 arrayPossible =
true;
3301 if (convertToArrays) {
3302 result = result.replaceJavaArgumentType(i, javaType(ArrayTypes.doubleArrayClass));
3304 result = result.replaceJavaArgumentType(i, JavaType.forNIODoubleBufferClass());
3307 throw new GlueGenException(
"Unknown C pointer type " + t);
3315 final JavaType t = result.getJavaReturnType();
3316 if (t.isCPrimitivePointerType()) {
3317 if (t.isCVoidPointerType()) {
3318 result = result.replaceJavaArgumentType(-1, JavaType.forNIOByteBufferClass());
3319 }
else if (t.isCCharPointerType()) {
3320 result = result.replaceJavaArgumentType(-1, JavaType.forNIOByteBufferClass());
3321 }
else if (t.isCShortPointerType()) {
3322 result = result.replaceJavaArgumentType(-1, JavaType.forNIOShortBufferClass());
3323 }
else if (t.isCInt32PointerType()) {
3324 result = result.replaceJavaArgumentType(-1, JavaType.forNIOIntBufferClass());
3325 }
else if (t.isCInt64PointerType()) {
3326 result = result.replaceJavaArgumentType(-1, JavaType.forNIOLongBufferClass());
3327 }
else if (t.isCFloatPointerType()) {
3328 result = result.replaceJavaArgumentType(-1, JavaType.forNIOFloatBufferClass());
3329 }
else if (t.isCDoublePointerType()) {
3330 result = result.replaceJavaArgumentType(-1, JavaType.forNIODoubleBufferClass());
3332 throw new GlueGenException(
"Unknown C pointer type " + t, result.getCReturnType().getASTLocusTag());
3338 if (canProduceArrayVariant !=
null) {
3339 canProduceArrayVariant[0] = arrayPossible;
3358 final List<MethodBinding> result =
new ArrayList<MethodBinding>();
3361 final boolean[] canProduceArrayVariant =
new boolean[1];
3363 if (binding.signatureUsesCPrimitivePointers() ||
3364 binding.signatureUsesCVoidPointers() ||
3365 binding.signatureUsesCArrays()) {
3367 result.add(lowerMethodBindingPointerTypes(binding,
false, canProduceArrayVariant));
3370 if (canProduceArrayVariant[0] && (binding.signatureUsesCPrimitivePointers() || binding.signatureUsesCArrays()) &&
3372 result.add(lowerMethodBindingPointerTypes(binding,
true,
null));
3375 result.add(binding);
3381 private Type canonicalize(
final Type t) {
3382 final Type res = canonMap.get(t);
3391 private static final String optStringCharsetCode =
3392 " private static Charset _charset = StandardCharsets.UTF_8;\n" +
3394 " /** Returns the Charset for this class's String mapping, default is StandardCharsets.UTF_8. */\n"+
3395 " public static Charset getCharset() { return _charset; };\n"+
3397 " /** Sets the Charset for this class's String mapping, default is StandardCharsets.UTF_8. */\n"+
3398 " public static void setCharset(Charset cs) { _charset = cs; }\n";
3400 private static final String optStringMaxStrnlenCode =
3401 " private static int _max_strnlen = 8192;\n"+
3403 " /** Returns the maximum number of bytes to read to determine native string length using `strnlen(..)`, default is 8192. */\n"+
3404 " public static int getMaxStrnlen() { return _max_strnlen; };\n"+
3406 " /** Sets the maximum number of bytes to read to determine native string length using `strnlen(..)`, default is 8192. */\n"+
3407 " public static void setMaxStrnlen(int v) { _max_strnlen = v; }\n";
Utility methods allowing easy java.nio.Buffer manipulations.
Machine data description for alignment and size onle, see com.jogamp.gluegen.
C code unit (a generated C source file), covering multiple FunctionEmitter allowing to unify output,...
void emitJNIOnLoadJNIEnvCode(final String libraryBasename)
Emits getJNIOnLoadJNIEnvCode(String).
void emitHeader(final String packageName, final String className, final List< String > customCode)
Emits the C-side component of the Java<->C JNI binding to its CodeUnit, see FunctionEmitter.
final void setTemporaryCVariableDeclarations(final List< String > arg)
Sets up a List of Strings containing declarations for temporary C variables to be assigned to after t...
final void setReturnValueCapacityExpression(final MessageFormat expression)
If this function returns a void* encapsulated in a java.nio.Buffer (or compound type wrapper),...
final void setReturnValueLengthExpression(final MessageFormat expression)
If this function returns an array, sets the expression for the length of the returned array.
final void setTemporaryCVariableAssignments(final List< String > arg)
Sets up a List of Strings containing assignments for temporary C variables which are made after the u...
static void emitJavaHeaders(final PrintWriter w, final String packageName, final String className, final boolean isClassNotInterface, final List< String > imports, final String[] accessModifiers, final String[] interfaces, final String classExtended, final EmissionCallback classDocComment)
Emit the opening headers for one java class/interface file.
static String packageAsPath(final String packageName)
Given a java package name (e.g., "java.lang"), return the package as a directory path (i....
static String capitalizeString(final String string)
Converts first letter to upper case.
General code unit (a generated C or Java source file), covering multiple FunctionEmitter allowing to ...
void emit(final String s)
A valid java expression, including its result type, usually generated from a native [C] expression,...
Represents a [native] constant expression, comprises the [native] expression, see getNativeExpr() and...
Generic function emitter to produce C (JNI) or Java code stubs to its CodeUnit, invoking a native fun...
void addModifier(final EmissionModifier m)
static final EmissionModifier STATIC
A generic exception for Jogamp errors used throughout the binding as a substitute for RuntimeExceptio...
Glue code generator for C functions and data structures.
Java code unit (a generated Java source file), covering multiple FunctionEmitter allowing to unify ou...
JavaCallback configuration definition (static)
Parses and provides access to the contents of .cfg files for the JavaEmitter.
List< Integer > stringArguments(final AliasedSymbol symbol)
Returns a list of Integers which are the indices of const char* arguments that should be converted to...
String extendedParentClass(final String className)
Returns a List of Strings indicating the interfaces the passed class should declare it implements.
List< String > customJavaCodeForClass(final String className)
Returns a list of Strings containing user-implemented code for the given Java type name (not fully-qu...
List< JavaType.PascalStringElem > pascalStringArgument(final AliasedSymbol symbol)
Returns a list of PascalStringIdx which are tuples of indices of int len, const char* arguments that ...
boolean allStatic()
Returns true if the emission style is AllStatic.
final void read(final String filename)
Reads the configuration file.
TypeInfo canonicalNameOpaque(final String canonicalName)
If the given canonicalName should be considered opaque, returns the TypeInfo describing the replaceme...
boolean shouldIgnoreInImpl(final AliasedSymbol symbol)
Returns true if this aliased symbol should be ignored during glue code generation of implementation o...
String returnValueLength(final String symbol)
Returns a MessageFormat string of the C expression calculating the length of the array being returned...
String returnedArrayLength(final String symbol)
Returns a MessageFormat string of the Java expression calculating the number of elements in the retur...
boolean emitInterface()
Returns true if an interface should be emitted during glue code generation.
boolean emitImpl()
Returns true if an implementing class should be emitted during glue code generation.
boolean isUnimplemented(final AliasedSymbol symbol)
Returns true if this function should be given a body which throws a run-time exception with an "unimp...
static String canonicalStructFieldSymbol(final String structName, final String fieldName)
Returns the canonical configuration name for a struct field name, i.e.
String returnStructMachineDataInfoIndex(final String structName)
Returns a MessageFormat string of the Java code defining mdIdx, i.e.
List< JavaCallbackDef > getJavaCallbackList()
Returns the list of all configured JavaCallback definitions.
List< String > javaPrologueForMethod(final MethodBinding binding, final boolean forImplementingMethodCall, final boolean eraseBufferAndArrayTypes)
Returns a list of Strings which should be emitted as a prologue to the body for the Java-side glue co...
final boolean immutableAccess(final AliasedSymbol symbol)
Returns true if the glue code for the given aliased symbol shall produce code for immutable access on...
JavaType getOpaqueReturnType(final String functionName)
Variant of getOpaqueReturnType(AliasedSymbol), where this method only considers the current-name of t...
String packageForStruct(final String structName)
Returns the package into which to place the glue code for accessing the specified struct.
String getJavaSymbolRename(final String origName)
Returns a replacement name for this function or definition which should be used as the Java name for ...
List< String > javaEpilogueForMethod(final MethodBinding binding, final boolean forImplementingMethodCall, final boolean eraseBufferAndArrayTypes)
Returns a list of Strings which should be emitted as an epilogue to the body for the Java-side glue c...
String returnValueCapacity(final String functionName)
Returns a MessageFormat string of the C expression calculating the capacity of the java....
String getDelegatedImplementation(final String functionName)
Variant of getDelegatedImplementation(AliasedSymbol), where this method only considers the current-na...
String renameJavaType(final String javaTypeName)
Returns a replacement name for this type, which should be the name of a Java wrapper class for a C st...
TypeInfo typeInfo(Type type)
If this type should be considered opaque, returns the TypeInfo describing the replacement type.
List< String > customJNICodeForClass(final String className)
Returns a list of Strings containing user-implemented JNI code for the given Java type name (not full...
final boolean shouldIgnoreInInterface(final String symbol)
Variant of shouldIgnoreInInterface(AliasedSymbol), where this method only considers the current-name ...
List< String > javadocForClass(final String className)
Returns a list of Strings containing Javadoc documentation for the given Java type name (not fully-qu...
void endEmission()
Finish the emission of glue code.
void emitStruct(final CompoundType structCType, final Type structCTypedefPtr)
Emit glue code for the given CompoundType.
CCodeUnit openCUnit(final String filename, final String cUnitName)
void beginFunctions(final TypeDictionary typedefDictionary, final TypeDictionary structDictionary, final Map< Type, Type > canonMap, final List< FunctionSymbol > cFunctions)
void generatePublicEmitters(final MethodBinding binding, final List< FunctionEmitter > allEmitters, final boolean signatureOnly)
Generates the public emitters for this MethodBinding which will produce either simply signatures (for...
Iterator< FunctionSymbol > emitFunctions(final List< FunctionSymbol > funcsToBind)
Emit glue code for the list of FunctionSymbols.
String getJavaOutputDir()
Returns the value that was specified by the configuration directive "JavaOutputDir",...
void generatePrivateEmitters(final MethodBinding binding, final List< FunctionEmitter > allEmitters)
Generates the private emitters for this MethodBinding.
void beginEmission(final GlueEmitterControls controls)
Begin the emission of glue code.
JavaCodeUnit openJavaUnit(final String filename, final String packageName, final String simpleClassName)
void readConfigurationFile(final String filename)
void emitDefine(final ConstantDefinition def, final String optionalComment)
JavaCodeUnit javaImplUnit()
static String getJNIMethodNamePrefix(final String javaPackageName, final String javaClassName)
Returns the JNI method prefix consisting our of mangled package- and class-name.
void beginStructLayout()
Begins the process of computing field offsets and type sizes for the structs to be emitted.
List< MethodBinding > expandMethodBinding(final MethodBinding binding)
String getImplPackageName()
Returns the value that was specified by the configuration directive "ImplPackage",...
void emitCustomJNICode(final CodeUnit unit, final String className)
Emit all the strings specified in the "CustomJNICode" parameters of the configuration file.
void emitAllFileHeaders()
Write out any header information for the output files (class declaration and opening brace,...
JavaConfiguration getConfig()
void emitAllFileFooters()
Write out any footer information for the output files (closing brace of class definition,...
void mangleBinding(final MethodBinding binding)
Allow specializations to modify the given MethodBinding before expanding and emission.
void beginStructs(final TypeDictionary typedefDictionary, final TypeDictionary structDictionary, final Map< Type, Type > canonMap)
static String jniMangle(final String name)
Mangle a class, package or function name for JNI usage, i.e.
JavaEmitter(final JavaConfiguration cfg)
void emitCustomJavaCode(final CodeUnit unit, final String className)
Emit all the strings specified in the "CustomJavaCode" parameters of the configuration file.
String getJavaPackageName()
Returns the value that was specified by the configuration directive "Package", or the default if none...
void endStructLayout()
Finishes the struct layout process.
static int addStrings2Buffer(StringBuilder buf, final String sep, final String first, final Collection< String > col)
String[] getClassAccessModifiers(final String classFQName)
void prepCEmitter(final String returnSizeLookupName, final JavaType javaReturnType, final CMethodBindingEmitter cEmitter)
JavaConfiguration createConfig()
Create the object that will read and store configuration information for this JavaEmitter.
void layoutStruct(final CompoundType t)
Lays out one struct which will be emitted later.
List<? extends FunctionEmitter > generateMethodBindingEmitters(final FunctionSymbol sym)
Generate all appropriate Java bindings for the specified C function symbols.
Emits the Java-side component (interface and.or implementation) of the Java<->C JNI binding to its Co...
void setEpilogue(final List< String > epilogue)
Sets the manually-generated epilogue code for this emitter.
static final EmissionModifier PRIVATE
void setReturnedArrayLengthExpression(final String expr)
If the underlying function returns an array (currently only arrays of compound types are supported) a...
void setPrologue(final List< String > prologue)
Sets the manually-generated prologue code for this emitter.
static final EmissionModifier PUBLIC
static final EmissionModifier NATIVE
static final EmissionModifier PROTECTED
Describes a java-side representation of a type that is used to represent the same data on both the Ja...
String getName()
Returns the Java type name corresponding to this type.
boolean isCompoundTypeWrapper()
boolean isPrimitiveArray()
static JavaType createForClass(final Class<?> clazz)
Creates a JavaType corresponding to the given Java type.
static JavaType createForStringClass(final Class<?> clazz, final PascalStringElem pascalStrElem)
boolean isCPrimitivePointerType()
boolean isArrayOfCompoundTypeWrappers()
static LoggerIf getLogger()
Returns the root package logger.
Represents the binding of a C function to a Java method.
JavaType getJavaReturnType()
String getName()
Returns the FunctionSymbol's current aliased API name.
FunctionSymbol getCSymbol()
Returns the FunctionSymbol.
String getDelegationImplName()
The implementation delegation name, or null for no delegation.
boolean needsNIOWrappingOrUnwrapping()
Returns true if the function needs NIO-related wrapping/unwrapping or conversion of various arguments...
Utility class for handling Opaque directives for JavaEmitter.
void rename(final String newName)
Rename this symbol with the given newName if not equal current-name.
void addAliasedName(final String origName)
Add the given origName to the list of aliases if not equal current-name.
Models all compound types, i.e., those containing fields: structs and unions.
Represents a field in a struct or union.
String getName()
Name of this field in the containing data structure.
Type getType()
Type of this field.
Describes a function symbol, which includes the name and type.
ASTLocusTag getASTLocusTag()
Returns this instance's ASTLocusTag, if available, otherwise returns null.
Provides a level of indirection between the definition of a type's size and the absolute value of thi...
final boolean hasFixedNativeSize()
static final SizeThunk POINTER
Encapsulates algorithm for laying out data structures.
void layout(final CompoundType t)
static StructLayout create(final int baseOffset)
Utility class for recording names of typedefs and structs.
final boolean isArray()
Indicates whether this is an ArrayType.
final StringBuilder getSignature(StringBuilder sb)
final ASTLocusTag getASTLocusTag()
Returns this instance's ASTLocusTag, if available, otherwise returns null.
Type getArrayBaseOrPointerTargetType()
Return getBaseType() if isArray() or returns getTargetType() otherwise.
final boolean isConst()
Indicates whether this type is const.
Type getBaseType()
Helper method to returns the bottom-most element type of this type, i.e.
boolean isFunctionPointer()
Convenience routine indicating whether this Type is a pointer to a function.
final String getName()
Returns the name of this type.
boolean setTypedefName(final String name)
Set the typedef name of this type and renders this type a typedef, if given name has a length.
FunctionType getTargetFunction()
Returns the target FunctionType if this type is isFunctionPointer().
Type getTargetType()
Helper method to returns the target type of this type, in case another type is being referenced,...
final SizeThunk getSize()
SizeThunk which computes size of this type in bytes.
final String getDebugString()
final boolean isPointer()
Indicates whether this is a PointerType.
final boolean isCompound()
Indicates whether this is a CompoundType.
Static enumeration of MachineDataInfo instances used for high performance data size and alignment loo...
Access control for emitted Java methods.
MethodAccess(final String javaName)
final String getJavaName()
Java
Java ownership of resource.
Mixed
Ambiguous mixed ownership of resource, i.e.
Parent
Parent ownership of resource, i.e.
Native
Native ownership of resource.
Interface callers may use ProcAddressHelper's reset helper method to install function pointers into a...
A class that emits source code of some time when activated.
Specifies the interface by which a GlueEmitter can request additional information from the glue gener...
Specifies the interface by which GlueGen requests glue code to be generated.
void log(final Level level, final String msg)
See Logger#log(Level, String).
Provides a mechanism by which the GlueEmitter can look at all of the #defines, enum values and functi...
Supports symbol aliasing, i.e.