Opentk/Source/Bind/Structures/Parameter.cs

639 lines
18 KiB
C#
Raw Normal View History

#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;
2007-08-01 11:27:57 +02:00
namespace Bind.Structures
{
/// <summary>
/// Represents a single parameter of an opengl function.
/// </summary>
2007-08-01 23:14:39 +02:00
public class Parameter : Type
{
string cache;
bool rebuild;
#region Constructors
/// <summary>
/// Creates a new Parameter without type and name.
/// </summary>
public Parameter()
2007-08-01 23:14:39 +02:00
:base()
{
}
/// <summary>
/// Creates a new parameter from the parameters passed (deep copy).
/// </summary>
/// <param name="p">The parameter to copy from.</param>
public Parameter(Parameter p)
2007-08-01 23:14:39 +02:00
: base(p)
{
if (p == null)
return;
this.Name = p.Name;
this.Unchecked = p.Unchecked;
this.UnmanagedType = p.UnmanagedType;
2007-08-01 11:27:57 +02:00
this.Flow = p.Flow;
this.cache = p.cache;
//this.rebuild = false;
}
#endregion
2007-08-01 23:14:39 +02:00
#region public string Name
string _name = String.Empty;
/// <summary>
/// Gets or sets the name of the parameter.
/// </summary>
public string Name
{
get { return _name; }
set
{
if (_name != value)
{
_name = value;
rebuild = true;
}
}
}
#endregion
#region UnmanagedType property
UnmanagedType _unmanaged_type;
/// <summary>
/// Gets or sets the name of the parameter.
/// </summary>
2007-08-01 23:14:39 +02:00
private UnmanagedType UnmanagedType
{
get { return _unmanaged_type; }
set
{
if (_unmanaged_type != value)
{
_unmanaged_type = value;
rebuild = true;
}
}
}
#endregion
2007-08-01 23:14:39 +02:00
#region public FlowDirection Flow
/// <summary>
/// Enumarates the possible flows of a parameter (ie. is this parameter
/// used as input or as output?)
/// </summary>
public enum FlowDirection
{
Undefined = 0,
In,
Out
}
FlowDirection _flow;
/// <summary>
/// Gets or sets the flow of the parameter.
/// </summary>
public FlowDirection Flow
{
get { return _flow; }
set
{
if (_flow != value)
{
_flow = value;
rebuild = true;
}
}
}
#endregion
2007-08-01 11:27:57 +02:00
#region public bool NeedsPin
public bool NeedsPin
{
2007-08-20 14:25:48 +02:00
get
{
return (Array > 0 || Reference || CurrentType == "object") &&
!CurrentType.ToLower().Contains("string");
}
2007-08-01 11:27:57 +02:00
}
#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;
}
2007-08-01 11:27:57 +02:00
}
#endregion
2007-08-01 11:27:57 +02:00
#region override public string ToString()
override public string ToString()
2007-08-01 11:27:57 +02:00
{
return ToString(false);
}
#endregion
#region public string ToString(bool taoCompatible)
public string ToString(bool taoCompatible)
{
if (!String.IsNullOrEmpty(cache) && !rebuild)
2007-08-01 11:27:57 +02:00
{
return cache;
2007-08-01 11:27:57 +02:00
}
else
2007-08-01 11:27:57 +02:00
{
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 (taoCompatible && Settings.Compatibility == Settings.Legacy.Tao)
2007-08-01 11:27:57 +02:00
{
if (Pointer)
{
sb.Append("IntPtr");
}
else
{
sb.Append(CurrentType);
if (Array > 0)
sb.Append("[]");
}
2007-08-01 11:27:57 +02:00
}
else
{
2007-08-01 23:14:39 +02:00
sb.Append(CurrentType);
if (Pointer)
sb.Append("*");
2007-08-01 11:27:57 +02:00
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;
2007-08-01 11:27:57 +02:00
}
}
2007-08-01 11:27:57 +02:00
#endregion
2007-08-01 23:14:39 +02:00
#region internal static Parameter Translate(Parameter par, string Category)
2007-08-01 23:14:39 +02:00
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);
2007-08-12 18:14:23 +02:00
2007-08-01 23:14:39 +02:00
// Translate enum types
if ((normal || aux) && @enum.Name != "GLenum")
2007-08-01 23:14:39 +02:00
{
if (Settings.Compatibility == Settings.Legacy.Tao)
{
2007-08-01 23:14:39 +02:00
p.CurrentType = "int";
}
2007-08-01 23:14:39 +02:00
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));
}
}
2007-08-01 23:14:39 +02:00
}
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.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);
2007-08-01 23:14:39 +02:00
}
else
{
p.CurrentType = String.Format("{0}.{1}", Settings.NormalEnumsClass, Settings.CompleteEnumName);
2007-08-01 23:14:39 +02:00
}
}
else
{
p.CurrentType = "int";
}
}
else
{
// This is not enum, default translation:
2007-08-20 14:25:48 +02:00
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";
2007-08-20 14:25:48 +02:00
else if (p.CurrentType == "LAYERPLANEDESCRIPTOR")
p.CurrentType = "LayerPlaneDescriptor";
2007-08-20 14:25:48 +02:00
else if (p.CurrentType == "GLYPHMETRICSFLOAT")
p.CurrentType = "GlyphMetricsFloat";
2007-08-20 14:25:48 +02:00
}
}
else if (p.CurrentType == "XVisualInfo")
{
//p.Pointer = false;
//p.Reference = true;
}
2007-08-20 14:25:48 +02:00
else
{
p.CurrentType = s;
}
2007-08-01 23:14:39 +02:00
p.CurrentType =
Bind.Structures.Type.CSTypes.ContainsKey(p.CurrentType) ?
Bind.Structures.Type.CSTypes[p.CurrentType] : p.CurrentType;
if (p.CurrentType == "IntPtr")
{
p.Pointer = false;
}
2007-08-01 23:14:39 +02:00
}
}
//if (CSTypes.ContainsKey(p.CurrentType))
// p.CurrentType = CSTypes[p.CurrentType];
// Translate pointer parameters
if (p.Pointer)
{
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.WrapperType = WrapperTypes.GenericParameter;
}
}
2007-08-20 14:25:48 +02:00
if (p.Reference)
{
p.WrapperType = WrapperTypes.ReferenceParameter;
}
2007-08-01 23:14:39 +02:00
if (p.CurrentType.ToLower().Contains("bool"))
{
// Is this actually used anywhere?
p.WrapperType = WrapperTypes.BoolParameter;
}
return p;
}
#endregion
}
/// <summary>
/// Holds the parameter list of an opengl function.
/// </summary>
public class ParameterCollection : List<Parameter>
{
string cache = String.Empty;
string callStringCache = String.Empty;
private bool rebuild = true;
bool hasPointerParameters;
bool hasReferenceParameters;
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
void BuildCache()
{
BuildCallStringCache();
BuildToStringCache();
BuildReferenceAndPointerParametersCache();
Rebuild = false;
}
public bool HasPointerParameters
{
get
{
if (!rebuild)
{
return hasPointerParameters;
}
else
{
BuildCache();
return hasPointerParameters;
}
}
}
public bool HasReferenceParameters
{
get
{
if (!Rebuild)
{
return hasReferenceParameters;
}
else
{
BuildCache();
return hasReferenceParameters;
}
}
}
void BuildReferenceAndPointerParametersCache()
{
foreach (Parameter p in this)
{
if (p.Pointer)
hasPointerParameters = true;
if (p.Reference)
hasReferenceParameters = true;
}
}
#region new public void Add(Parameter p)
new public void Add(Parameter p)
{
Rebuild = true;
base.Add(p);
}
#endregion
#region override public string ToString()
/// <summary>
2007-08-01 11:27:57 +02:00
/// Gets the parameter declaration string.
/// </summary>
/// <returns>The parameter list of an opengl function in the form ( [parameters] )</returns>
override public string ToString()
2007-08-01 11:27:57 +02:00
{
2007-08-01 23:14:39 +02:00
return ToString(false);
2007-08-01 11:27:57 +02:00
}
#endregion
2007-08-01 23:14:39 +02:00
#region public string ToString(bool taoCompatible)
2007-08-01 11:27:57 +02:00
/// <summary>
/// Gets the parameter declaration string.
/// </summary>
/// <param name="getCLSCompliant">If true, all types will be replaced by their CLSCompliant C# equivalents</param>
/// <param name="CSTypes">The list of C# types equivalent to the OpenGL types.</param>
/// <returns>The parameter list of an opengl function in the form ( [parameters] )</returns>
2007-08-01 23:14:39 +02:00
public string ToString(bool taoCompatible)
{
if (!Rebuild)
{
return cache;
}
else
{
BuildCache();
return cache;
}
}
#endregion
#region void BuildToStringCache()
void BuildToStringCache()
{
StringBuilder sb = new StringBuilder();
sb.Append("(");
if (this.Count > 0)
{
foreach (Parameter p in this)
{
if (Settings.Compatibility == Settings.Legacy.Tao)
2007-08-01 11:27:57 +02:00
{
sb.Append(p.ToString(true));
2007-08-01 11:27:57 +02:00
}
else
{
sb.Append(p.ToString());
}
sb.Append(", ");
}
sb.Replace(", ", ")", sb.Length - 2, 2);
}
else
sb.Append(")");
cache = sb.ToString();
}
2007-08-01 11:27:57 +02:00
#endregion
#region public string CallString()
2007-08-01 23:14:39 +02:00
public string CallString()
2007-08-01 23:14:39 +02:00
{
if (!Rebuild)
{
return callStringCache;
}
else
{
BuildCache();
return callStringCache;
}
}
#endregion
#region private void BuildCallStringCache()
/// <summary>
/// Builds a call string instance and caches it.
/// </summary>
private void BuildCallStringCache()
{
StringBuilder sb = new StringBuilder();
2007-08-01 23:14:39 +02:00
sb.Append("(");
2007-08-01 23:14:39 +02:00
if (this.Count > 0)
{
foreach (Parameter p in this)
2007-08-01 23:14:39 +02:00
{
if (p.Unchecked)
sb.Append("unchecked((" + p.CurrentType + ")");
if (p.CurrentType != "object")
2007-08-01 23:14:39 +02:00
{
if (p.CurrentType.ToLower().Contains("string"))
{
sb.Append(String.Format("({0}{1})",
p.CurrentType, (p.Array > 0) ? "[]" : ""));
2007-08-01 23:14:39 +02:00
}
else if (p.Pointer || p.Array > 0 || p.Reference)
{
sb.Append(String.Format("({0}*)",
p.CurrentType /*, (p.Pointer || p.Array > 0) ? "*" : ""*/));
}
//else if (p.Reference)
//{
// sb.Append(String.Format("{0} ({1})",
// p.Flow == Parameter.FlowDirection.Out ? "out" : "ref", p.CurrentType));
//}
else
2007-08-20 14:25:48 +02:00
{
sb.Append(String.Format("({0})", p.CurrentType));
2007-08-20 14:25:48 +02:00
}
}
2007-08-01 23:14:39 +02:00
sb.Append(
Utilities.Keywords.Contains(p.Name) ? "@" + p.Name : p.Name
);
2007-08-01 23:14:39 +02:00
if (p.Unchecked)
sb.Append(")");
2007-08-01 23:14:39 +02:00
sb.Append(", ");
}
sb.Replace(", ", ")", sb.Length - 2, 2);
}
else
{
sb.Append(")");
}
callStringCache = sb.ToString();
2007-08-01 23:14:39 +02:00
}
#endregion
public bool ContainsType(string type)
{
foreach (Parameter p in this)
2007-08-01 23:14:39 +02:00
if (p.CurrentType == type)
return true;
return false;
}
}
}