mirror of https://github.com/mono/CppSharp.git
c-sharpdotnetmonobindingsbridgecclangcpluspluscppsharpglueinteropparserparsingpinvokeswigsyntax-treevisitorsxamarinxamarin-bindings
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
450 lines
14 KiB
450 lines
14 KiB
namespace CppSharp.AST.Extensions |
|
{ |
|
public static class TypeExtensions |
|
{ |
|
public static bool IsPrimitiveType(this Type t) |
|
{ |
|
PrimitiveType type; |
|
return t.IsPrimitiveType(out type); |
|
} |
|
|
|
public static bool IsPrimitiveType(this Type t, out PrimitiveType primitive) |
|
{ |
|
var builtin = t.Desugar() as BuiltinType; |
|
if (builtin != null) |
|
{ |
|
primitive = builtin.Type; |
|
return true; |
|
} |
|
|
|
primitive = PrimitiveType.Null; |
|
return false; |
|
} |
|
|
|
public static bool IsPrimitiveType(this Type t, PrimitiveType primitive) |
|
{ |
|
PrimitiveType type; |
|
if (!t.IsPrimitiveType(out type)) |
|
return false; |
|
|
|
return primitive == type; |
|
} |
|
|
|
public static bool IsEnumType(this Type t) |
|
{ |
|
var tag = t.Desugar() as TagType; |
|
|
|
if (tag == null) |
|
return false; |
|
|
|
return tag.Declaration is Enumeration; |
|
} |
|
|
|
public static bool IsAddress(this Type t) |
|
{ |
|
return t.IsPointer() || t.IsReference(); |
|
} |
|
|
|
public static bool IsPointer(this Type t) |
|
{ |
|
var functionPointer = t as MemberPointerType; |
|
if (functionPointer != null) |
|
return true; |
|
var pointer = t as PointerType; |
|
if (pointer == null) |
|
return false; |
|
return pointer.Modifier == PointerType.TypeModifier.Pointer; |
|
} |
|
|
|
public static bool IsReference(this Type t) |
|
{ |
|
var pointer = t as PointerType; |
|
if (pointer == null) |
|
return false; |
|
return pointer.IsReference; |
|
} |
|
|
|
public static bool IsPointerToPrimitiveType(this Type t) |
|
{ |
|
var ptr = t as PointerType; |
|
if (ptr == null) |
|
return false; |
|
PrimitiveType primitiveType; |
|
return ptr.Pointee.IsPrimitiveType(out primitiveType); |
|
} |
|
|
|
public static bool IsPointerToPrimitiveType(this Type t, out PrimitiveType primitive) |
|
{ |
|
var ptr = t as PointerType; |
|
if (ptr == null) |
|
{ |
|
primitive = PrimitiveType.Null; |
|
return false; |
|
} |
|
return ptr.Pointee.IsPrimitiveType(out primitive); |
|
} |
|
|
|
public static bool IsPointerToPrimitiveType(this Type t, PrimitiveType primitive) |
|
{ |
|
var ptr = t as PointerType; |
|
if (ptr == null) |
|
return false; |
|
return ptr.Pointee.IsPrimitiveType(primitive); |
|
} |
|
|
|
public static bool IsPointerTo<T>(this Type t, out T type) where T : Type |
|
{ |
|
var pointee = t.GetPointee(); |
|
type = pointee as T; |
|
if (type == null) |
|
{ |
|
var attributedType = pointee as AttributedType; |
|
if (attributedType != null) |
|
type = attributedType.Modified.Type as T; |
|
} |
|
return type != null; |
|
} |
|
|
|
public static bool IsClass(this Type t) |
|
{ |
|
Class @class; |
|
return t.TryGetClass(out @class); |
|
} |
|
|
|
public static bool TryGetClass(this Type t, out Class @class, Class value = null) |
|
{ |
|
return TryGetDeclaration(t, out @class, value); |
|
} |
|
|
|
public static bool TryGetDeclaration<T>(this Type t, out T decl, T value = null) where T : Declaration |
|
{ |
|
t = t.Desugar(); |
|
|
|
TagType tagType = null; |
|
var type = t as TemplateSpecializationType; |
|
if (type != null) |
|
{ |
|
if (type.IsDependent) |
|
{ |
|
if (type.Template is TypeAliasTemplate) |
|
{ |
|
type.Desugared.Type.TryGetDeclaration(out decl, value); |
|
decl = decl as T; |
|
return decl != null; |
|
} |
|
|
|
var classTemplate = type.Template as ClassTemplate; |
|
if (classTemplate != null) |
|
{ |
|
var templatedClass = classTemplate.TemplatedClass; |
|
decl = templatedClass.CompleteDeclaration == null |
|
? templatedClass as T |
|
: (T) templatedClass.CompleteDeclaration; |
|
if (decl != null) |
|
{ |
|
if (value != null) |
|
type.Template = new ClassTemplate { TemplatedDecl = value }; |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
var templateTemplateParameter = type.Template as TemplateTemplateParameter; |
|
if (templateTemplateParameter != null) |
|
return (decl = templateTemplateParameter.TemplatedDecl as T) != null; |
|
} |
|
tagType = (type.Desugared.Type.GetFinalPointee() ?? type.Desugared.Type) as TagType; |
|
} |
|
else |
|
{ |
|
tagType = t as TagType; |
|
} |
|
|
|
if (tagType != null) |
|
{ |
|
decl = tagType.Declaration as T; |
|
if (decl != null) |
|
{ |
|
if (value != null) |
|
tagType.Declaration = value; |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
decl = null; |
|
return false; |
|
} |
|
|
|
public static bool IsEnum(this Type t) |
|
{ |
|
Enumeration @enum; |
|
return t.TryGetEnum(out @enum); |
|
} |
|
|
|
public static bool TryGetEnum(this Type t, out Enumeration @enum) |
|
{ |
|
var tag = t.Desugar() as TagType; |
|
|
|
if (tag == null) |
|
{ |
|
@enum = null; |
|
return false; |
|
} |
|
|
|
@enum = tag.Declaration as Enumeration; |
|
return @enum != null; |
|
} |
|
|
|
public static Type Desugar(this Type t, bool resolveTemplateSubstitution = true) |
|
{ |
|
var typeDef = t as TypedefType; |
|
if (typeDef != null) |
|
{ |
|
var decl = typeDef.Declaration.Type; |
|
if (decl != null) |
|
return decl.Desugar(resolveTemplateSubstitution); |
|
} |
|
|
|
if (resolveTemplateSubstitution) |
|
{ |
|
var substType = t as TemplateParameterSubstitutionType; |
|
if (substType != null) |
|
{ |
|
var replacement = substType.Replacement.Type; |
|
if (replacement != null) |
|
return replacement.Desugar(resolveTemplateSubstitution); |
|
} |
|
} |
|
|
|
var injectedType = t as InjectedClassNameType; |
|
if (injectedType != null) |
|
{ |
|
if (injectedType.InjectedSpecializationType.Type != null) |
|
return injectedType.InjectedSpecializationType.Type.Desugar( |
|
resolveTemplateSubstitution); |
|
return new TagType(injectedType.Class); |
|
} |
|
|
|
var attributedType = t as AttributedType; |
|
if (attributedType != null) |
|
return attributedType.Equivalent.Type.Desugar(resolveTemplateSubstitution); |
|
|
|
return t; |
|
} |
|
|
|
public static Type SkipPointerRefs(this Type t) |
|
{ |
|
var type = t as PointerType; |
|
|
|
if (type != null) |
|
{ |
|
var pointee = type.Pointee; |
|
|
|
if (type.IsReference()) |
|
return pointee.Desugar().SkipPointerRefs(); |
|
} |
|
|
|
return t; |
|
} |
|
|
|
/// <summary> |
|
/// If t is a pointer type the type pointed to by t will be returned. |
|
/// Otherwise null. |
|
/// </summary> |
|
public static Type GetPointee(this Type t) |
|
{ |
|
var ptr = t as PointerType; |
|
if (ptr != null) |
|
return ptr.Pointee; |
|
var memberPtr = t as MemberPointerType; |
|
if (memberPtr != null) |
|
return memberPtr.QualifiedPointee.Type; |
|
return null; |
|
} |
|
|
|
/// <summary> |
|
/// If t is a pointer type the type pointed to by t will be returned |
|
/// after fully dereferencing it. Otherwise null. |
|
/// For example int** -> int. |
|
/// </summary> |
|
public static Type GetFinalPointee(this Type t) |
|
{ |
|
var finalPointee = t.GetPointee(); |
|
var pointee = finalPointee; |
|
while (pointee != null) |
|
{ |
|
pointee = pointee.GetPointee(); |
|
if (pointee != null) |
|
finalPointee = pointee; |
|
} |
|
return finalPointee; |
|
} |
|
|
|
/// <summary> |
|
/// If t is a pointer type the type pointed to by t will be returned. |
|
/// Otherwise the default qualified type. |
|
/// </summary> |
|
public static QualifiedType GetQualifiedPointee(this Type t) |
|
{ |
|
var ptr = t as PointerType; |
|
if (ptr != null) |
|
return ptr.QualifiedPointee; |
|
var memberPtr = t as MemberPointerType; |
|
if (memberPtr != null) |
|
return memberPtr.QualifiedPointee; |
|
return new QualifiedType(); |
|
} |
|
|
|
/// <summary> |
|
/// If t is a pointer type the type pointed to by t will be returned |
|
/// after fully dereferencing it. Otherwise the default qualified type. |
|
/// For example int** -> int. |
|
/// </summary> |
|
public static QualifiedType GetFinalQualifiedPointee(this Type t) |
|
{ |
|
var finalPointee = t.GetQualifiedPointee(); |
|
var pointee = finalPointee; |
|
while (pointee.Type != null) |
|
{ |
|
pointee = pointee.Type.GetQualifiedPointee(); |
|
if (pointee.Type != null) |
|
finalPointee = pointee; |
|
} |
|
return finalPointee; |
|
} |
|
|
|
public static PointerType GetFinalPointer(this Type t) |
|
{ |
|
var type = t as PointerType; |
|
|
|
if (type == null) |
|
return null; |
|
|
|
var pointee = type.Desugar().GetPointee(); |
|
|
|
if (pointee.IsPointer()) |
|
return pointee.GetFinalPointer(); |
|
|
|
return type; |
|
} |
|
|
|
public static bool ResolvesTo(this QualifiedType type, QualifiedType other) |
|
{ |
|
if (!type.Qualifiers.Equals(other.Qualifiers)) |
|
return false; |
|
|
|
var left = type.Type.Desugar(); |
|
var right = other.Type.Desugar(); |
|
var leftPointer = left as PointerType; |
|
var rightPointer = right as PointerType; |
|
if (leftPointer != null && rightPointer != null) |
|
{ |
|
return leftPointer.Modifier == rightPointer.Modifier && |
|
leftPointer.QualifiedPointee.ResolvesTo(rightPointer.QualifiedPointee); |
|
} |
|
return left.Equals(right); |
|
} |
|
|
|
public static bool IsConstRef(this QualifiedType type) |
|
{ |
|
Type desugared = type.Type.Desugar(); |
|
return desugared.IsReference() && type.IsConst(); |
|
} |
|
|
|
public static bool IsConstRefToPrimitive(this QualifiedType type) |
|
{ |
|
Type desugared = type.Type.Desugar(); |
|
Type pointee = desugared.GetFinalPointee().Desugar(); |
|
pointee = (pointee.GetFinalPointee() ?? pointee).Desugar(); |
|
return desugared.IsReference() && |
|
(pointee.IsPrimitiveType() || pointee.IsEnum()) && type.IsConst(); |
|
} |
|
|
|
public static bool IsConst(this QualifiedType type) |
|
{ |
|
return type.Type != null && (type.Qualifiers.IsConst || |
|
type.Type.GetQualifiedPointee().IsConst()); |
|
} |
|
|
|
public static QualifiedType StripConst(this QualifiedType type) |
|
{ |
|
var qualifiers = type.Qualifiers; |
|
qualifiers.IsConst = false; |
|
type.Qualifiers = qualifiers; |
|
|
|
var ptr = type.Type as PointerType; |
|
if (ptr != null) |
|
{ |
|
var pointee = ptr.QualifiedPointee; |
|
var pointeeQualifiers = pointee.Qualifiers; |
|
pointeeQualifiers.IsConst = false; |
|
pointee.Qualifiers = pointeeQualifiers; |
|
ptr.QualifiedPointee = pointee; |
|
} |
|
|
|
return type; |
|
} |
|
|
|
public static bool IsConstCharString(this Type type) |
|
{ |
|
var desugared = type.Desugar(); |
|
|
|
if (!(desugared is PointerType)) |
|
return false; |
|
|
|
var pointer = desugared as PointerType; |
|
return IsConstCharString(pointer); |
|
} |
|
|
|
public static bool IsConstCharString(this PointerType pointer) |
|
{ |
|
if (pointer.IsReference) |
|
return false; |
|
|
|
var pointee = pointer.Pointee.Desugar(); |
|
|
|
return (pointee.IsPrimitiveType(PrimitiveType.Char) || |
|
pointee.IsPrimitiveType(PrimitiveType.Char16) || |
|
pointee.IsPrimitiveType(PrimitiveType.Char32) || |
|
pointee.IsPrimitiveType(PrimitiveType.WideChar)) && |
|
pointer.QualifiedPointee.Qualifiers.IsConst; |
|
} |
|
|
|
public static bool IsDependentPointer(this Type type) |
|
{ |
|
var desugared = type.Desugar(); |
|
if (desugared.IsAddress()) |
|
{ |
|
var pointee = desugared.GetFinalPointee().Desugar(); |
|
return pointee.IsDependent |
|
&& !(pointee is TemplateSpecializationType) |
|
&& !(pointee is InjectedClassNameType); |
|
} |
|
return false; |
|
} |
|
|
|
public static Module GetModule(this Type type) |
|
{ |
|
Declaration declaration; |
|
if (!(type.GetFinalPointee() ?? type).TryGetDeclaration(out declaration)) |
|
return null; |
|
|
|
declaration = declaration.CompleteDeclaration ?? declaration; |
|
if (declaration.Namespace == null || declaration.TranslationUnit.Module == null) |
|
return null; |
|
|
|
return declaration.TranslationUnit.Module; |
|
} |
|
|
|
public static long GetSizeInBytes(this ArrayType array) |
|
{ |
|
return GetSizeInBits(array) / 8; |
|
} |
|
|
|
public static long GetSizeInBits(this ArrayType array) |
|
{ |
|
return array.Size * array.ElementSize; |
|
} |
|
} |
|
} |