feat: add csharp interop code generation but no test.
- add csharp interop code generation without testing. - add annotation for bmap binding project. - fix README.
This commit is contained in:
parent
8a1fc03965
commit
a2fb376231
|
@ -1,11 +1,282 @@
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class CSharpWriter {
|
public class CSharpWriter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class represent the C# type corresponding to extracted variable type.
|
||||||
|
*/
|
||||||
|
private static class CsInteropType {
|
||||||
|
public CsInteropType() {
|
||||||
|
mMarshalAs = null;
|
||||||
|
mCsType = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The argument of MarshalAsAttribute constructor. In generation, this field
|
||||||
|
* should be used like this: "[MarshalAs(THIS)]" (for parameter) or "[return:
|
||||||
|
* MarshalAs(THIS)]" (for return value).
|
||||||
|
*/
|
||||||
|
public String mMarshalAs;
|
||||||
|
/**
|
||||||
|
* The C# type used in interop function declaration for corresponding parameter.
|
||||||
|
*/
|
||||||
|
public String mCsType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* C# specified function which get C# used interop MarshalAs constructor
|
||||||
|
* arguments and C# type used in interop function declaration.
|
||||||
|
*
|
||||||
|
* @param vt The instance of {@linkplain VariableType} for fetching interop
|
||||||
|
* type.
|
||||||
|
* @return The corresponding interop type of given variable type.
|
||||||
|
*/
|
||||||
|
private static CsInteropType getCsInteropType(ExpFctParamDecl paramdecl) {
|
||||||
|
// get essential variable type properties first
|
||||||
|
VariableType vt = paramdecl.mVarType;
|
||||||
|
String vt_base_type = vt.getBaseType();
|
||||||
|
int vt_pointer_level = vt.getPointerLevel();
|
||||||
|
|
||||||
|
// create return value
|
||||||
|
CsInteropType ret = new CsInteropType();
|
||||||
|
|
||||||
|
// use "switch" to check variable type
|
||||||
|
switch (vt_base_type) {
|
||||||
|
case "CKSTRING":
|
||||||
|
// only allow 0 and 1 pointer level for string.
|
||||||
|
switch (vt_pointer_level) {
|
||||||
|
case 0:
|
||||||
|
ret.mMarshalAs = "UnmanagedType.LPUTF8Str";
|
||||||
|
ret.mCsType = "string";
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
ret.mMarshalAs = "UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(BMStringArrayMashaler)";
|
||||||
|
ret.mCsType = "string[]";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "CKDWORD":
|
||||||
|
if (vt_pointer_level == 0) {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.U4";
|
||||||
|
ret.mCsType = "uint";
|
||||||
|
} else {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.SysInt";
|
||||||
|
ret.mCsType = "IntPtr";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "CKWORD":
|
||||||
|
if (vt_pointer_level == 0) {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.U2";
|
||||||
|
ret.mCsType = "ushort";
|
||||||
|
} else {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.SysInt";
|
||||||
|
ret.mCsType = "IntPtr";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "CKINT":
|
||||||
|
if (vt_pointer_level == 0) {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.I4";
|
||||||
|
ret.mCsType = "int";
|
||||||
|
} else {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.SysInt";
|
||||||
|
ret.mCsType = "IntPtr";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "bool":
|
||||||
|
if (vt_pointer_level == 0) {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.U1";
|
||||||
|
ret.mCsType = "bool";
|
||||||
|
} else {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.SysInt";
|
||||||
|
ret.mCsType = "IntPtr";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "CKFLOAT":
|
||||||
|
if (vt_pointer_level == 0) {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.R4";
|
||||||
|
ret.mCsType = "float";
|
||||||
|
} else {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.SysInt";
|
||||||
|
ret.mCsType = "IntPtr";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "CKBYTE":
|
||||||
|
if (vt_pointer_level == 0) {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.U1";
|
||||||
|
ret.mCsType = "byte";
|
||||||
|
} else {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.SysInt";
|
||||||
|
ret.mCsType = "IntPtr";
|
||||||
|
}
|
||||||
|
case "CK_ID":
|
||||||
|
if (vt_pointer_level == 0) {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.U4";
|
||||||
|
ret.mCsType = "uint";
|
||||||
|
} else {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.SysInt";
|
||||||
|
ret.mCsType = "IntPtr";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "NakedOutputCallback":
|
||||||
|
// callback actually is a function pointer
|
||||||
|
// so it only allow base type without any pointer level.
|
||||||
|
if (vt_pointer_level == 0) {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.FunctionPtr";
|
||||||
|
ret.mCsType = "OutputCallback";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "BMFile":
|
||||||
|
// In any case, BMFile only should be raw pointer
|
||||||
|
if (vt_pointer_level != 0) {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.SysInt";
|
||||||
|
ret.mCsType = "IntPtr";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "BMMeshTransition":
|
||||||
|
// In any case, BMMeshTransition only should be raw pointer
|
||||||
|
if (vt_pointer_level != 0) {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.SysInt";
|
||||||
|
ret.mCsType = "IntPtr";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "VxVector3":
|
||||||
|
if (vt_pointer_level == 0) {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.Struct";
|
||||||
|
ret.mCsType = "VxVector3";
|
||||||
|
} else {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.SysInt";
|
||||||
|
ret.mCsType = "IntPtr";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "VxVector2":
|
||||||
|
if (vt_pointer_level == 0) {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.Struct";
|
||||||
|
ret.mCsType = "VxVector2";
|
||||||
|
} else {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.SysInt";
|
||||||
|
ret.mCsType = "IntPtr";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "VxColor":
|
||||||
|
if (vt_pointer_level == 0) {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.Struct";
|
||||||
|
ret.mCsType = "VxColor";
|
||||||
|
} else {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.SysInt";
|
||||||
|
ret.mCsType = "IntPtr";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "VxMatrix":
|
||||||
|
if (vt_pointer_level == 0) {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.Struct";
|
||||||
|
ret.mCsType = "VxMatrix";
|
||||||
|
} else {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.SysInt";
|
||||||
|
ret.mCsType = "IntPtr";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "CK_TEXTURE_SAVEOPTIONS":
|
||||||
|
case "VX_PIXELFORMAT":
|
||||||
|
case "VXTEXTURE_BLENDMODE":
|
||||||
|
case "VXTEXTURE_FILTERMODE":
|
||||||
|
case "VXTEXTURE_ADDRESSMODE":
|
||||||
|
case "VXBLEND_MODE":
|
||||||
|
case "VXFILL_MODE":
|
||||||
|
case "VXSHADE_MODE":
|
||||||
|
case "VXCMPFUNC":
|
||||||
|
case "VXMESH_LITMODE":
|
||||||
|
// all enum share the same underlying type.
|
||||||
|
if (vt_pointer_level == 0) {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.U4";
|
||||||
|
ret.mCsType = "uint";
|
||||||
|
} else {
|
||||||
|
ret.mMarshalAs = "UnmanagedType.SysInt";
|
||||||
|
ret.mCsType = "IntPtr";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check whether we successfully get result
|
||||||
|
if (ret.mMarshalAs == null || ret.mCsType == null) {
|
||||||
|
throw new IllegalArgumentException("Unexpected type: " + vt.toCType());
|
||||||
|
}
|
||||||
|
|
||||||
|
// return value
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
public static void writeCSharpCode(Vector<ExpFctDecl> data) throws Exception {
|
public static void writeCSharpCode(Vector<ExpFctDecl> data) throws Exception {
|
||||||
OutputStreamWriter writer = CommonHelper.openWriter("dest/BMExports.cs");
|
OutputStreamWriter writer = CommonHelper.openWriter("dest/BMExports.cs");
|
||||||
writer.write("// WIP");
|
IndentHelper helper = new IndentHelper(writer);
|
||||||
|
|
||||||
|
// write function decls
|
||||||
|
helper.puts("");
|
||||||
|
helper.puts("#region Function Defines");
|
||||||
|
helper.puts("");
|
||||||
|
|
||||||
|
for (ExpFctDecl fctdecl : data) {
|
||||||
|
// write annotation
|
||||||
|
// summary (just plain function name)
|
||||||
|
helper.puts("/// <summary>");
|
||||||
|
helper.printf("/// %s", fctdecl.mFctName);
|
||||||
|
helper.puts("/// </summary>");
|
||||||
|
// parameter list
|
||||||
|
for (ExpFctParamDecl paramdecl : fctdecl.mFctParams) {
|
||||||
|
helper.printf("/// <param name=\"%s\">Type: %s. %s%s</param>", paramdecl.mVarName,
|
||||||
|
paramdecl.mVarType.toCType(), (paramdecl.mIsInput ? "" : "This is OUT parameter. "),
|
||||||
|
paramdecl.mVarDesc);
|
||||||
|
}
|
||||||
|
// return value
|
||||||
|
helper.puts("/// <returns>True if no error, otherwise False.</returns>");
|
||||||
|
|
||||||
|
// write real declaration
|
||||||
|
// first, write DllImportAttribute
|
||||||
|
helper.printf(
|
||||||
|
"[DllImport(g_DllName, EntryPoint = \"%s\", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, ExactSpelling = true)]",
|
||||||
|
fctdecl.mFctName);
|
||||||
|
// second, write return value MarshalAsAttribute
|
||||||
|
helper.printf("[return: MarshalAs(UnmanagedType.U1)]");
|
||||||
|
// then, before we write function body, we need origanize its parameter list
|
||||||
|
// first
|
||||||
|
Vector<String> cs_param_list = new Vector<String>();
|
||||||
|
for (ExpFctParamDecl paramdecl : fctdecl.mFctParams) {
|
||||||
|
// create string builder
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
// push in out symbol
|
||||||
|
if (paramdecl.mIsInput) {
|
||||||
|
sb.append("[In, ");
|
||||||
|
} else {
|
||||||
|
sb.append("[Out, ");
|
||||||
|
}
|
||||||
|
// get interop type now
|
||||||
|
CsInteropType interop_type = getCsInteropType(paramdecl);
|
||||||
|
// push MarshalAsAttribute
|
||||||
|
sb.append("MarshalAs(");
|
||||||
|
sb.append(interop_type.mMarshalAs);
|
||||||
|
sb.append(") ");
|
||||||
|
// push out keyword if parameter is out parameter
|
||||||
|
if (!paramdecl.mIsInput) {
|
||||||
|
sb.append("out ");
|
||||||
|
}
|
||||||
|
// push parameter cs type
|
||||||
|
sb.append(interop_type.mCsType);
|
||||||
|
sb.append(" ");
|
||||||
|
// push parameter name
|
||||||
|
sb.append(paramdecl.mVarName);
|
||||||
|
// insert built string into list
|
||||||
|
cs_param_list.add(sb.toString());
|
||||||
|
}
|
||||||
|
// join built parameter list and output real function declaration
|
||||||
|
helper.printf("internal static extern bool %s(%s);", fctdecl.mFctName,
|
||||||
|
cs_param_list.stream().collect(Collectors.joining(", ")));
|
||||||
|
}
|
||||||
|
|
||||||
|
helper.puts("");
|
||||||
|
helper.puts("#endregion");
|
||||||
|
helper.puts("");
|
||||||
|
|
||||||
writer.close();
|
writer.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,23 @@
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class represent an export BMap function.
|
||||||
|
*/
|
||||||
public class ExpFctDecl {
|
public class ExpFctDecl {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of this function.
|
||||||
|
*/
|
||||||
public String mFctName;
|
public String mFctName;
|
||||||
|
/**
|
||||||
|
* The return value type of this function.
|
||||||
|
*/
|
||||||
public VariableType mFctRetType;
|
public VariableType mFctRetType;
|
||||||
|
/**
|
||||||
|
* The parameters (arguments) list of this function. Each items are
|
||||||
|
* {@linkplain ExpFctParamDecl} and represent parameter one by one from left to
|
||||||
|
* right.
|
||||||
|
*/
|
||||||
public Vector<ExpFctParamDecl> mFctParams;
|
public Vector<ExpFctParamDecl> mFctParams;
|
||||||
|
|
||||||
public ExpFctDecl() {
|
public ExpFctDecl() {
|
||||||
|
@ -13,4 +27,3 @@ public class ExpFctDecl {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,41 @@
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class represent a single parameter (argument) of function. This class
|
||||||
|
* usually is the member of {@linkplain ExpFctDecl}.
|
||||||
|
*/
|
||||||
public class ExpFctParamDecl {
|
public class ExpFctParamDecl {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of this parameter.
|
||||||
|
*/
|
||||||
public VariableType mVarType;
|
public VariableType mVarType;
|
||||||
|
/**
|
||||||
|
* The name of this parameter.
|
||||||
|
*/
|
||||||
public String mVarName;
|
public String mVarName;
|
||||||
|
/**
|
||||||
|
* True if this paramter is marked as input parameter, otherwise false.
|
||||||
|
* <p>
|
||||||
|
* Input parameter and output paramter is commonly used in C/C++ code. By using
|
||||||
|
* this feature, each function can receive multiple arguments and return
|
||||||
|
* multiple arguments without defining a struct to hold it.
|
||||||
|
* <p>
|
||||||
|
* The type of input parameter is itself. However, the type of output parameter
|
||||||
|
* is the pointer of itself. So you may need get its pointer type when
|
||||||
|
* processing output paramter, especially for the scenario that the target
|
||||||
|
* language do not support explicit output parameter keyword.
|
||||||
|
*/
|
||||||
public boolean mIsInput;
|
public boolean mIsInput;
|
||||||
|
/**
|
||||||
|
* The description of this parameter.
|
||||||
|
* <p>
|
||||||
|
* This description is generated by this program. It will indicate the
|
||||||
|
* underlying C++ type to tell end user how to treat this paramter because some
|
||||||
|
* target languages' native calling style can not represent these detail.
|
||||||
|
* <p>
|
||||||
|
* In this program, this field must be written as a annotation of corresponding
|
||||||
|
* function.
|
||||||
|
*/
|
||||||
public String mVarDesc;
|
public String mVarDesc;
|
||||||
|
|
||||||
public ExpFctParamDecl() {
|
public ExpFctParamDecl() {
|
||||||
|
|
|
@ -39,19 +39,29 @@ public class PythonWriter {
|
||||||
return Collections.unmodifiableMap(cache);
|
return Collections.unmodifiableMap(cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String pythonTypeGetter(ExpFctParamDecl paramdecl) {
|
private static String pythonTypeGetter(ExpFctParamDecl paramdecl) throws IllegalArgumentException {
|
||||||
VariableType vt = paramdecl.mVarType;
|
VariableType vt = paramdecl.mVarType;
|
||||||
if (!paramdecl.mIsInput) {
|
if (!paramdecl.mIsInput) {
|
||||||
vt = vt.getPointerOfThis();
|
vt = vt.getPointerOfThis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create string builder for build final type string
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
|
// add type prefix
|
||||||
sb.append("bm_");
|
sb.append("bm_");
|
||||||
sb.append(g_CppTypeMap.get(vt.getBaseType()));
|
// try getting cpp type from base type
|
||||||
|
String cpp_type = g_CppTypeMap.get(vt.getBaseType());
|
||||||
|
if (cpp_type == null) {
|
||||||
|
throw new IllegalArgumentException("Unexpected type: " + vt.toCType());
|
||||||
|
}
|
||||||
|
// assign cpp type
|
||||||
|
sb.append(cpp_type);
|
||||||
|
// add pointer suffix
|
||||||
if (vt.isPointer()) {
|
if (vt.isPointer()) {
|
||||||
sb.append("_");
|
sb.append("_");
|
||||||
sb.append(String.join("", Collections.nCopies(vt.getPointerLevel(), "p")));
|
sb.append(String.join("", Collections.nCopies(vt.getPointerLevel(), "p")));
|
||||||
}
|
}
|
||||||
|
// return built type string.
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,28 +2,51 @@ import java.util.Collections;
|
||||||
import java.util.Vector;
|
import java.util.Vector;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class represent the type of each parameters and function return value.
|
||||||
|
*/
|
||||||
public class VariableType {
|
public class VariableType {
|
||||||
/**
|
/**
|
||||||
* The base type of this variable which remove all ending stars. Each item is a
|
* The base type of this variable removing all ending stars (remove all pointer
|
||||||
* part of namespace string. If no namespace, this Vector will only have one
|
* levels) Each item in this a part of namespace and the last one must be the
|
||||||
* item.
|
* type itself (without any namespace restriction). If no namespace restriction
|
||||||
|
* for this type, this Vector will only have one item.
|
||||||
|
* <p>
|
||||||
|
* For end user, it is enough that knowing the last item is type itself.
|
||||||
*/
|
*/
|
||||||
private Vector<String> mBaseType;
|
private Vector<String> mBaseType;
|
||||||
/**
|
/**
|
||||||
* The pointer level of this type. It is equal with the count of stars.
|
* The pointer level of this type. It is equal to the count of trailing star of
|
||||||
|
* this field in C style representation.
|
||||||
*/
|
*/
|
||||||
private int mPointerLevel;
|
private int mPointerLevel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct an empty varible type. This is commonly used constructor.
|
||||||
|
*/
|
||||||
public VariableType() {
|
public VariableType() {
|
||||||
mBaseType = new Vector<String>();
|
mBaseType = new Vector<String>();
|
||||||
mPointerLevel = 0;
|
mPointerLevel = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The constructor used for cloning self. This constructor is only can be used
|
||||||
|
* by self.
|
||||||
|
*
|
||||||
|
* @param base_type The hierarchy of the variable type.
|
||||||
|
* @param pointer_level The pointer level of new created variable type.
|
||||||
|
*/
|
||||||
private VariableType(Vector<String> base_type, int pointer_level) {
|
private VariableType(Vector<String> base_type, int pointer_level) {
|
||||||
mBaseType = (Vector<String>) base_type.clone();
|
mBaseType = (Vector<String>) base_type.clone();
|
||||||
mPointerLevel = pointer_level;
|
mPointerLevel = pointer_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set this variable type with a type string in C/C++ style. For example
|
||||||
|
* "NSTest::NSTest2::MyType**".
|
||||||
|
*
|
||||||
|
* @param ctype The type string in C/C++ style.
|
||||||
|
*/
|
||||||
public void fromCType(String ctype) {
|
public void fromCType(String ctype) {
|
||||||
if (ctype.isEmpty())
|
if (ctype.isEmpty())
|
||||||
throw new IllegalArgumentException("empty string can not be parsed.");
|
throw new IllegalArgumentException("empty string can not be parsed.");
|
||||||
|
@ -51,31 +74,78 @@ public class VariableType {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a type string represented by this variable type in C/C++ style.
|
||||||
|
*
|
||||||
|
* @return The type string in C/C++ style.
|
||||||
|
*/
|
||||||
public String toCType() {
|
public String toCType() {
|
||||||
return mBaseType.stream().collect(Collectors.joining("::"))
|
return mBaseType.stream().collect(Collectors.joining("::"))
|
||||||
+ String.join("", Collections.nCopies(mPointerLevel, "*"));
|
+ String.join("", Collections.nCopies(mPointerLevel, "*"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the base type of this variable type without any namespace. It just simply
|
||||||
|
* get the last entry in type hierarchy.
|
||||||
|
*
|
||||||
|
* @return The base type string without namespace prefix.
|
||||||
|
*/
|
||||||
public String getBaseType() {
|
public String getBaseType() {
|
||||||
return mBaseType.lastElement();
|
return mBaseType.lastElement();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether this variable type is a pointer. This function just check
|
||||||
|
* whether the pointer level of this variavle type is zero.
|
||||||
|
*
|
||||||
|
* @return True if it is pointer, otherwise false.
|
||||||
|
*/
|
||||||
public boolean isPointer() {
|
public boolean isPointer() {
|
||||||
return mPointerLevel != 0;
|
return mPointerLevel != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the pointer level of this variable type. You can simply assume the
|
||||||
|
* pointer level is equal to the count of trailing star.
|
||||||
|
*
|
||||||
|
* @return The pointer level integer. Zero means that this type is not a
|
||||||
|
* pointer.
|
||||||
|
*/
|
||||||
public int getPointerLevel() {
|
public int getPointerLevel() {
|
||||||
return mPointerLevel;
|
return mPointerLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the clone of the type hierarchy of this variable type.
|
||||||
|
* <p>
|
||||||
|
* It is rarely used. This only should be used when you need the namespace
|
||||||
|
* hierarchy of this variable type.
|
||||||
|
*
|
||||||
|
* @return The clone of current variable type hierarchy.
|
||||||
|
*/
|
||||||
public Vector<String> getBaseTypeHierarchy() {
|
public Vector<String> getBaseTypeHierarchy() {
|
||||||
return (Vector<String>) mBaseType.clone();
|
return (Vector<String>) mBaseType.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether this type is a valid one. It actually check whether type
|
||||||
|
* hierarchy include at least one entry.
|
||||||
|
*
|
||||||
|
* @return True if no problem of this type, otherwise false.
|
||||||
|
*/
|
||||||
public boolean isValid() {
|
public boolean isValid() {
|
||||||
return mBaseType.size() != 0;
|
return mBaseType.size() != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a new created variable type which is the pointer of this variable
|
||||||
|
* type.
|
||||||
|
* <p>
|
||||||
|
* In internal implementation, it just create a clone of current variable type
|
||||||
|
* with the increase of pointer level by 1.
|
||||||
|
*
|
||||||
|
* @return The new created pointer type of this variable type.
|
||||||
|
*/
|
||||||
public VariableType getPointerOfThis() {
|
public VariableType getPointerOfThis() {
|
||||||
return new VariableType(mBaseType, mPointerLevel + 1);
|
return new VariableType(mBaseType, mPointerLevel + 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,9 @@ This project welcome everyone's contribution, except the employee of Dassault, w
|
||||||
The aim of this project is creating a universal library which can read / write CMO files or any other Virtools files without any Virtools dependencies.
|
The aim of this project is creating a universal library which can read / write CMO files or any other Virtools files without any Virtools dependencies.
|
||||||
This project will not link any original Virtools dynamic library. So this project can be ported to any platform if the compiler supports.
|
This project will not link any original Virtools dynamic library. So this project can be ported to any platform if the compiler supports.
|
||||||
This project only involving specific Virtools version, 2.1. Other Virtools versions are not considered by this project.
|
This project only involving specific Virtools version, 2.1. Other Virtools versions are not considered by this project.
|
||||||
This project is based on reverse work of CK2.dll, VxMath.dll and CK2_3D.dll. The program [unvirt](https://aluigi.altervista.org/papers.htm#unvirt) created by Luigi Auriemma, which is licensed by GPL-v2, also help my work.
|
This project is based on reverse work of `CK2.dll`, `VxMath.dll` and `CK2_3D.dll`. The program [unvirt](https://aluigi.altervista.org/papers.htm#unvirt) created by Luigi Auriemma, which is licensed by GPL-v2, also help my work.
|
||||||
|
|
||||||
**The difference between this project and other Virtools libraries, is that we are not focusing on re-creating the whole Virtools engine. We only focus on the Virtools files RW, and we only just implement a minimalist Virtools environment for achieving this.**
|
**The difference between this project and other Virtools libraries (e.g. [doyaGu/CK2](https://github.com/doyaGu/CK2)), is that we are not focusing on re-creating the whole Virtools engine. We only focus on the Virtools files RW, and we only just implement a minimalist Virtools environment for achieving this.**
|
||||||
|
|
||||||
## Goals
|
## Goals
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ These features explicitly will not be merged.
|
||||||
|
|
||||||
This project require:
|
This project require:
|
||||||
|
|
||||||
* The compiler supporting C++20
|
* The compiler supporting C++ 20
|
||||||
* Littile-endian architecture system.
|
* Littile-endian architecture system.
|
||||||
* zlib
|
* zlib
|
||||||
* [stb](https://github.com/nothings/stb) (For image read / write)
|
* [stb](https://github.com/nothings/stb) (For image read / write)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user