#region --- License --- /* Copyright (c) 2006, 2007 Stefanos Apostolopoulos * See license.txt for license info */ #endregion using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; namespace Bind.Structures { /// /// Represents a single parameter of an opengl function. /// public class Parameter : Type { string cache; bool rebuild; bool unsafe_allowed; // True if the cache may contain unsafe types, false otherwise. #region Constructors /// /// Creates a new Parameter without type and name. /// public Parameter() :base() { } /// /// Creates a new parameter from the parameters passed (deep copy). /// /// The parameter to copy from. public Parameter(Parameter p) : base(p) { if (p == null) return; this.Name = p.Name; this.Unchecked = p.Unchecked; this.UnmanagedType = p.UnmanagedType; this.Flow = p.Flow; this.cache = p.cache; //this.rebuild = false; } #endregion #region public string Name string _name = String.Empty; /// /// Gets or sets the name of the parameter. /// public string Name { get { return _name; } set { if (_name != value) { _name = value; rebuild = true; } } } #endregion #region UnmanagedType property UnmanagedType _unmanaged_type; /// /// Gets or sets the name of the parameter. /// private UnmanagedType UnmanagedType { get { return _unmanaged_type; } set { if (_unmanaged_type != value) { _unmanaged_type = value; rebuild = true; } } } #endregion #region public FlowDirection Flow /// /// Enumarates the possible flows of a parameter (ie. is this parameter /// used as input or as output?) /// public enum FlowDirection { Undefined = 0, In, Out } FlowDirection _flow; /// /// Gets or sets the flow of the parameter. /// public FlowDirection Flow { get { return _flow; } set { if (_flow != value) { _flow = value; rebuild = true; } } } #endregion #region public bool NeedsPin public bool NeedsPin { get { return (Array > 0 || Reference || CurrentType == "object") && !CurrentType.ToLower().Contains("string"); } } #endregion #region public bool Unchecked private bool _unchecked; public bool Unchecked { get { return _unchecked; } set { if (_unchecked != value) { _unchecked = value; rebuild = true; } } } #endregion #region public override string CurrentType public override string CurrentType { get { return base.CurrentType; } set { base.CurrentType = value; rebuild = true; } } #endregion public override string ToString() { return ToString(false); } #region public string ToString(bool override_unsafe_setting) public string ToString(bool override_unsafe_setting) { rebuild |= unsafe_allowed |= override_unsafe_setting; unsafe_allowed = override_unsafe_setting; if (!String.IsNullOrEmpty(cache) && !rebuild) { return cache; } else { StringBuilder sb = new StringBuilder(); if (Flow == FlowDirection.Out) sb.Append("[Out] "); else if (Flow == FlowDirection.Undefined) sb.Append("[In, Out] "); if (Reference) { if (Flow == FlowDirection.Out) sb.Append("out "); else sb.Append("ref "); } if (!override_unsafe_setting && ((Settings.Compatibility & Settings.Legacy.NoPublicUnsafeFunctions) != Settings.Legacy.None)) { if (Pointer) { sb.Append("IntPtr"); } else { sb.Append(CurrentType); if (Array > 0) sb.Append("[]"); } } else { sb.Append(CurrentType); if (Pointer) sb.Append("*"); if (Array > 0) sb.Append("[]"); } if (!String.IsNullOrEmpty(Name)) { sb.Append(" "); sb.Append(Utilities.Keywords.Contains(Name) ? "@" + Name : Name); } rebuild = false; cache = sb.ToString(); return cache; } } #endregion #region internal static Parameter Translate(Parameter par, string Category) internal static Parameter Translate(Parameter par, string Category) { Enum @enum; string s; Parameter p = new Parameter(par); // 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. bool normal = false; bool aux = false; normal = Enum.GLEnums.TryGetValue(p.CurrentType, out @enum); if (!normal) aux = Enum.AuxEnums != null && Enum.AuxEnums.TryGetValue(p.CurrentType, out @enum); // Translate enum types if ((normal || aux) && @enum.Name != "GLenum") { if ((Settings.Compatibility & Settings.Legacy.ConstIntEnums) != Settings.Legacy.None) { p.CurrentType = "int"; } else { if (normal) { p.CurrentType = p.CurrentType.Insert(0, String.Format("{0}.", Settings.NormalEnumsClass)); } else if (aux) { p.CurrentType = p.CurrentType.Insert(0, String.Format("{0}.", Settings.AuxEnumsClass)); } } } else if (Bind.Structures.Type.GLTypes.TryGetValue(p.CurrentType, out s)) { // Check if the parameter is a generic GLenum. If yes, // check if a better match exists: if (s.Contains("GLenum") && !String.IsNullOrEmpty(Category)) { if ((Settings.Compatibility & Settings.Legacy.ConstIntEnums) == Settings.Legacy.None) { // Better match: enum.Name == function.Category (e.g. GL_VERSION_1_1 etc) if (Enum.GLEnums.ContainsKey(Category)) { p.CurrentType = String.Format("{0}.{1}", Settings.NormalEnumsClass, Category); } else { p.CurrentType = String.Format("{0}.{1}", Settings.NormalEnumsClass, Settings.CompleteEnumName); } } else { p.CurrentType = "int"; } } else { // This is not enum, default translation: if (p.CurrentType == "PIXELFORMATDESCRIPTOR" || p.CurrentType == "LAYERPLANEDESCRIPTOR" || p.CurrentType == "GLYPHMETRICSFLOAT") { if (Settings.Compatibility == Settings.Legacy.Tao) { p.CurrentType = p.CurrentType.Insert(0, "Gdi."); } else { if (p.CurrentType == "PIXELFORMATDESCRIPTOR") p.CurrentType ="PixelFormatDescriptor"; else if (p.CurrentType == "LAYERPLANEDESCRIPTOR") p.CurrentType = "LayerPlaneDescriptor"; else if (p.CurrentType == "GLYPHMETRICSFLOAT") p.CurrentType = "GlyphMetricsFloat"; } } else if (p.CurrentType == "XVisualInfo") { //p.Pointer = false; //p.Reference = true; } else { p.CurrentType = s; } p.CurrentType = Bind.Structures.Type.CSTypes.ContainsKey(p.CurrentType) ? Bind.Structures.Type.CSTypes[p.CurrentType] : p.CurrentType; if (p.CurrentType == "IntPtr") { p.Pointer = false; } } } //if (CSTypes.ContainsKey(p.CurrentType)) // p.CurrentType = CSTypes[p.CurrentType]; // Translate pointer parameters if (p.Pointer || p.CurrentType == "IntPtr") { p.WrapperType = WrapperTypes.ArrayParameter; if (p.CurrentType.ToLower().Contains("char") || p.CurrentType.ToLower().Contains("string")) { // char* or string -> [In] String or [Out] StringBuilder p.CurrentType = p.Flow == Parameter.FlowDirection.Out ? "System.Text.StringBuilder" : "System.String"; p.Pointer = false; p.WrapperType = WrapperTypes.None; } else if (p.CurrentType.ToLower().Contains("void") || p.CurrentType.Contains("IntPtr")) { p.CurrentType = "IntPtr"; p.Pointer = false; p.WrapperType = WrapperTypes.GenericParameter; } } if (p.Reference) { p.WrapperType = WrapperTypes.ReferenceParameter; } if (p.CurrentType.ToLower().Contains("bool")) { // Is this actually used anywhere? p.WrapperType = WrapperTypes.BoolParameter; } return p; } #endregion } /// /// Holds the parameter list of an opengl function. /// public class ParameterCollection : List { string cache = String.Empty; string callStringCache = String.Empty; private bool rebuild = true; bool hasPointerParameters; bool hasReferenceParameters; bool unsafe_types_allowed; private bool Rebuild { get { return rebuild; } set { rebuild = value; } } #region Constructors public ParameterCollection() { } public ParameterCollection(ParameterCollection pc) { foreach (Parameter p in pc) { this.Add(new Parameter(p)); } } #endregion #region void BuildCache() void BuildCache() { BuildCallStringCache(); BuildToStringCache(unsafe_types_allowed); BuildReferenceAndPointerParametersCache(); Rebuild = false; } #endregion #region public bool HasPointerParameters public bool HasPointerParameters { get { if (!rebuild) { return hasPointerParameters; } else { BuildCache(); return hasPointerParameters; } } } #endregion #region public bool HasReferenceParameters public bool HasReferenceParameters { get { if (!Rebuild) { return hasReferenceParameters; } else { BuildCache(); return hasReferenceParameters; } } } #endregion #region void BuildReferenceAndPointerParametersCache() void BuildReferenceAndPointerParametersCache() { foreach (Parameter p in this) { if (p.Pointer || p.CurrentType.Contains("IntPtr")) hasPointerParameters = true; if (p.Reference) hasReferenceParameters = true; } } #endregion #region new public void Add(Parameter p) new public void Add(Parameter p) { Rebuild = true; base.Add(p); } #endregion public override string ToString() { return ToString(false); } #region public string ToString(bool override_unsafe_setting) /// /// Gets the parameter declaration string. /// /// If true, unsafe types will be used even if the Settings.Compatibility.NoPublicUnsafeFunctions flag is set. /// The parameter list of an opengl function in the form ( [parameters] ) public string ToString(bool override_unsafe_setting) { Rebuild |= unsafe_types_allowed != override_unsafe_setting; unsafe_types_allowed = override_unsafe_setting; if (!Rebuild) { return cache; } else { BuildCache(); return cache; } } #endregion #region void BuildToStringCache(bool override_unsafe_setting) void BuildToStringCache(bool override_unsafe_setting) { unsafe_types_allowed = override_unsafe_setting; StringBuilder sb = new StringBuilder(); sb.Append("("); if (this.Count > 0) { foreach (Parameter p in this) { sb.Append(p.ToString(override_unsafe_setting)); sb.Append(", "); } sb.Replace(", ", ")", sb.Length - 2, 2); } else sb.Append(")"); cache = sb.ToString(); } #endregion #region public string CallString() public string CallString() { if (!Rebuild) { return callStringCache; } else { BuildCache(); return callStringCache; } } #endregion #region private void BuildCallStringCache() /// /// Builds a call string instance and caches it. /// private void BuildCallStringCache() { StringBuilder sb = new StringBuilder(); sb.Append("("); if (this.Count > 0) { foreach (Parameter p in this) { if (p.Unchecked) sb.Append("unchecked((" + p.CurrentType + ")"); if (p.CurrentType != "object") { if (p.CurrentType.ToLower().Contains("string")) { sb.Append(String.Format("({0}{1})", p.CurrentType, (p.Array > 0) ? "[]" : "")); } else if (p.Pointer || p.Array > 0 || p.Reference) { if (((Settings.Compatibility & Settings.Legacy.TurnVoidPointersToIntPtr) != Settings.Legacy.None) && p.Pointer && p.CurrentType.Contains("void")) sb.Append("(IntPtr)"); else sb.Append(String.Format("({0}*)", p.CurrentType)); } else { sb.Append(String.Format("({0})", p.CurrentType)); } } sb.Append( Utilities.Keywords.Contains(p.Name) ? "@" + p.Name : p.Name ); if (p.Unchecked) sb.Append(")"); sb.Append(", "); } sb.Replace(", ", ")", sb.Length - 2, 2); } else { sb.Append(")"); } callStringCache = sb.ToString(); } #endregion public bool ContainsType(string type) { foreach (Parameter p in this) if (p.CurrentType == type) return true; return false; } } }