#region --- License --- /* Copyright (c) 2006, 2007 Stefanos Apostolopoulos * See license.txt for license info */ #endregion using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Xml.XPath; namespace Bind.Structures { /// /// Represents an opengl function. /// The return value, function name, function parameters and opengl version can be retrieved or set. /// class Delegate : IComparable, IEquatable { //internal static DelegateCollection Delegates; bool? cls_compliance_overriden; protected static Regex endings = new Regex(@"((((d|f|fi)|u?[isb])_?v?)|v)", RegexOptions.Compiled | RegexOptions.RightToLeft); protected static Regex endingsNotToTrim = new Regex("(ib|[tdrey]s|[eE]n[vd]|bled|Flag|Tess|Status|Pixels|Instanced|Indexed|Varyings|Boolean|IDs)", RegexOptions.Compiled | RegexOptions.RightToLeft); // Add a trailing v to functions matching this regex. Used to differntiate between overloads taking both // a 'type' and a 'ref type' (such overloads are not CLS Compliant). // The default Regex matches no functions. Create a new Regex in Bind.Generator classes to override the default behavior. internal static Regex endingsAddV = new Regex("^0", RegexOptions.Compiled); #region --- Constructors --- public Delegate() { Parameters = new ParameterCollection(); } public Delegate(Delegate d) { Category = d.Category; Extension = d.Extension; Name = d.Name; Parameters = new ParameterCollection(d.Parameters); ReturnType = new Type(d.ReturnType); Version = d.Version; //this.Version = !String.IsNullOrEmpty(d.Version) ? new string(d.Version.ToCharArray()) : ""; Deprecated = d.Deprecated; DeprecatedVersion = d.DeprecatedVersion; EntryPoint = d.EntryPoint; } #endregion #region --- Properties --- #region public bool CLSCompliant /// /// Gets the CLSCompliant property. True if the delegate is not CLSCompliant. /// public virtual bool CLSCompliant { get { if (cls_compliance_overriden != null) return (bool)cls_compliance_overriden; if (Unsafe) return false; if (!ReturnType.CLSCompliant) return false; foreach (Parameter p in Parameters) { if (!p.CLSCompliant) return false; } return true; } set { cls_compliance_overriden = value; } } #endregion #region public string Category private string _category; public string Category { get { return _category; } set { _category = value; } } #endregion #region public bool NeedsWrapper /// /// Gets a value that indicates whether this function needs to be wrapped with a Marshaling function. /// This flag is set if a function contains an Array parameter, or returns /// an Array or string. /// public bool NeedsWrapper { get { // TODO: Add special cases for (Get)ShaderSource. if (ReturnType.WrapperType != WrapperTypes.None) return true; foreach (Parameter p in Parameters) { if (p.WrapperType != WrapperTypes.None) return true; } return false; } } #endregion #region public virtual bool Unsafe /// /// True if the delegate must be declared as 'unsafe'. /// public virtual bool Unsafe { //get { return @unsafe; } //set { @unsafe = value; } get { //if ((Settings.Compatibility & Settings.Legacy.NoPublicUnsafeFunctions) != Settings.Legacy.None) // return false; if (ReturnType.Pointer != 0) return true; foreach (Parameter p in Parameters) { if (p.Pointer != 0) { return true; } } return false; } } #endregion #region public Parameter ReturnType Type _return_type = new Type(); /// /// Gets or sets the return value of the opengl function. /// public Type ReturnType { get { return _return_type; } set { _return_type = value; } } #endregion #region public virtual string Name string _name; /// /// Gets or sets the name of the opengl function. /// public virtual string Name { get { return _name; } set { if (!String.IsNullOrEmpty(value)) { _name = value.Trim(); } } } #endregion #region public ParameterCollection Parameters ParameterCollection _parameters; public ParameterCollection Parameters { get { return _parameters; } set { _parameters = value; } } #endregion #region public string Version string _version; /// /// Defines the opengl version that introduced this function. /// public string Version { get { return _version; } set { _version = value; } } #endregion #region public bool Extension public string Extension { get; set; } #endregion public bool Deprecated { get; set; } public string DeprecatedVersion { get; set; } public string EntryPoint { get; set; } #endregion // This method should only be used for debugging purposes, not for code generation! // Returns a string representing the full delegate declaration without decorations. // (ie "(unsafe) void delegate glXxxYyy(int a, float b, IntPtr c)" override public string ToString() { StringBuilder sb = new StringBuilder(); sb.Append(Unsafe ? "unsafe " : ""); sb.Append("delegate "); sb.Append(ReturnType); sb.Append(" "); sb.Append(Name); sb.Append(Parameters.ToString()); return sb.ToString(); } #region IComparable Members public int CompareTo(Delegate other) { int ret = Name.CompareTo(other.Name); if (ret == 0) ret = Parameters.CompareTo(other.Parameters); if (ret == 0) ret = ReturnType.CompareTo(other.ReturnType); return ret; } #endregion #region IEquatable Members public bool Equals(Delegate other) { return Name.Equals(other.Name) && Parameters.Equals(other.Parameters) && ReturnType.Equals(other.ReturnType); } #endregion } #region DelegateCollection class DelegateCollection : IDictionary> { readonly SortedDictionary> Delegates = new SortedDictionary>(); public void Add(Delegate d) { if (!ContainsKey(d.Name)) { Add(d.Name, new List { d }); } else { var list = Delegates[d.Name]; var index = list.IndexOf(d); if (index < 0) { // Function not defined - add it! list.Add(d); } else { // Function redefined with identical parameters: // merge their version and category properties and // discard the duplicate definition if (!list[index].Category.Contains(d.Category)) { list[index].Category += "|" + d.Category; } if (String.IsNullOrEmpty(list[index].Version)) { list[index].Version = d.Version; } } } } public void AddRange(IEnumerable delegates) { foreach (var d in delegates) { Add(d); } } public void AddRange(DelegateCollection delegates) { foreach (var d in delegates.Values.SelectMany(v => v)) { Add(d); } } #region IDictionary Members public void Add(string key, List value) { Delegates.Add(key, value.ToList()); } public bool ContainsKey(string key) { return Delegates.ContainsKey(key); } public bool Remove(string key) { return Delegates.Remove(key); } public bool TryGetValue(string key, out List value) { return Delegates.TryGetValue(key, out value); } public List this[string index] { get { return Delegates[index]; } set { Delegates[index] = value; } } public ICollection Keys { get { return Delegates.Keys; } } public ICollection> Values { get { return Delegates.Values; } } #endregion #region ICollection implementation public void Add(KeyValuePair> item) { Delegates.Add(item.Key, item.Value.ToList()); } public void Clear() { Delegates.Clear(); } public bool Contains(KeyValuePair> item) { return Delegates.Contains(item); } public void CopyTo(KeyValuePair>[] array, int arrayIndex) { Delegates.CopyTo(array, arrayIndex); } public bool Remove(KeyValuePair> item) { return Delegates.Remove(item.Key); } public int Count { get { return Delegates.Count; } } public bool IsReadOnly { get { return false; } } #endregion #region IEnumerable implementation public IEnumerator>> GetEnumerator() { return Delegates.GetEnumerator(); } #endregion #region IEnumerable implementation System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return Delegates.GetEnumerator(); } #endregion } #endregion }