2007-08-10 09:27:13 +00:00
#region - - - License - - -
/ * Copyright ( c ) 2006 , 2007 Stefanos Apostolopoulos
* See license . txt for license info
* /
2007-07-23 00:15:18 +00:00
#endregion
using System ;
using System.Collections.Generic ;
using System.Text ;
using System.Runtime.InteropServices ;
2007-08-01 09:27:57 +00:00
namespace Bind.Structures
2007-07-23 00:15:18 +00:00
{
/// <summary>
/// Represents a single parameter of an opengl function.
/// </summary>
2007-08-01 21:14:39 +00:00
public class Parameter : Type
2007-07-23 00:15:18 +00:00
{
2007-09-02 00:40:43 +00:00
string cache ;
bool rebuild ;
2007-10-21 15:48:52 +00:00
bool unsafe_allowed ; // True if the cache may contain unsafe types, false otherwise.
2007-09-02 00:40:43 +00:00
2007-07-23 00:15:18 +00:00
#region Constructors
/// <summary>
/// Creates a new Parameter without type and name.
/// </summary>
public Parameter ( )
2007-08-01 21:14:39 +00:00
: base ( )
2007-07-23 00:15:18 +00:00
{
}
/// <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 21:14:39 +00:00
: base ( p )
2007-07-23 00:15:18 +00:00
{
if ( p = = null )
return ;
2007-09-02 00:40:43 +00:00
this . Name = p . Name ;
2007-07-23 00:15:18 +00:00
this . Unchecked = p . Unchecked ;
this . UnmanagedType = p . UnmanagedType ;
2007-08-01 09:27:57 +00:00
this . Flow = p . Flow ;
2007-09-02 00:40:43 +00:00
this . cache = p . cache ;
//this.rebuild = false;
2007-07-23 00:15:18 +00:00
}
#endregion
2007-08-01 21:14:39 +00:00
#region public string Name
2007-07-23 00:15:18 +00:00
2007-09-02 00:40:43 +00:00
string _name = String . Empty ;
2007-07-23 00:15:18 +00:00
/// <summary>
/// Gets or sets the name of the parameter.
/// </summary>
public string Name
{
get { return _name ; }
2007-09-02 00:40:43 +00:00
set
{
if ( _name ! = value )
{
_name = value ;
rebuild = true ;
}
}
2007-07-23 00:15:18 +00:00
}
#endregion
#region UnmanagedType property
UnmanagedType _unmanaged_type ;
/// <summary>
/// Gets or sets the name of the parameter.
/// </summary>
2007-08-01 21:14:39 +00:00
private UnmanagedType UnmanagedType
2007-07-23 00:15:18 +00:00
{
get { return _unmanaged_type ; }
2007-09-02 00:40:43 +00:00
set
{
if ( _unmanaged_type ! = value )
{
_unmanaged_type = value ;
rebuild = true ;
}
}
2007-07-23 00:15:18 +00:00
}
#endregion
2007-08-01 21:14:39 +00:00
#region public FlowDirection Flow
2007-07-23 00:15:18 +00:00
/// <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 ; }
2007-09-02 00:40:43 +00:00
set
{
if ( _flow ! = value )
{
_flow = value ;
rebuild = true ;
}
}
2007-07-23 00:15:18 +00:00
}
#endregion
2007-08-01 09:27:57 +00:00
#region public bool NeedsPin
public bool NeedsPin
{
2007-08-20 12:25:48 +00:00
get
{
return ( Array > 0 | | Reference | | CurrentType = = "object" ) & &
! CurrentType . ToLower ( ) . Contains ( "string" ) ;
}
2007-08-01 09:27:57 +00:00
}
#endregion
#region public bool Unchecked
private bool _unchecked ;
public bool Unchecked
{
get { return _unchecked ; }
2007-09-02 00:40:43 +00:00
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 09:27:57 +00:00
}
2007-07-23 00:15:18 +00:00
#endregion
2007-10-21 15:48:52 +00:00
public override string ToString ( )
2007-08-01 09:27:57 +00:00
{
return ToString ( false ) ;
}
2007-10-21 15:48:52 +00:00
#region public string ToString ( bool override_unsafe_setting )
2007-08-01 09:27:57 +00:00
2007-10-21 15:48:52 +00:00
public string ToString ( bool override_unsafe_setting )
2007-07-23 00:15:18 +00:00
{
2007-10-21 15:48:52 +00:00
rebuild | = unsafe_allowed | = override_unsafe_setting ;
unsafe_allowed = override_unsafe_setting ;
2007-09-02 00:40:43 +00:00
if ( ! String . IsNullOrEmpty ( cache ) & & ! rebuild )
2007-08-01 09:27:57 +00:00
{
2007-09-02 00:40:43 +00:00
return cache ;
2007-08-01 09:27:57 +00:00
}
2007-09-02 00:40:43 +00:00
else
2007-08-01 09:27:57 +00:00
{
2007-09-02 00:40:43 +00: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 " ) ;
}
2007-10-21 15:48:52 +00:00
if ( ! override_unsafe_setting & & ( ( Settings . Compatibility & Settings . Legacy . NoPublicUnsafeFunctions ) ! = Settings . Legacy . None ) )
2007-08-01 09:27:57 +00:00
{
2007-09-02 00:40:43 +00:00
if ( Pointer )
{
sb . Append ( "IntPtr" ) ;
}
else
{
sb . Append ( CurrentType ) ;
if ( Array > 0 )
sb . Append ( "[]" ) ;
}
2007-08-01 09:27:57 +00:00
}
else
{
2007-08-01 21:14:39 +00:00
sb . Append ( CurrentType ) ;
2007-09-02 00:40:43 +00:00
if ( Pointer )
sb . Append ( "*" ) ;
2007-08-01 09:27:57 +00:00
if ( Array > 0 )
sb . Append ( "[]" ) ;
}
2007-09-02 00:40:43 +00:00
if ( ! String . IsNullOrEmpty ( Name ) )
{
sb . Append ( " " ) ;
sb . Append ( Utilities . Keywords . Contains ( Name ) ? "@" + Name : Name ) ;
}
rebuild = false ;
cache = sb . ToString ( ) ;
return cache ;
2007-08-01 09:27:57 +00:00
}
2007-07-23 00:15:18 +00:00
}
2007-08-01 09:27:57 +00:00
2007-07-23 00:15:18 +00:00
#endregion
2007-08-01 21:14:39 +00:00
2007-08-10 09:27:13 +00:00
#region internal static Parameter Translate ( Parameter par , string Category )
2007-08-01 21:14:39 +00:00
internal static Parameter Translate ( Parameter par , string Category )
{
Enum @enum ;
string s ;
Parameter p = new Parameter ( par ) ;
2007-09-02 22:52:00 +00:00
// 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 16:14:23 +00:00
2007-08-01 21:14:39 +00:00
// Translate enum types
2007-09-02 22:52:00 +00:00
if ( ( normal | | aux ) & & @enum . Name ! = "GLenum" )
2007-08-01 21:14:39 +00:00
{
2007-10-21 15:48:52 +00:00
if ( ( Settings . Compatibility & Settings . Legacy . ConstIntEnums ) ! = Settings . Legacy . None )
2007-09-02 22:52:00 +00:00
{
2007-08-01 21:14:39 +00:00
p . CurrentType = "int" ;
2007-09-02 22:52:00 +00:00
}
2007-08-01 21:14:39 +00:00
else
2007-09-02 22:52:00 +00:00
{
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 21:14:39 +00: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 ) )
{
2007-10-21 15:48:52 +00:00
if ( ( Settings . Compatibility & Settings . Legacy . ConstIntEnums ) = = Settings . Legacy . None )
2007-08-01 21:14:39 +00:00
{
// Better match: enum.Name == function.Category (e.g. GL_VERSION_1_1 etc)
if ( Enum . GLEnums . ContainsKey ( Category ) )
{
2007-09-02 22:52:00 +00:00
p . CurrentType = String . Format ( "{0}.{1}" , Settings . NormalEnumsClass , Category ) ;
2007-08-01 21:14:39 +00:00
}
else
{
2007-09-02 22:52:00 +00:00
p . CurrentType = String . Format ( "{0}.{1}" , Settings . NormalEnumsClass , Settings . CompleteEnumName ) ;
2007-08-01 21:14:39 +00:00
}
}
else
{
p . CurrentType = "int" ;
}
}
else
{
// This is not enum, default translation:
2007-08-20 12:25:48 +00: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" )
2007-09-01 23:59:47 +00:00
p . CurrentType = "PixelFormatDescriptor" ;
2007-08-20 12:25:48 +00:00
else if ( p . CurrentType = = "LAYERPLANEDESCRIPTOR" )
2007-09-01 23:59:47 +00:00
p . CurrentType = "LayerPlaneDescriptor" ;
2007-08-20 12:25:48 +00:00
else if ( p . CurrentType = = "GLYPHMETRICSFLOAT" )
2007-09-01 23:59:47 +00:00
p . CurrentType = "GlyphMetricsFloat" ;
2007-08-20 12:25:48 +00:00
}
}
2007-09-02 22:52:00 +00:00
else if ( p . CurrentType = = "XVisualInfo" )
{
//p.Pointer = false;
//p.Reference = true;
}
2007-08-20 12:25:48 +00:00
else
{
p . CurrentType = s ;
}
2007-08-01 21:14:39 +00:00
p . CurrentType =
Bind . Structures . Type . CSTypes . ContainsKey ( p . CurrentType ) ?
Bind . Structures . Type . CSTypes [ p . CurrentType ] : p . CurrentType ;
2007-09-02 22:52:00 +00:00
if ( p . CurrentType = = "IntPtr" )
{
p . Pointer = false ;
}
2007-08-01 21:14:39 +00:00
}
}
//if (CSTypes.ContainsKey(p.CurrentType))
// p.CurrentType = CSTypes[p.CurrentType];
// Translate pointer parameters
2007-10-31 17:42:29 +00:00
if ( p . Pointer ) /* || p.CurrentType == "IntPtr")*/
2007-08-01 21:14:39 +00:00
{
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 ;
}
2007-10-31 17:42:29 +00:00
else if ( p . CurrentType . ToLower ( ) . Contains ( "void" ) ) /*|| p.CurrentType.Contains("IntPtr"))*/
2007-08-01 21:14:39 +00:00
{
2007-10-21 15:48:52 +00:00
p . CurrentType = "IntPtr" ;
p . Pointer = false ;
2007-08-01 21:14:39 +00:00
p . WrapperType = WrapperTypes . GenericParameter ;
}
}
2007-08-20 12:25:48 +00:00
if ( p . Reference )
{
p . WrapperType = WrapperTypes . ReferenceParameter ;
}
2007-08-01 21:14:39 +00:00
if ( p . CurrentType . ToLower ( ) . Contains ( "bool" ) )
{
// Is this actually used anywhere?
p . WrapperType = WrapperTypes . BoolParameter ;
}
return p ;
}
2007-08-10 09:27:13 +00:00
#endregion
2007-07-23 00:15:18 +00:00
}
/// <summary>
/// Holds the parameter list of an opengl function.
/// </summary>
public class ParameterCollection : List < Parameter >
{
2007-09-02 00:40:43 +00:00
string cache = String . Empty ;
string callStringCache = String . Empty ;
2007-09-02 22:52:00 +00:00
private bool rebuild = true ;
bool hasPointerParameters ;
bool hasReferenceParameters ;
2007-10-21 15:48:52 +00:00
bool unsafe_types_allowed ;
2007-09-02 22:52:00 +00:00
private bool Rebuild
{
get { return rebuild ; }
set
{
rebuild = value ;
}
}
2007-09-02 00:40:43 +00:00
2007-07-23 00:15:18 +00:00
#region Constructors
public ParameterCollection ( )
{
}
public ParameterCollection ( ParameterCollection pc )
{
foreach ( Parameter p in pc )
{
this . Add ( new Parameter ( p ) ) ;
}
}
#endregion
2007-10-21 15:48:52 +00:00
#region void BuildCache ( )
2007-09-02 22:52:00 +00:00
void BuildCache ( )
{
BuildCallStringCache ( ) ;
2007-10-21 15:48:52 +00:00
BuildToStringCache ( unsafe_types_allowed ) ;
2007-09-02 22:52:00 +00:00
BuildReferenceAndPointerParametersCache ( ) ;
Rebuild = false ;
}
2007-10-21 15:48:52 +00:00
#endregion
#region public bool HasPointerParameters
2007-09-02 22:52:00 +00:00
public bool HasPointerParameters
{
get
{
if ( ! rebuild )
{
return hasPointerParameters ;
}
else
{
BuildCache ( ) ;
return hasPointerParameters ;
}
}
}
2007-10-21 15:48:52 +00:00
#endregion
#region public bool HasReferenceParameters
2007-09-02 22:52:00 +00:00
public bool HasReferenceParameters
{
get
{
if ( ! Rebuild )
{
return hasReferenceParameters ;
}
else
{
BuildCache ( ) ;
return hasReferenceParameters ;
}
}
}
2007-10-21 15:48:52 +00:00
#endregion
#region void BuildReferenceAndPointerParametersCache ( )
2007-09-02 22:52:00 +00:00
void BuildReferenceAndPointerParametersCache ( )
{
foreach ( Parameter p in this )
{
2007-10-21 15:48:52 +00:00
if ( p . Pointer | | p . CurrentType . Contains ( "IntPtr" ) )
2007-09-02 22:52:00 +00:00
hasPointerParameters = true ;
if ( p . Reference )
hasReferenceParameters = true ;
}
}
2007-10-21 15:48:52 +00:00
#endregion
2007-09-02 22:52:00 +00:00
#region new public void Add ( Parameter p )
2007-09-02 00:40:43 +00:00
new public void Add ( Parameter p )
{
2007-09-02 22:52:00 +00:00
Rebuild = true ;
2007-09-02 00:40:43 +00:00
base . Add ( p ) ;
}
2007-09-02 22:52:00 +00:00
#endregion
2007-10-21 15:48:52 +00:00
public override string ToString ( )
2007-08-01 09:27:57 +00:00
{
2007-08-01 21:14:39 +00:00
return ToString ( false ) ;
2007-08-01 09:27:57 +00:00
}
2007-10-21 15:48:52 +00:00
#region public string ToString ( bool override_unsafe_setting )
2007-08-01 09:27:57 +00:00
/// <summary>
/// Gets the parameter declaration string.
/// </summary>
2007-10-21 15:48:52 +00:00
/// <param name="override_unsafe_setting">If true, unsafe types will be used even if the Settings.Compatibility.NoPublicUnsafeFunctions flag is set.</param>
2007-08-01 09:27:57 +00:00
/// <returns>The parameter list of an opengl function in the form ( [parameters] )</returns>
2007-10-21 15:48:52 +00:00
public string ToString ( bool override_unsafe_setting )
2007-07-23 00:15:18 +00:00
{
2007-10-21 15:48:52 +00:00
Rebuild | = unsafe_types_allowed ! = override_unsafe_setting ;
unsafe_types_allowed = override_unsafe_setting ;
2007-09-02 22:52:00 +00:00
if ( ! Rebuild )
2007-09-02 00:40:43 +00:00
{
return cache ;
}
else
2007-07-23 00:15:18 +00:00
{
2007-09-02 22:52:00 +00:00
BuildCache ( ) ;
return cache ;
}
}
#endregion
2007-10-21 15:48:52 +00:00
#region void BuildToStringCache ( bool override_unsafe_setting )
2007-09-02 22:52:00 +00:00
2007-10-21 15:48:52 +00:00
void BuildToStringCache ( bool override_unsafe_setting )
2007-09-02 22:52:00 +00:00
{
2007-10-21 15:48:52 +00:00
unsafe_types_allowed = override_unsafe_setting ;
2007-09-02 22:52:00 +00:00
StringBuilder sb = new StringBuilder ( ) ;
sb . Append ( "(" ) ;
if ( this . Count > 0 )
{
foreach ( Parameter p in this )
2007-07-23 00:15:18 +00:00
{
2007-10-21 15:48:52 +00:00
sb . Append ( p . ToString ( override_unsafe_setting ) ) ;
2007-09-02 22:52:00 +00:00
sb . Append ( ", " ) ;
2007-07-23 00:15:18 +00:00
}
2007-09-02 22:52:00 +00:00
sb . Replace ( ", " , ")" , sb . Length - 2 , 2 ) ;
2007-09-02 00:40:43 +00:00
}
2007-09-02 22:52:00 +00:00
else
sb . Append ( ")" ) ;
cache = sb . ToString ( ) ;
2007-07-23 00:15:18 +00:00
}
2007-08-01 09:27:57 +00:00
#endregion
2007-09-02 22:52:00 +00:00
#region public string CallString ( )
2007-08-01 21:14:39 +00:00
2007-09-02 22:52:00 +00:00
public string CallString ( )
2007-08-01 21:14:39 +00:00
{
2007-09-02 22:52:00 +00:00
if ( ! Rebuild )
2007-09-02 00:40:43 +00:00
{
return callStringCache ;
}
else
{
2007-09-02 22:52:00 +00:00
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 21:14:39 +00:00
2007-09-02 22:52:00 +00:00
sb . Append ( "(" ) ;
2007-08-01 21:14:39 +00:00
2007-09-02 22:52:00 +00:00
if ( this . Count > 0 )
{
foreach ( Parameter p in this )
2007-08-01 21:14:39 +00:00
{
2007-09-02 22:52:00 +00:00
if ( p . Unchecked )
sb . Append ( "unchecked((" + p . CurrentType + ")" ) ;
if ( p . CurrentType ! = "object" )
2007-08-01 21:14:39 +00:00
{
2007-09-02 22:52:00 +00:00
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 )
{
2007-10-21 15:48:52 +00:00
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 ) ) ;
2007-09-02 22:52:00 +00:00
}
else
2007-08-20 12:25:48 +00:00
{
2007-09-02 22:52:00 +00:00
sb . Append ( String . Format ( "({0})" , p . CurrentType ) ) ;
2007-08-20 12:25:48 +00:00
}
2007-09-02 22:52:00 +00:00
}
2007-08-01 21:14:39 +00:00
2007-09-02 22:52:00 +00:00
sb . Append (
Utilities . Keywords . Contains ( p . Name ) ? "@" + p . Name : p . Name
) ;
2007-08-01 21:14:39 +00:00
2007-09-02 22:52:00 +00:00
if ( p . Unchecked )
sb . Append ( ")" ) ;
2007-08-01 21:14:39 +00:00
2007-09-02 22:52:00 +00:00
sb . Append ( ", " ) ;
2007-09-02 00:40:43 +00:00
}
2007-09-02 22:52:00 +00:00
sb . Replace ( ", " , ")" , sb . Length - 2 , 2 ) ;
2007-09-02 00:40:43 +00:00
}
2007-09-02 22:52:00 +00:00
else
{
sb . Append ( ")" ) ;
}
callStringCache = sb . ToString ( ) ;
2007-08-01 21:14:39 +00:00
}
2007-09-02 22:52:00 +00:00
#endregion
2007-07-23 00:15:18 +00:00
public bool ContainsType ( string type )
{
foreach ( Parameter p in this )
2007-08-01 21:14:39 +00:00
if ( p . CurrentType = = type )
2007-07-23 00:15:18 +00:00
return true ;
return false ;
}
}
}