2007-08-10 11:27:13 +02:00
#region - - - License - - -
/ * Copyright ( c ) 2006 , 2007 Stefanos Apostolopoulos
* See license . txt for license info
* /
2007-07-23 02:15:18 +02:00
#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
2007-07-23 02:15:18 +02:00
{
/// <summary>
/// Represents a single parameter of an opengl function.
/// </summary>
2007-08-01 23:14:39 +02:00
public class Parameter : Type
2007-07-23 02:15:18 +02:00
{
2007-09-02 02:40:43 +02:00
string cache ;
bool rebuild ;
2007-10-21 17:48:52 +02:00
bool unsafe_allowed ; // True if the cache may contain unsafe types, false otherwise.
2007-09-02 02:40:43 +02:00
2007-07-23 02:15:18 +02:00
#region Constructors
/// <summary>
/// Creates a new Parameter without type and name.
/// </summary>
public Parameter ( )
2007-08-01 23:14:39 +02:00
: base ( )
2007-07-23 02:15:18 +02: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 23:14:39 +02:00
: base ( p )
2007-07-23 02:15:18 +02:00
{
if ( p = = null )
return ;
2007-09-02 02:40:43 +02:00
this . Name = p . Name ;
2007-07-23 02:15:18 +02:00
this . Unchecked = p . Unchecked ;
this . UnmanagedType = p . UnmanagedType ;
2007-08-01 11:27:57 +02:00
this . Flow = p . Flow ;
2007-09-02 02:40:43 +02:00
this . cache = p . cache ;
//this.rebuild = false;
2007-07-23 02:15:18 +02:00
}
#endregion
2007-08-01 23:14:39 +02:00
#region public string Name
2007-07-23 02:15:18 +02:00
2007-09-02 02:40:43 +02:00
string _name = String . Empty ;
2007-07-23 02:15:18 +02:00
/// <summary>
/// Gets or sets the name of the parameter.
/// </summary>
public string Name
{
get { return _name ; }
2007-09-02 02:40:43 +02:00
set
{
if ( _name ! = value )
{
_name = value ;
rebuild = true ;
}
}
2007-07-23 02:15:18 +02:00
}
#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
2007-07-23 02:15:18 +02:00
{
get { return _unmanaged_type ; }
2007-09-02 02:40:43 +02:00
set
{
if ( _unmanaged_type ! = value )
{
_unmanaged_type = value ;
rebuild = true ;
}
}
2007-07-23 02:15:18 +02:00
}
#endregion
2007-08-01 23:14:39 +02:00
#region public FlowDirection Flow
2007-07-23 02:15:18 +02: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 02:40:43 +02:00
set
{
if ( _flow ! = value )
{
_flow = value ;
rebuild = true ;
}
}
2007-07-23 02:15:18 +02:00
}
#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 ; }
2007-09-02 02:40:43 +02: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 11:27:57 +02:00
}
2007-07-23 02:15:18 +02:00
#endregion
2007-10-21 17:48:52 +02:00
public override string ToString ( )
2007-08-01 11:27:57 +02:00
{
return ToString ( false ) ;
}
2007-10-21 17:48:52 +02:00
#region public string ToString ( bool override_unsafe_setting )
2007-08-01 11:27:57 +02:00
2007-10-21 17:48:52 +02:00
public string ToString ( bool override_unsafe_setting )
2007-07-23 02:15:18 +02:00
{
2007-10-21 17:48:52 +02:00
rebuild | = unsafe_allowed | = override_unsafe_setting ;
unsafe_allowed = override_unsafe_setting ;
2007-09-02 02:40:43 +02:00
if ( ! String . IsNullOrEmpty ( cache ) & & ! rebuild )
2007-08-01 11:27:57 +02:00
{
2007-09-02 02:40:43 +02:00
return cache ;
2007-08-01 11:27:57 +02:00
}
2007-09-02 02:40:43 +02:00
else
2007-08-01 11:27:57 +02:00
{
2007-09-02 02:40:43 +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 " ) ;
}
2007-10-21 17:48:52 +02:00
if ( ! override_unsafe_setting & & ( ( Settings . Compatibility & Settings . Legacy . NoPublicUnsafeFunctions ) ! = Settings . Legacy . None ) )
2007-08-01 11:27:57 +02:00
{
2007-09-02 02:40:43 +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 ) ;
2007-09-02 02:40:43 +02:00
if ( Pointer )
sb . Append ( "*" ) ;
2007-08-01 11:27:57 +02:00
if ( Array > 0 )
sb . Append ( "[]" ) ;
}
2007-09-02 02:40:43 +02: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 11:27:57 +02:00
}
2007-07-23 02:15:18 +02:00
}
2007-08-01 11:27:57 +02:00
2007-07-23 02:15:18 +02:00
#endregion
2007-08-01 23:14:39 +02:00
2007-11-04 16:19:01 +01:00
#region override public void Translate ( string category )
2007-09-03 00:52:00 +02:00
2007-11-04 16:19:01 +01:00
override public void Translate ( string category )
{
base . Translate ( category ) ;
2007-08-01 23:14:39 +02:00
2007-11-04 16:19:01 +01:00
// Find out the necessary wrapper types.
if ( Pointer ) /* || CurrentType == "IntPtr")*/
2007-08-01 23:14:39 +02:00
{
2007-11-04 16:19:01 +01:00
WrapperType = WrapperTypes . ArrayParameter ;
2007-08-01 23:14:39 +02:00
2007-11-04 16:19:01 +01:00
if ( CurrentType . ToLower ( ) . Contains ( "char" ) | | CurrentType . ToLower ( ) . Contains ( "string" ) )
2007-08-01 23:14:39 +02:00
{
// char* or string -> [In] String or [Out] StringBuilder
2007-11-04 16:19:01 +01:00
CurrentType =
Flow = = Parameter . FlowDirection . Out ?
2007-08-01 23:14:39 +02:00
"System.Text.StringBuilder" :
"System.String" ;
2007-11-04 16:19:01 +01:00
Pointer = false ;
WrapperType = WrapperTypes . None ;
2007-08-01 23:14:39 +02:00
}
2007-11-04 16:19:01 +01:00
else if ( CurrentType . ToLower ( ) . Contains ( "void" ) ) /*|| CurrentType.Contains("IntPtr"))*/
2007-08-01 23:14:39 +02:00
{
2007-11-04 16:19:01 +01:00
CurrentType = "IntPtr" ;
Pointer = false ;
WrapperType = WrapperTypes . GenericParameter ;
2007-08-01 23:14:39 +02:00
}
}
2007-11-04 16:19:01 +01:00
if ( Reference )
WrapperType = WrapperTypes . ReferenceParameter ;
2007-08-01 23:14:39 +02:00
2007-11-04 16:19:01 +01:00
// This causes problems with bool arrays
//if (CurrentType.ToLower().Contains("bool"))
// WrapperType = WrapperTypes.BoolParameter;
2007-08-01 23:14:39 +02:00
}
2007-11-04 16:19:01 +01:00
2007-08-10 11:27:13 +02:00
#endregion
2007-07-23 02:15:18 +02:00
}
/// <summary>
/// Holds the parameter list of an opengl function.
/// </summary>
public class ParameterCollection : List < Parameter >
{
2007-09-02 02:40:43 +02:00
string cache = String . Empty ;
string callStringCache = String . Empty ;
2007-09-03 00:52:00 +02:00
private bool rebuild = true ;
bool hasPointerParameters ;
bool hasReferenceParameters ;
2007-10-21 17:48:52 +02:00
bool unsafe_types_allowed ;
2007-09-03 00:52:00 +02:00
private bool Rebuild
{
get { return rebuild ; }
set
{
rebuild = value ;
}
}
2007-09-02 02:40:43 +02:00
2007-07-23 02:15:18 +02:00
#region Constructors
public ParameterCollection ( )
{
}
public ParameterCollection ( ParameterCollection pc )
{
foreach ( Parameter p in pc )
{
this . Add ( new Parameter ( p ) ) ;
}
}
#endregion
2007-10-21 17:48:52 +02:00
#region void BuildCache ( )
2007-09-03 00:52:00 +02:00
void BuildCache ( )
{
BuildCallStringCache ( ) ;
2007-10-21 17:48:52 +02:00
BuildToStringCache ( unsafe_types_allowed ) ;
2007-09-03 00:52:00 +02:00
BuildReferenceAndPointerParametersCache ( ) ;
Rebuild = false ;
}
2007-10-21 17:48:52 +02:00
#endregion
#region public bool HasPointerParameters
2007-09-03 00:52:00 +02:00
public bool HasPointerParameters
{
get
{
if ( ! rebuild )
{
return hasPointerParameters ;
}
else
{
BuildCache ( ) ;
return hasPointerParameters ;
}
}
}
2007-10-21 17:48:52 +02:00
#endregion
#region public bool HasReferenceParameters
2007-09-03 00:52:00 +02:00
public bool HasReferenceParameters
{
get
{
if ( ! Rebuild )
{
return hasReferenceParameters ;
}
else
{
BuildCache ( ) ;
return hasReferenceParameters ;
}
}
}
2007-10-21 17:48:52 +02:00
#endregion
#region void BuildReferenceAndPointerParametersCache ( )
2007-09-03 00:52:00 +02:00
void BuildReferenceAndPointerParametersCache ( )
{
foreach ( Parameter p in this )
{
2007-10-21 17:48:52 +02:00
if ( p . Pointer | | p . CurrentType . Contains ( "IntPtr" ) )
2007-09-03 00:52:00 +02:00
hasPointerParameters = true ;
if ( p . Reference )
hasReferenceParameters = true ;
}
}
2007-10-21 17:48:52 +02:00
#endregion
2007-09-03 00:52:00 +02:00
#region new public void Add ( Parameter p )
2007-09-02 02:40:43 +02:00
new public void Add ( Parameter p )
{
2007-09-03 00:52:00 +02:00
Rebuild = true ;
2007-09-02 02:40:43 +02:00
base . Add ( p ) ;
}
2007-09-03 00:52:00 +02:00
#endregion
2007-10-21 17:48:52 +02:00
public override 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
}
2007-10-21 17:48:52 +02:00
#region public string ToString ( bool override_unsafe_setting )
2007-08-01 11:27:57 +02:00
/// <summary>
/// Gets the parameter declaration string.
/// </summary>
2007-10-21 17:48:52 +02: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 11:27:57 +02:00
/// <returns>The parameter list of an opengl function in the form ( [parameters] )</returns>
2007-10-21 17:48:52 +02:00
public string ToString ( bool override_unsafe_setting )
2007-07-23 02:15:18 +02:00
{
2007-10-21 17:48:52 +02:00
Rebuild | = unsafe_types_allowed ! = override_unsafe_setting ;
unsafe_types_allowed = override_unsafe_setting ;
2007-09-03 00:52:00 +02:00
if ( ! Rebuild )
2007-09-02 02:40:43 +02:00
{
return cache ;
}
else
2007-07-23 02:15:18 +02:00
{
2007-09-03 00:52:00 +02:00
BuildCache ( ) ;
return cache ;
}
}
#endregion
2007-10-21 17:48:52 +02:00
#region void BuildToStringCache ( bool override_unsafe_setting )
2007-09-03 00:52:00 +02:00
2007-10-21 17:48:52 +02:00
void BuildToStringCache ( bool override_unsafe_setting )
2007-09-03 00:52:00 +02:00
{
2007-10-21 17:48:52 +02:00
unsafe_types_allowed = override_unsafe_setting ;
2007-09-03 00:52:00 +02:00
StringBuilder sb = new StringBuilder ( ) ;
sb . Append ( "(" ) ;
if ( this . Count > 0 )
{
foreach ( Parameter p in this )
2007-07-23 02:15:18 +02:00
{
2007-10-21 17:48:52 +02:00
sb . Append ( p . ToString ( override_unsafe_setting ) ) ;
2007-09-03 00:52:00 +02:00
sb . Append ( ", " ) ;
2007-07-23 02:15:18 +02:00
}
2007-09-03 00:52:00 +02:00
sb . Replace ( ", " , ")" , sb . Length - 2 , 2 ) ;
2007-09-02 02:40:43 +02:00
}
2007-09-03 00:52:00 +02:00
else
sb . Append ( ")" ) ;
cache = sb . ToString ( ) ;
2007-07-23 02:15:18 +02:00
}
2007-08-01 11:27:57 +02:00
#endregion
2007-09-03 00:52:00 +02:00
#region public string CallString ( )
2007-08-01 23:14:39 +02:00
2007-09-03 00:52:00 +02:00
public string CallString ( )
2007-08-01 23:14:39 +02:00
{
2007-09-03 00:52:00 +02:00
if ( ! Rebuild )
2007-09-02 02:40:43 +02:00
{
return callStringCache ;
}
else
{
2007-09-03 00:52:00 +02: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 23:14:39 +02:00
2007-09-03 00:52:00 +02:00
sb . Append ( "(" ) ;
2007-08-01 23:14:39 +02:00
2007-09-03 00:52:00 +02:00
if ( this . Count > 0 )
{
foreach ( Parameter p in this )
2007-08-01 23:14:39 +02:00
{
2007-09-03 00:52:00 +02:00
if ( p . Unchecked )
sb . Append ( "unchecked((" + p . CurrentType + ")" ) ;
if ( p . CurrentType ! = "object" )
2007-08-01 23:14:39 +02:00
{
2007-09-03 00:52:00 +02: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 17:48:52 +02: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-03 00:52:00 +02:00
}
else
2007-08-20 14:25:48 +02:00
{
2007-09-03 00:52:00 +02:00
sb . Append ( String . Format ( "({0})" , p . CurrentType ) ) ;
2007-08-20 14:25:48 +02:00
}
2007-09-03 00:52:00 +02:00
}
2007-08-01 23:14:39 +02:00
2007-09-03 00:52:00 +02:00
sb . Append (
Utilities . Keywords . Contains ( p . Name ) ? "@" + p . Name : p . Name
) ;
2007-08-01 23:14:39 +02:00
2007-09-03 00:52:00 +02:00
if ( p . Unchecked )
sb . Append ( ")" ) ;
2007-08-01 23:14:39 +02:00
2007-09-03 00:52:00 +02:00
sb . Append ( ", " ) ;
2007-09-02 02:40:43 +02:00
}
2007-09-03 00:52:00 +02:00
sb . Replace ( ", " , ")" , sb . Length - 2 , 2 ) ;
2007-09-02 02:40:43 +02:00
}
2007-09-03 00:52:00 +02:00
else
{
sb . Append ( ")" ) ;
}
callStringCache = sb . ToString ( ) ;
2007-08-01 23:14:39 +02:00
}
2007-09-03 00:52:00 +02:00
#endregion
2007-07-23 02:15:18 +02:00
public bool ContainsType ( string type )
{
foreach ( Parameter p in this )
2007-08-01 23:14:39 +02:00
if ( p . CurrentType = = type )
2007-07-23 02:15:18 +02:00
return true ;
return false ;
}
}
}