Blame |
Last modification |
View Log
| RSS feed
#region --- License ---
/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos
* See license.txt for license info
*/
#endregion
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.XPath;
namespace Bind
.Structures
{
public class Type
: IComparable
<Type
>
{
internal static Dictionary
<string,
string> GLTypes
;
internal static Dictionary
<string,
string> CSTypes
;
private static bool typesLoaded
;
string current_qualifier
= "", previous_qualifier
= "";
#region internal static void Initialize(string glTypes, string csTypes)
internal static void Initialize
(string glTypes,
string csTypes
)
{
if (!typesLoaded
)
{
if (GLTypes
== null)
{
using (StreamReader sr
= Utilities
.OpenSpecFile(Settings
.InputPath, glTypes
))
{
GLTypes
= MainClass
.Generator.ReadTypeMap(sr
);
}
}
if (CSTypes
== null)
{
using (StreamReader sr
= Utilities
.OpenSpecFile(Settings
.InputPath, csTypes
))
{
CSTypes
= MainClass
.Generator.ReadCSTypeMap(sr
);
}
}
typesLoaded
= true;
}
}
#endregion
#region --- Constructors ---
public Type
()
{
}
public Type
(Type t
)
{
if (t
!= null)
{
QualifiedType
= t
.QualifiedType; // Covers current type and qualifier
PreviousType
= t
.PreviousType;
PreviousQualifier
= t
.PreviousQualifier;
WrapperType
= t
.WrapperType;
Array
= t
.Array;
Pointer
= t
.Pointer;
Reference
= t
.Reference;
ElementCount
= t
.ElementCount;
}
}
#endregion
public string CurrentQualifier
{
get
{ return current_qualifier
; }
set
{ PreviousQualifier
= CurrentQualifier
; current_qualifier
= value
; }
}
public string PreviousQualifier
{
get
{ return previous_qualifier
; }
private set
{ previous_qualifier
= value
; }
}
public string QualifiedType
{
get
{
if (!String.IsNullOrEmpty(CurrentQualifier
))
return String.Format("{0}.{1}", CurrentQualifier, CurrentType
);
else
return CurrentType
;
}
set
{
if (String.IsNullOrEmpty(value
))
throw new ArgumentException
();
int qualifier_end
= value
.LastIndexOf('.');
if (qualifier_end
> -1)
{
CurrentQualifier
= value
.Substring(0, qualifier_end
);
CurrentType
= value
.Substring(qualifier_end
+ 1);
}
else
{
CurrentType
= value
;
}
}
}
#region public string CurrentType
string type
;
/// <summary>
/// Gets the type of the parameter.
/// </summary>
public virtual string CurrentType
{
//get { return _type; }
get
{
if (((Settings
.Compatibility & Settings
.Legacy.TurnVoidPointersToIntPtr) != Settings
.Legacy.None) && Pointer
!= 0 && type
.Contains("void"))
return "IntPtr";
return type
;
}
set
{
if (String.IsNullOrEmpty(value
))
throw new ArgumentException
();
if (!String.IsNullOrEmpty(type
))
PreviousType
= type
;
if (!String.IsNullOrEmpty(value
))
type
= value
.Trim();
while (type
.EndsWith("*"))
{
type
= type
.Substring(0, type
.Length - 1);
Pointer
++;
}
}
}
#endregion
#region public string PreviousType
private string _previous_type
;
public string PreviousType
{
get
{ return _previous_type
; }
private set
{ _previous_type
= value
; }
}
#endregion
#region public bool Reference
bool reference
;
public bool Reference
{
get
{ return reference
; }
set
{ reference
= value
; }
}
#endregion
#region public int Array
int array
;
public int Array
{
get
{ return array
; }
set
{ array
= value
> 0 ? value
: 0; }
}
#endregion
#region public int ElementCount
int element_count
;
// If the type is an array and ElementCount > 0, then ElemenCount defines the expected array length.
public int ElementCount
{
get
{ return element_count
; }
set
{ element_count
= value
> 0 ? value
: 0; }
}
#endregion
#region public int Pointer
int pointer
;
public int Pointer
{
get
{ return pointer
; }
set
{ pointer
= value
> 0 ? value
: 0; }
}
#endregion
// Returns true if parameter is an enum.
public bool IsEnum
{
get
{
return Enum.GLEnums.ContainsKey(CurrentType
) ||
Enum.AuxEnums.ContainsKey(CurrentType
);
}
}
#region IndirectionLevel
// Gets the the level of indirection for this type. For example,
// type 'foo' has indirection level = 0, while 'ref foo*[]' has
// an indirection level of 3.
public int IndirectionLevel
{
get
{ return Pointer
+ Array
+ (Reference
? 1 : 0); }
}
#endregion
#region public bool CLSCompliant
public bool CLSCompliant
{
get
{
bool compliant
= true;
switch (CurrentType
.ToLower())
{
case "sbyte":
case "ushort":
case "uint":
case "ulong":
case "uintptr":
case "uint16":
case "uint32":
case "uint64":
compliant
= false;
break;
default:
compliant
= Pointer
== 0;
break;
}
return compliant
;
/*
if (Pointer != 0)
{
compliant &= CurrentType.Contains("IntPtr"); // IntPtr's are CLSCompliant.
// If the NoPublicUnsageFunctions is set, the pointer will be CLSCompliant.
compliant |= (Settings.Compatibility & Settings.Legacy.NoPublicUnsafeFunctions) != Settings.Legacy.None;
}
return compliant;
*/
//return compliant && (!Pointer || CurrentType.Contains("IntPtr"));
//return compliant && !(Pointer && ((Settings.Compatibility & Settings.Legacy.NoPublicUnsafeFunctions) == Settings.Legacy.None));
/*
* return !(
(Pointer && ((Settings.Compatibility & Settings.Legacy.NoPublicUnsafeFunctions) == Settings.Legacy.None ) ||
CurrentType.Contains("UInt") ||
CurrentType.Contains("SByte")));
*/
/*(Type.Contains("GLu") && !Type.Contains("GLubyte")) ||
Type == "GLbitfield" ||
Type.Contains("GLhandle") ||
Type.Contains("GLhalf") ||
Type == "GLbyte");*/
}
}
#endregion
#region public bool Unsigned
public bool Unsigned
{
get
{
return (CurrentType
.Contains("UInt") || CurrentType
.Contains("Byte"));
}
}
#endregion
#region public WrapperTypes WrapperType
private WrapperTypes _wrapper_type
= WrapperTypes
.None;
public WrapperTypes WrapperType
{
get
{ return _wrapper_type
; }
set
{ _wrapper_type
= value
; }
}
#endregion
#region public string GetCLSCompliantType()
public string GetCLSCompliantType
()
{
if (!CLSCompliant
)
{
if (Pointer
!= 0 && Settings
.Compatibility == Settings
.Legacy.Tao)
return "IntPtr";
switch (CurrentType
)
{
case "UInt16":
case "ushort":
return "Int16";
case "UInt32":
case "uint":
return "Int32";
case "UInt64":
case "ulong":
return "Int64";
case "SByte":
case "sbyte":
return "Byte";
case "UIntPtr":
return "IntPtr";
}
}
return CurrentType
;
}
#endregion
#region public override string ToString()
public override string ToString
()
{
return QualifiedType
;
}
#endregion
#region public virtual void Translate(XPathNavigator overrides, string category)
public virtual void Translate
(XPathNavigator overrides,
string category
)
{
Enum @
enum;
string s
;
// Try to find out if it is an enum. If the type exists in the normal GLEnums list, use this.
// Otherwise, try to find it in the aux enums list. If it exists in neither, it is not an enum.
// Special case for Boolean - it is an enum, but it is dumb to use that instead of the 'bool' type.
bool normal
= false;
bool aux
= false;
normal
= Enum.GLEnums.TryGetValue(CurrentType,
out @
enum);
if (!normal
)
aux
= Enum.AuxEnums != null && Enum.AuxEnums.TryGetValue(CurrentType,
out @
enum);
// Translate enum types
if ((normal
|| aux
) && @
enum.Name != "GLenum" && @
enum.Name != "Boolean")
{
if ((Settings
.Compatibility & Settings
.Legacy.ConstIntEnums) != Settings
.Legacy.None)
QualifiedType
= "int";
else
{
#warning "Unecessary code"
if (normal
)
QualifiedType
= CurrentType
.Insert(0,
String.Format("{0}.", Settings
.EnumsOutput));
else if (aux
)
QualifiedType
= CurrentType
.Insert(0,
String.Format("{0}.", Settings
.EnumsAuxOutput));
}
}
else if (GLTypes
.TryGetValue(CurrentType,
out s
))
{
// Check if the parameter is a generic GLenum. If it is, search for a better match,
// otherwise fallback to Settings.CompleteEnumName (named 'All' by default).
if (s
.Contains("GLenum") /*&& !String.IsNullOrEmpty(category)*/)
{
if ((Settings
.Compatibility & Settings
.Legacy.ConstIntEnums) != Settings
.Legacy.None)
{
QualifiedType
= "int";
}
else
{
// Better match: enum.Name == function.Category (e.g. GL_VERSION_1_1 etc)
if (Enum.GLEnums.ContainsKey(category
))
{
QualifiedType
= String.Format("{0}.{1}", Settings
.EnumsOutput,
Enum.TranslateName(category
));
}
else
{
QualifiedType
= String.Format("{0}.{1}", Settings
.EnumsOutput, Settings
.CompleteEnumName);
}
}
}
else
{
// A few translations for consistency
switch (CurrentType
.ToLower())
{
case "string": QualifiedType
= "String"; break;
}
#warning "Stale code"
// This is not enum, default translation:
if (CurrentType
== "PIXELFORMATDESCRIPTOR" || CurrentType
== "LAYERPLANEDESCRIPTOR" ||
CurrentType
== "GLYPHMETRICSFLOAT")
{
if (Settings
.Compatibility == Settings
.Legacy.Tao)
CurrentType
= CurrentType
.Insert(0,
"Gdi.");
else
{
if (CurrentType
== "PIXELFORMATDESCRIPTOR")
CurrentType
= "PixelFormatDescriptor";
else if (CurrentType
== "LAYERPLANEDESCRIPTOR")
CurrentType
= "LayerPlaneDescriptor";
else if (CurrentType
== "GLYPHMETRICSFLOAT")
CurrentType
= "GlyphMetricsFloat";
}
}
else if (CurrentType
== "XVisualInfo")
{
//p.Pointer = false;
//p.Reference = true;
}
else
QualifiedType
= s
;
}
}
CurrentType
=
CSTypes
.ContainsKey(CurrentType
) ?
CSTypes
[CurrentType
] : CurrentType
;
// Make sure that enum parameters follow enum overrides, i.e.
// if enum ErrorCodes is overriden to ErrorCode, then parameters
// of type ErrorCodes should also be overriden to ErrorCode.
XPathNavigator enum_override
= overrides
.SelectSingleNode(String.Format("/overrides/replace/enum[@name='{0}']/name", CurrentType
));
if (enum_override
!= null)
{
// For consistency - many overrides use string instead of String.
if (enum_override
.Value == "string")
QualifiedType
= "String";
else if (enum_override
.Value == "StringBuilder")
QualifiedType
= "StringBuilder";
else
CurrentType
= enum_override
.Value;
}
if (CurrentType
== "IntPtr" && String.IsNullOrEmpty(PreviousType
))
Pointer
= 0;
}
#endregion
#region IComparable<Type> Members
public int CompareTo
(Type other
)
{
// Make sure that Pointer parameters are sorted last to avoid bug [#1098].
// The rest of the comparisons are not important, but they are there to
// guarantee a stable order between program executions.
int result
= this.CurrentType.CompareTo(other
.CurrentType);
if (result
== 0)
result
= Pointer
.CompareTo(other
.Pointer);
if (result
== 0)
result
= Reference
.CompareTo(other
.Reference);
if (result
== 0)
result
= Array
.CompareTo(other
.Array);
if (result
== 0)
result
= CLSCompliant
.CompareTo(other
.CLSCompliant);
if (result
== 0)
result
= ElementCount
.CompareTo(other
.ElementCount);
return result
;
}
#endregion
}
}