mirror of
https://github.com/Ryujinx/Opentk.git
synced 2025-03-28 15:56:52 +00:00
Remove enum and constant processing from the classes with the same name and move it into its own file.
This commit is contained in:
parent
745dae3dbe
commit
2a1d85a4c0
290
Source/Bind/EnumProcessor.cs
Normal file
290
Source/Bind/EnumProcessor.cs
Normal file
|
@ -0,0 +1,290 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Xml.XPath;
|
||||
using Bind.Structures;
|
||||
using Enum = Bind.Structures.Enum;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Bind
|
||||
{
|
||||
class EnumProcessor
|
||||
{
|
||||
const string Path = "/overrides/replace/enum[@name='{0}']";
|
||||
XPathDocument Overrides { get; set; }
|
||||
|
||||
public EnumProcessor(XPathDocument overrides)
|
||||
{
|
||||
if (overrides == null)
|
||||
throw new ArgumentNullException("overrides");
|
||||
|
||||
Overrides = overrides;
|
||||
}
|
||||
|
||||
public EnumCollection Process(EnumCollection enums)
|
||||
{
|
||||
var nav = Overrides.CreateNavigator();
|
||||
enums = ProcessNames(enums, nav);
|
||||
enums = ProcessConstants(enums, nav);
|
||||
return enums;
|
||||
}
|
||||
|
||||
static EnumCollection ProcessNames(EnumCollection enums, XPathNavigator nav)
|
||||
{
|
||||
EnumCollection processed_enums = new EnumCollection();
|
||||
foreach (var e in enums.Values)
|
||||
{
|
||||
// Note that we cannot modify a collection while iterating over it,
|
||||
// so we keep a list of modified enums and remove/readd the
|
||||
// modified items to refresh their keys.
|
||||
string name = e.Name;
|
||||
name = ReplaceName(nav, name);
|
||||
name = TranslateEnumName(name);
|
||||
e.Name = name;
|
||||
processed_enums.Add(e.Name, e);
|
||||
}
|
||||
return processed_enums;
|
||||
}
|
||||
|
||||
static string ReplaceName(XPathNavigator nav, string name)
|
||||
{
|
||||
var enum_override = nav.SelectSingleNode(String.Format(Path, name));
|
||||
if (enum_override != null)
|
||||
{
|
||||
var name_override = enum_override.SelectSingleNode("name");
|
||||
if (name_override != null)
|
||||
{
|
||||
name = name_override.Value;
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
public static string TranslateEnumName(string name)
|
||||
{
|
||||
if (Utilities.Keywords.Contains(name))
|
||||
return name;
|
||||
|
||||
if (Char.IsDigit(name[0]))
|
||||
name = Settings.ConstantPrefix + name;
|
||||
|
||||
StringBuilder translator = new StringBuilder(name.Length);
|
||||
|
||||
// Process according to these rules:
|
||||
// 1. if current char is '_', '-' remove it and make next char uppercase
|
||||
// 2. if current char is or '0-9' keep it and make next char uppercase.
|
||||
// 3. if current character is uppercase make next char lowercase.
|
||||
bool is_after_underscore_or_number = true;
|
||||
bool is_previous_uppercase = false;
|
||||
foreach (char c in name)
|
||||
{
|
||||
char char_to_add;
|
||||
if (c == '_' || c == '-')
|
||||
{
|
||||
is_after_underscore_or_number = true;
|
||||
continue; // skip this character
|
||||
}
|
||||
else if (Char.IsDigit(c))
|
||||
{
|
||||
is_after_underscore_or_number = true;
|
||||
}
|
||||
|
||||
if (is_after_underscore_or_number)
|
||||
char_to_add = Char.ToUpper(c);
|
||||
else if (is_previous_uppercase)
|
||||
char_to_add = Char.ToLower(c);
|
||||
else
|
||||
char_to_add = c;
|
||||
|
||||
translator.Append(char_to_add);
|
||||
|
||||
is_previous_uppercase = Char.IsUpper(c);
|
||||
is_after_underscore_or_number = false;
|
||||
}
|
||||
|
||||
// First letter should always be uppercase in order
|
||||
// to conform to .Net style guidelines.
|
||||
translator[0] = Char.ToUpper(translator[0]);
|
||||
|
||||
// Replace a number of words that do not play well
|
||||
// with the previous process (i.e. they have two
|
||||
// consecutive uppercase letters).
|
||||
translator.Replace("Pname", "PName");
|
||||
translator.Replace("AttribIp", "AttribIP");
|
||||
translator.Replace("SRgb", "Srgb");
|
||||
|
||||
name = translator.ToString();
|
||||
if (name.StartsWith(Settings.EnumPrefix))
|
||||
name = name.Substring(Settings.EnumPrefix.Length);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
static EnumCollection ProcessConstants(EnumCollection enums, XPathNavigator nav)
|
||||
{
|
||||
foreach (var e in enums.Values)
|
||||
{
|
||||
var processed_constants = new Dictionary<string, Constant>(e.ConstantCollection.Count);
|
||||
foreach (Constant c in e.ConstantCollection.Values)
|
||||
{
|
||||
c.Name = TranslateConstantName(c.Name, false);
|
||||
c.Value = TranslateConstantValue(c.Value);
|
||||
if (!processed_constants.ContainsKey(c.Name))
|
||||
processed_constants.Add(c.Name, c);
|
||||
}
|
||||
e.ConstantCollection = processed_constants;
|
||||
|
||||
var enum_override = nav.SelectSingleNode(String.Format(Path, e.Name));
|
||||
foreach (Constant c in e.ConstantCollection.Values)
|
||||
{
|
||||
ReplaceConstant(enum_override, c);
|
||||
ResolveBareAlias(c, enums);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var e in enums.Values)
|
||||
{
|
||||
ResolveAliases(e, enums);
|
||||
}
|
||||
|
||||
return enums;
|
||||
}
|
||||
|
||||
static void ReplaceConstant(XPathNavigator enum_override, Constant c)
|
||||
{
|
||||
if (enum_override != null)
|
||||
{
|
||||
XPathNavigator constant_override = enum_override.SelectSingleNode(String.Format("token[@name='{0}']", c.PreviousName)) ??
|
||||
enum_override.SelectSingleNode(String.Format("token[@name={0}]", c.Name));
|
||||
if (constant_override != null)
|
||||
{
|
||||
foreach (XPathNavigator node in constant_override.SelectChildren(XPathNodeType.Element))
|
||||
{
|
||||
switch (node.Name)
|
||||
{
|
||||
case "name": c.Name = (string)node.TypedValue; break;
|
||||
case "value": c.Value = (string)node.TypedValue; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static string TranslateConstantName(string s, bool isValue)
|
||||
{
|
||||
StringBuilder translator = new StringBuilder(s.Length);
|
||||
|
||||
// Translate the constant's name to match .Net naming conventions
|
||||
bool name_is_all_caps = s.AsEnumerable().All(c => Char.IsLetter(c) ? Char.IsUpper(c) : true);
|
||||
bool name_contains_underscore = s.Contains("_");
|
||||
if ((Settings.Compatibility & Settings.Legacy.NoAdvancedEnumProcessing) == Settings.Legacy.None &&
|
||||
(name_is_all_caps || name_contains_underscore))
|
||||
{
|
||||
bool next_char_uppercase = true;
|
||||
bool is_after_digit = false;
|
||||
|
||||
if (!isValue && Char.IsDigit(s[0]))
|
||||
s = Settings.ConstantPrefix + s;
|
||||
|
||||
foreach (char c in s)
|
||||
{
|
||||
if (c == '_' || c == '-')
|
||||
{
|
||||
next_char_uppercase = true;
|
||||
continue; // do not add these chars to output
|
||||
}
|
||||
else if (Char.IsDigit(c))
|
||||
{
|
||||
translator.Append(c);
|
||||
is_after_digit = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check for common 'digit'-'letter' abbreviations:
|
||||
// 2D, 3D, R3G3B2, etc. The abbreviated characters
|
||||
// should be made upper case.
|
||||
if (is_after_digit && (c == 'D' || c == 'R' || c == 'G' || c == 'B' || c == 'A'))
|
||||
{
|
||||
next_char_uppercase = true;
|
||||
}
|
||||
translator.Append(next_char_uppercase ? Char.ToUpper(c) : Char.ToLower(c));
|
||||
is_after_digit = next_char_uppercase = false;
|
||||
}
|
||||
}
|
||||
|
||||
translator[0] = Char.ToUpper(translator[0]);
|
||||
}
|
||||
else
|
||||
translator.Append(s);
|
||||
|
||||
return translator.ToString();
|
||||
}
|
||||
|
||||
public static string TranslateConstantValue(string value)
|
||||
{
|
||||
if (value.ToLower() == " 0xffffffffffffffff") System.Diagnostics.Debugger.Break();
|
||||
|
||||
// Remove decorations to get a pure number (e.g. 0x80u -> 80).
|
||||
if (value.ToLower().StartsWith("0x"))
|
||||
{
|
||||
// Trim the unsigned or long specifiers used in C constants ('u' or 'ull').
|
||||
if (value.ToLower().EndsWith("ull"))
|
||||
value = value.Substring(0, value.Length - 3);
|
||||
if (value.ToLower().EndsWith("u"))
|
||||
value = value.Substring(0, value.Length - 1);
|
||||
}
|
||||
|
||||
// Strip the prefix, if any.
|
||||
if (value.StartsWith(Settings.ConstantPrefix))
|
||||
value = value.Substring(Settings.ConstantPrefix.Length);
|
||||
|
||||
return TranslateConstantName(value, IsValue(value));
|
||||
}
|
||||
|
||||
// There are cases when a value is an aliased constant, with no enum specified.
|
||||
// (e.g. FOG_COORD_ARRAY_TYPE = GL_FOG_COORDINATE_ARRAY_TYPE)
|
||||
// In this case try searching all enums for the correct constant to alias (stupid opengl specs).
|
||||
// This turns every bare alias into a normal alias that is processed afterwards.
|
||||
static void ResolveBareAlias(Constant c, EnumCollection enums)
|
||||
{
|
||||
// Constants are considered bare aliases when they don't have a reference and
|
||||
// their values are non-numeric.
|
||||
if (String.IsNullOrEmpty(c.Reference) && !Char.IsDigit(c.Value[0]))
|
||||
{
|
||||
// Skip generic GLenum, as this doesn't help resolve references.
|
||||
foreach (Enum e in enums.Values.Where(e => e.Name != "GLenum"))
|
||||
{
|
||||
if (e.ConstantCollection.ContainsKey(c.Value))
|
||||
{
|
||||
c.Reference = e.Name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve 'use' tokens by searching and replacing the correct
|
||||
// value from the enum collection.
|
||||
// Tokens that can't be resolved are removed.
|
||||
static void ResolveAliases(Enum e, EnumCollection enums)
|
||||
{
|
||||
// Note that we have the removal must be a separate step, since
|
||||
// we cannot modify a collection while iterating with foreach.
|
||||
var broken_references = e.ConstantCollection.Values
|
||||
.Where(c => !Constant.TranslateConstantWithReference(c, enums, null))
|
||||
.Select(c => c).ToList();
|
||||
foreach (var c in broken_references)
|
||||
e.ConstantCollection.Remove(c.Name);
|
||||
}
|
||||
|
||||
static bool IsValue(string test)
|
||||
{
|
||||
ulong number;
|
||||
|
||||
// Check if the result is a number.
|
||||
return UInt64.TryParse(test.ToLower().Replace("0x", String.Empty),
|
||||
NumberStyles.AllowHexSpecifier, null, out number);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -47,11 +47,10 @@ namespace Bind.Structures
|
|||
get { return _name; }
|
||||
set
|
||||
{
|
||||
if (!String.IsNullOrEmpty(value))
|
||||
_name = Translate(value.Trim(), false);
|
||||
else _name = value;
|
||||
|
||||
PreviousName = value;
|
||||
if (String.IsNullOrEmpty(value))
|
||||
throw new ArgumentNullException("value");
|
||||
PreviousName = _name;
|
||||
_name = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,48 +65,16 @@ namespace Bind.Structures
|
|||
/// </summary>
|
||||
public string Value
|
||||
{
|
||||
get
|
||||
get
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (!String.IsNullOrEmpty(value))
|
||||
{
|
||||
value = value.Trim();
|
||||
if (String.IsNullOrEmpty(value))
|
||||
throw new ArgumentNullException("value");
|
||||
|
||||
if (value.ToLower() == " 0xffffffffffffffff") Debugger.Break();
|
||||
// Check whether this value is a number and make sure the Unchecked property is set correctly.
|
||||
ulong number;
|
||||
if (value.ToLower().StartsWith("0x"))
|
||||
{
|
||||
// Trim the unsigned or long specifiers used in C constants ('u' or 'ull').
|
||||
if (value.ToLower().EndsWith("ull"))
|
||||
value = value.Substring(0, value.Length - 3);
|
||||
if (value.ToLower().EndsWith("u"))
|
||||
value = value.Substring(0, value.Length - 1);
|
||||
}
|
||||
if (UInt64.TryParse(value.ToLower().Replace("0x", String.Empty), NumberStyles.AllowHexSpecifier, null, out number))
|
||||
{
|
||||
// The value is a number, check if it should be unchecked.
|
||||
if (number > 0x7FFFFFFF)
|
||||
Unchecked = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The value is not a number. Strip the prefix.
|
||||
if (value.StartsWith(Settings.ConstantPrefix))
|
||||
value = value.Substring(Settings.ConstantPrefix.Length);
|
||||
|
||||
// If the name now starts with a digit (doesn't matter whether we
|
||||
// stripped "GL_" above), add a "GL_" prefix.
|
||||
// (e.g. GL_4_BYTES).
|
||||
if (Char.IsDigit(value[0]))
|
||||
value = Settings.ConstantPrefix + value;
|
||||
}
|
||||
}
|
||||
|
||||
_value = Translate(value, true);
|
||||
_value = value;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -127,7 +94,7 @@ namespace Bind.Structures
|
|||
set
|
||||
{
|
||||
if (!String.IsNullOrEmpty(value))
|
||||
_reference = Enum.TranslateName(value.Trim());
|
||||
_reference = EnumProcessor.TranslateEnumName(value.Trim());
|
||||
else _reference = value;
|
||||
}
|
||||
}
|
||||
|
@ -136,12 +103,17 @@ namespace Bind.Structures
|
|||
|
||||
#region public bool Unchecked
|
||||
|
||||
private bool @unchecked;
|
||||
|
||||
public bool Unchecked
|
||||
{
|
||||
get { return @unchecked; }
|
||||
set { @unchecked = value; }
|
||||
get
|
||||
{
|
||||
// Check if the value is a number larger than Int32.MaxValue.
|
||||
ulong number;
|
||||
string test = Value;
|
||||
return UInt64.TryParse(test.ToLower().Replace("0x", String.Empty),
|
||||
NumberStyles.AllowHexSpecifier, null, out number) &&
|
||||
number > Int32.MaxValue;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -170,6 +142,7 @@ namespace Bind.Structures
|
|||
|
||||
#region Translate
|
||||
|
||||
[Obsolete]
|
||||
public static string Translate(string s, bool isValue)
|
||||
{
|
||||
translator.Remove(0, translator.Length);
|
||||
|
@ -221,6 +194,11 @@ namespace Bind.Structures
|
|||
/// <returns>True if the reference was found; false otherwise.</returns>
|
||||
public static bool TranslateConstantWithReference(Constant c, EnumCollection enums, EnumCollection auxEnums)
|
||||
{
|
||||
if (c == null)
|
||||
throw new ArgumentNullException("c");
|
||||
if (enums == null)
|
||||
throw new ArgumentNullException("enums");
|
||||
|
||||
if (!String.IsNullOrEmpty(c.Reference))
|
||||
{
|
||||
Constant referenced_constant;
|
||||
|
@ -230,7 +208,7 @@ namespace Bind.Structures
|
|||
TranslateConstantWithReference(enums[c.Reference].ConstantCollection[c.Value] as Constant, enums, auxEnums);
|
||||
referenced_constant = (enums[c.Reference].ConstantCollection[c.Value] as Constant);
|
||||
}
|
||||
else if (auxEnums.ContainsKey(c.Reference) && auxEnums[c.Reference].ConstantCollection.ContainsKey(c.Value))
|
||||
else if (auxEnums != null && auxEnums.ContainsKey(c.Reference) && auxEnums[c.Reference].ConstantCollection.ContainsKey(c.Value))
|
||||
{
|
||||
TranslateConstantWithReference(auxEnums[c.Reference].ConstantCollection[c.Value] as Constant, enums, auxEnums);
|
||||
referenced_constant = (auxEnums[c.Reference].ConstantCollection[c.Value] as Constant);
|
||||
|
@ -245,7 +223,6 @@ namespace Bind.Structures
|
|||
|
||||
c.Value = referenced_constant.Value;
|
||||
c.Reference = null;
|
||||
c.Unchecked = referenced_constant.Unchecked;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -127,7 +127,7 @@ namespace Bind.Structures
|
|||
public string Category
|
||||
{
|
||||
get { return _category; }
|
||||
set { _category = Enum.TranslateName(value); }
|
||||
set { _category = EnumProcessor.TranslateEnumName(value); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -113,6 +113,17 @@ namespace Bind.Structures
|
|||
public IDictionary<string, Constant> ConstantCollection
|
||||
{
|
||||
get { return _constant_collection; }
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
throw new ArgumentNullException("value");
|
||||
|
||||
_constant_collection.Clear();
|
||||
foreach (var item in value)
|
||||
{
|
||||
_constant_collection.Add(item.Key, item.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -120,6 +131,7 @@ namespace Bind.Structures
|
|||
#region TranslateName
|
||||
|
||||
// Translate the constant's name to match .Net naming conventions
|
||||
[Obsolete]
|
||||
public static string TranslateName(string name)
|
||||
{
|
||||
if (String.IsNullOrEmpty(name))
|
||||
|
@ -223,6 +235,7 @@ namespace Bind.Structures
|
|||
Utilities.Merge(this, e);
|
||||
}
|
||||
|
||||
[Obsolete]
|
||||
internal void Translate(XPathDocument overrides)
|
||||
{
|
||||
if (overrides == null)
|
||||
|
@ -247,7 +260,7 @@ namespace Bind.Structures
|
|||
}
|
||||
}
|
||||
|
||||
name = Enum.TranslateName(name);
|
||||
name = EnumProcessor.TranslateEnumName(name);
|
||||
if (name != e.Name)
|
||||
{
|
||||
keys_to_update.Add(e.Name);
|
||||
|
|
|
@ -394,7 +394,7 @@ namespace Bind.Structures
|
|||
// Better match: enum.Name == function.Category (e.g. GL_VERSION_1_1 etc)
|
||||
if (Enum.GLEnums.ContainsKey(category))
|
||||
{
|
||||
QualifiedType = String.Format("{0}.{1}", Settings.EnumsOutput, Enum.TranslateName(category));
|
||||
QualifiedType = String.Format("{0}.{1}", Settings.EnumsOutput, EnumProcessor.TranslateEnumName(category));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue