2009-02-22 11:43:35 +01:00
|
|
|
#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;
|
2009-10-27 23:37:05 +01:00
|
|
|
using System.Linq;
|
2009-08-17 14:28:22 +02:00
|
|
|
using System.Text;
|
2009-05-29 17:57:01 +02:00
|
|
|
using System.Text.RegularExpressions;
|
2009-08-17 14:28:22 +02:00
|
|
|
using System.Xml.XPath;
|
2009-02-22 11:43:35 +01:00
|
|
|
|
|
|
|
namespace Bind.Structures
|
|
|
|
{
|
|
|
|
/// <summary>
|
|
|
|
/// Represents an opengl function.
|
|
|
|
/// The return value, function name, function parameters and opengl version can be retrieved or set.
|
|
|
|
/// </summary>
|
2013-11-01 09:15:02 +01:00
|
|
|
class Delegate : IComparable<Delegate>, IEquatable<Delegate>
|
2009-02-22 11:43:35 +01:00
|
|
|
{
|
2010-10-13 23:41:06 +02:00
|
|
|
//internal static DelegateCollection Delegates;
|
2009-02-22 11:43:35 +01:00
|
|
|
|
2009-04-12 20:23:01 +02:00
|
|
|
bool? cls_compliance_overriden;
|
2009-05-29 17:57:01 +02:00
|
|
|
|
|
|
|
protected static Regex endings = new Regex(@"((((d|f|fi)|u?[isb])_?v?)|v)", RegexOptions.Compiled | RegexOptions.RightToLeft);
|
2009-08-20 23:38:23 +02:00
|
|
|
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);
|
2009-05-29 17:57:01 +02:00
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
#region --- Constructors ---
|
|
|
|
|
|
|
|
public Delegate()
|
|
|
|
{
|
|
|
|
Parameters = new ParameterCollection();
|
|
|
|
}
|
|
|
|
|
|
|
|
public Delegate(Delegate d)
|
|
|
|
{
|
2009-08-25 17:59:57 +02:00
|
|
|
Category = d.Category;
|
2013-10-27 01:30:45 +02:00
|
|
|
Extension = d.Extension;
|
2009-08-25 17:59:57 +02:00
|
|
|
Name = d.Name;
|
|
|
|
Parameters = new ParameterCollection(d.Parameters);
|
|
|
|
ReturnType = new Type(d.ReturnType);
|
|
|
|
Version = d.Version;
|
2009-02-22 11:43:35 +01:00
|
|
|
//this.Version = !String.IsNullOrEmpty(d.Version) ? new string(d.Version.ToCharArray()) : "";
|
2010-10-10 14:28:27 +02:00
|
|
|
Deprecated = d.Deprecated;
|
|
|
|
DeprecatedVersion = d.DeprecatedVersion;
|
2013-11-03 16:09:11 +01:00
|
|
|
EntryPoint = d.EntryPoint;
|
2013-11-14 13:46:42 +01:00
|
|
|
Obsolete = d.Obsolete;
|
2013-12-15 22:01:45 +01:00
|
|
|
CLSCompliant = d.CLSCompliant;
|
2013-11-24 13:55:13 +01:00
|
|
|
Slot = d.Slot;
|
2009-02-22 11:43:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region --- Properties ---
|
|
|
|
|
|
|
|
#region public bool CLSCompliant
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Gets the CLSCompliant property. True if the delegate is not CLSCompliant.
|
|
|
|
/// </summary>
|
|
|
|
public virtual bool CLSCompliant
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
2009-04-12 20:23:01 +02:00
|
|
|
if (cls_compliance_overriden != null)
|
|
|
|
return (bool)cls_compliance_overriden;
|
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
if (Unsafe)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (!ReturnType.CLSCompliant)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
foreach (Parameter p in Parameters)
|
|
|
|
{
|
|
|
|
if (!p.CLSCompliant)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2009-04-12 20:23:01 +02:00
|
|
|
set
|
|
|
|
{
|
|
|
|
cls_compliance_overriden = value;
|
|
|
|
}
|
2009-02-22 11:43:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region public string Category
|
|
|
|
|
|
|
|
private string _category;
|
|
|
|
|
|
|
|
public string Category
|
|
|
|
{
|
|
|
|
get { return _category; }
|
2010-10-14 01:09:10 +02:00
|
|
|
set { _category = value; }
|
2009-02-22 11:43:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region public bool NeedsWrapper
|
|
|
|
|
|
|
|
/// <summary>
|
2009-10-27 23:37:05 +01:00
|
|
|
/// Gets a value that indicates whether this function needs to be wrapped with a Marshaling function.
|
2009-02-22 11:43:35 +01:00
|
|
|
/// This flag is set if a function contains an Array parameter, or returns
|
|
|
|
/// an Array or string.
|
|
|
|
/// </summary>
|
|
|
|
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
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// True if the delegate must be declared as 'unsafe'.
|
|
|
|
/// </summary>
|
|
|
|
public virtual bool Unsafe
|
|
|
|
{
|
|
|
|
//get { return @unsafe; }
|
|
|
|
//set { @unsafe = value; }
|
|
|
|
get
|
|
|
|
{
|
|
|
|
//if ((Settings.Compatibility & Settings.Legacy.NoPublicUnsafeFunctions) != Settings.Legacy.None)
|
|
|
|
// return false;
|
|
|
|
|
2009-07-16 00:33:26 +02:00
|
|
|
if (ReturnType.Pointer != 0)
|
2009-02-22 11:43:35 +01:00
|
|
|
return true;
|
|
|
|
|
|
|
|
foreach (Parameter p in Parameters)
|
|
|
|
{
|
2009-07-16 00:33:26 +02:00
|
|
|
if (p.Pointer != 0)
|
2009-02-22 11:43:35 +01:00
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region public Parameter ReturnType
|
|
|
|
|
|
|
|
Type _return_type = new Type();
|
|
|
|
/// <summary>
|
|
|
|
/// Gets or sets the return value of the opengl function.
|
|
|
|
/// </summary>
|
|
|
|
public Type ReturnType
|
|
|
|
{
|
|
|
|
get { return _return_type; }
|
|
|
|
set
|
|
|
|
{
|
|
|
|
_return_type = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region public virtual string Name
|
|
|
|
|
|
|
|
string _name;
|
|
|
|
/// <summary>
|
|
|
|
/// Gets or sets the name of the opengl function.
|
|
|
|
/// </summary>
|
|
|
|
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; }
|
2009-10-27 23:37:05 +01:00
|
|
|
set { _parameters = value; }
|
2009-02-22 11:43:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region public string Version
|
|
|
|
|
|
|
|
string _version;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Defines the opengl version that introduced this function.
|
|
|
|
/// </summary>
|
|
|
|
public string Version
|
|
|
|
{
|
|
|
|
get { return _version; }
|
|
|
|
set { _version = value; }
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region public bool Extension
|
|
|
|
|
|
|
|
public string Extension
|
|
|
|
{
|
2013-10-27 01:30:45 +02:00
|
|
|
get;
|
|
|
|
set;
|
2009-02-22 11:43:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
2010-10-10 14:28:27 +02:00
|
|
|
public bool Deprecated { get; set; }
|
|
|
|
public string DeprecatedVersion { get; set; }
|
2013-11-03 16:09:11 +01:00
|
|
|
public string EntryPoint { get; set; }
|
2013-11-14 13:46:42 +01:00
|
|
|
public string Obsolete { get; set; }
|
2010-10-10 14:28:27 +02:00
|
|
|
|
2013-11-24 13:55:13 +01:00
|
|
|
// Slot index in the address table
|
|
|
|
public int Slot { get; set; }
|
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
#endregion
|
|
|
|
|
2013-11-01 09:15:02 +01:00
|
|
|
// 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)"
|
2009-02-22 11:43:35 +01:00
|
|
|
override public string ToString()
|
|
|
|
{
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
|
|
|
|
sb.Append(Unsafe ? "unsafe " : "");
|
|
|
|
sb.Append("delegate ");
|
|
|
|
sb.Append(ReturnType);
|
|
|
|
sb.Append(" ");
|
|
|
|
sb.Append(Name);
|
2013-11-01 09:15:02 +01:00
|
|
|
sb.Append(Parameters.ToString());
|
2009-02-22 11:43:35 +01:00
|
|
|
|
|
|
|
return sb.ToString();
|
|
|
|
}
|
|
|
|
|
2009-05-30 17:28:52 +02:00
|
|
|
#region IComparable<Delegate> Members
|
|
|
|
|
|
|
|
public int CompareTo(Delegate other)
|
|
|
|
{
|
2013-11-03 16:09:11 +01:00
|
|
|
int ret = Name.CompareTo(other.Name);
|
|
|
|
if (ret == 0)
|
|
|
|
ret = Parameters.CompareTo(other.Parameters);
|
|
|
|
if (ret == 0)
|
|
|
|
ret = ReturnType.CompareTo(other.ReturnType);
|
|
|
|
return ret;
|
2009-05-30 17:28:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
2013-11-01 09:15:02 +01:00
|
|
|
|
|
|
|
#region IEquatable<Delegate> Members
|
|
|
|
|
|
|
|
public bool Equals(Delegate other)
|
|
|
|
{
|
2013-11-03 16:09:11 +01:00
|
|
|
return
|
|
|
|
Name.Equals(other.Name) &&
|
|
|
|
Parameters.Equals(other.Parameters) &&
|
|
|
|
ReturnType.Equals(other.ReturnType);
|
2013-11-01 09:15:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
2009-02-22 11:43:35 +01:00
|
|
|
}
|
|
|
|
|
2013-11-03 16:09:11 +01:00
|
|
|
#region DelegateCollection
|
2009-02-22 11:43:35 +01:00
|
|
|
|
2013-11-03 16:09:11 +01:00
|
|
|
class DelegateCollection : IDictionary<string, List<Delegate>>
|
2009-02-22 11:43:35 +01:00
|
|
|
{
|
2013-11-03 16:09:11 +01:00
|
|
|
readonly SortedDictionary<string, List<Delegate>> Delegates =
|
|
|
|
new SortedDictionary<string, List<Delegate>>();
|
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
public void Add(Delegate d)
|
|
|
|
{
|
2009-08-25 17:59:57 +02:00
|
|
|
if (!ContainsKey(d.Name))
|
2009-02-22 11:43:35 +01:00
|
|
|
{
|
2013-11-03 16:09:11 +01:00
|
|
|
Add(d.Name, new List<Delegate> { d });
|
2009-02-22 11:43:35 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-11-03 16:09:11 +01:00
|
|
|
var list = Delegates[d.Name];
|
2013-11-17 21:27:09 +01:00
|
|
|
var index = list.FindIndex(w => w.CompareTo(d) == 0);
|
2013-11-03 19:13:49 +01:00
|
|
|
if (index < 0)
|
2013-11-03 16:09:11 +01:00
|
|
|
{
|
2013-11-03 19:13:49 +01:00
|
|
|
// Function not defined - add it!
|
2013-11-03 16:09:11 +01:00
|
|
|
list.Add(d);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2013-11-03 19:13:49 +01:00
|
|
|
// Function redefined with identical parameters:
|
2013-11-03 20:41:29 +01:00
|
|
|
// merge their version and category properties and
|
|
|
|
// discard the duplicate definition
|
2013-11-03 19:13:49 +01:00
|
|
|
if (!list[index].Category.Contains(d.Category))
|
|
|
|
{
|
|
|
|
list[index].Category += "|" + d.Category;
|
|
|
|
}
|
2013-11-03 20:41:29 +01:00
|
|
|
if (String.IsNullOrEmpty(list[index].Version))
|
|
|
|
{
|
|
|
|
list[index].Version = d.Version;
|
|
|
|
}
|
2013-11-03 16:09:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-09 19:22:31 +01:00
|
|
|
public void AddRange(IEnumerable<Delegate> delegates)
|
|
|
|
{
|
|
|
|
foreach (var d in delegates)
|
|
|
|
{
|
|
|
|
Add(d);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public void AddRange(DelegateCollection delegates)
|
|
|
|
{
|
|
|
|
foreach (var d in delegates.Values.SelectMany(v => v))
|
|
|
|
{
|
|
|
|
Add(d);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-03 16:09:11 +01:00
|
|
|
#region IDictionary Members
|
|
|
|
|
|
|
|
public void Add(string key, List<Delegate> 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<Delegate> value)
|
|
|
|
{
|
|
|
|
return Delegates.TryGetValue(key, out value);
|
|
|
|
}
|
|
|
|
|
|
|
|
public List<Delegate> this[string index]
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return Delegates[index];
|
|
|
|
}
|
|
|
|
set
|
|
|
|
{
|
|
|
|
Delegates[index] = value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public ICollection<string> Keys
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return Delegates.Keys;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public ICollection<List<Delegate>> Values
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return Delegates.Values;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region ICollection implementation
|
|
|
|
|
|
|
|
public void Add(KeyValuePair<string, List<Delegate>> item)
|
|
|
|
{
|
|
|
|
Delegates.Add(item.Key, item.Value.ToList());
|
|
|
|
}
|
|
|
|
|
|
|
|
public void Clear()
|
|
|
|
{
|
|
|
|
Delegates.Clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool Contains(KeyValuePair<string, List<Delegate>> item)
|
|
|
|
{
|
|
|
|
return Delegates.Contains(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void CopyTo(KeyValuePair<string, List<Delegate>>[] array, int arrayIndex)
|
|
|
|
{
|
|
|
|
Delegates.CopyTo(array, arrayIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
public bool Remove(KeyValuePair<string, List<Delegate>> item)
|
|
|
|
{
|
|
|
|
return Delegates.Remove(item.Key);
|
|
|
|
}
|
|
|
|
|
|
|
|
public int Count
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return Delegates.Count;
|
2009-02-22 11:43:35 +01:00
|
|
|
}
|
|
|
|
}
|
2013-11-03 16:09:11 +01:00
|
|
|
|
|
|
|
public bool IsReadOnly
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region IEnumerable implementation
|
|
|
|
|
|
|
|
public IEnumerator<KeyValuePair<string, List<Delegate>>> GetEnumerator()
|
|
|
|
{
|
|
|
|
return Delegates.GetEnumerator();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region IEnumerable implementation
|
|
|
|
|
|
|
|
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
|
|
|
|
{
|
|
|
|
return Delegates.GetEnumerator();
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
2009-02-22 11:43:35 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
}
|