Details | Last modification | View Log | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 1452 | chris | 1 | #region --- License --- |
| 2 | /* Copyright (c) 2006, 2007 Stefanos Apostolopoulos |
||
| 3 | * See license.txt for license info |
||
| 4 | */ |
||
| 5 | #endregion |
||
| 6 | |||
| 7 | using System; |
||
| 8 | using System.Diagnostics; |
||
| 9 | using System.Globalization; |
||
| 10 | using System.Linq; |
||
| 11 | using System.Text; |
||
| 12 | |||
| 13 | namespace Bind.Structures |
||
| 14 | { |
||
| 15 | /// <summary> |
||
| 16 | /// Represents an opengl constant in C# format. Both the constant name and value |
||
| 17 | /// can be retrieved or set. The value can be either a number, another constant |
||
| 18 | /// or an alias to a constant |
||
| 19 | /// </summary> |
||
| 20 | public class Constant |
||
| 21 | { |
||
| 22 | static StringBuilder translator = new StringBuilder(); |
||
| 23 | |||
| 24 | #region PreviousName |
||
| 25 | |||
| 26 | string previous_name; |
||
| 27 | |||
| 28 | // Gets the name prior to translation. |
||
| 29 | public string PreviousName |
||
| 30 | { |
||
| 31 | get { return previous_name; } |
||
| 32 | private set { previous_name = value; } |
||
| 33 | } |
||
| 34 | |||
| 35 | #endregion |
||
| 36 | |||
| 37 | #region public string Name |
||
| 38 | |||
| 39 | string _name; |
||
| 40 | |||
| 41 | /// <summary> |
||
| 42 | /// Gets or sets the name of the opengl constant (eg. GL_LINES). |
||
| 43 | /// Undergoes processing unless the Settings.Legacy.NoAdvancedEnumProcessing flag is set. |
||
| 44 | /// </summary> |
||
| 45 | public string Name |
||
| 46 | { |
||
| 47 | get { return _name; } |
||
| 48 | set |
||
| 49 | { |
||
| 50 | if (!String.IsNullOrEmpty(value)) |
||
| 51 | _name = Translate(value.Trim(), false); |
||
| 52 | else _name = value; |
||
| 53 | |||
| 54 | PreviousName = value; |
||
| 55 | } |
||
| 56 | } |
||
| 57 | |||
| 58 | #endregion |
||
| 59 | |||
| 60 | #region public string Value |
||
| 61 | |||
| 62 | string _value; |
||
| 63 | |||
| 64 | /// <summary> |
||
| 65 | /// Gets or sets the value of the opengl constant (eg. 0x00000001). |
||
| 66 | /// </summary> |
||
| 67 | public string Value |
||
| 68 | { |
||
| 69 | get |
||
| 70 | { |
||
| 71 | return _value; |
||
| 72 | } |
||
| 73 | set |
||
| 74 | { |
||
| 75 | if (!String.IsNullOrEmpty(value)) |
||
| 76 | { |
||
| 77 | value = value.Trim(); |
||
| 78 | |||
| 79 | if (value.ToLower() == " 0xffffffffffffffff") Debugger.Break(); |
||
| 80 | // Check whether this value is a number and make sure the Unchecked property is set correctly. |
||
| 81 | ulong number; |
||
| 82 | if (value.ToLower().StartsWith("0x")) |
||
| 83 | { |
||
| 84 | // Trim the unsigned or long specifiers used in C constants ('u' or 'ull'). |
||
| 85 | if (value.ToLower().EndsWith("ull")) |
||
| 86 | value = value.Substring(0, value.Length - 3); |
||
| 87 | if (value.ToLower().EndsWith("u")) |
||
| 88 | value = value.Substring(0, value.Length - 1); |
||
| 89 | } |
||
| 90 | if (UInt64.TryParse(value.ToLower().Replace("0x", String.Empty), NumberStyles.AllowHexSpecifier, null, out number)) |
||
| 91 | { |
||
| 92 | // The value is a number, check if it should be unchecked. |
||
| 93 | if (number > 0x7FFFFFFF) |
||
| 94 | Unchecked = true; |
||
| 95 | } |
||
| 96 | else |
||
| 97 | { |
||
| 98 | // The value is not a number. Strip the prefix. |
||
| 99 | if (value.StartsWith(Settings.ConstantPrefix)) |
||
| 100 | value = value.Substring(Settings.ConstantPrefix.Length); |
||
| 101 | |||
| 102 | // If the name now starts with a digit (doesn't matter whether we |
||
| 103 | // stripped "GL_" above), add a "GL_" prefix. |
||
| 104 | // (e.g. GL_4_BYTES). |
||
| 105 | if (Char.IsDigit(value[0])) |
||
| 106 | value = Settings.ConstantPrefix + value; |
||
| 107 | } |
||
| 108 | } |
||
| 109 | |||
| 110 | _value = Translate(value, true); |
||
| 111 | } |
||
| 112 | } |
||
| 113 | |||
| 114 | #endregion |
||
| 115 | |||
| 116 | #region public string Reference |
||
| 117 | |||
| 118 | string _reference; |
||
| 119 | |||
| 120 | /// <summary> |
||
| 121 | /// Gets or sets a string indicating the OpenGL enum reference by this constant. |
||
| 122 | /// Can be null. |
||
| 123 | /// </summary> |
||
| 124 | public string Reference |
||
| 125 | { |
||
| 126 | get { return _reference; } |
||
| 127 | set |
||
| 128 | { |
||
| 129 | if (!String.IsNullOrEmpty(value)) |
||
| 130 | _reference = Enum.TranslateName(value.Trim()); |
||
| 131 | else _reference = value; |
||
| 132 | } |
||
| 133 | } |
||
| 134 | |||
| 135 | #endregion |
||
| 136 | |||
| 137 | #region public bool Unchecked |
||
| 138 | |||
| 139 | private bool @unchecked; |
||
| 140 | |||
| 141 | public bool Unchecked |
||
| 142 | { |
||
| 143 | get { return @unchecked; } |
||
| 144 | set { @unchecked = value; } |
||
| 145 | } |
||
| 146 | |||
| 147 | #endregion |
||
| 148 | |||
| 149 | #region Constructors |
||
| 150 | |||
| 151 | /// <summary> |
||
| 152 | /// Creates an empty Constant. |
||
| 153 | /// </summary> |
||
| 154 | public Constant() |
||
| 155 | { |
||
| 156 | } |
||
| 157 | |||
| 158 | /// <summary> |
||
| 159 | /// Creates a Constant with the given name and value. |
||
| 160 | /// </summary> |
||
| 161 | /// <param name="name">The Name of the Constant.</param> |
||
| 162 | /// <param name="value">The Type of the Constant.</param> |
||
| 163 | public Constant(string name, string value) |
||
| 164 | { |
||
| 165 | Name = name; |
||
| 166 | Value = value; |
||
| 167 | } |
||
| 168 | |||
| 169 | #endregion |
||
| 170 | |||
| 171 | #region Translate |
||
| 172 | |||
| 173 | public static string Translate(string s, bool isValue) |
||
| 174 | { |
||
| 175 | translator.Remove(0, translator.Length); |
||
| 176 | |||
| 177 | // Translate the constant's name to match .Net naming conventions |
||
| 178 | bool name_is_all_caps = s.AsEnumerable().All(c => Char.IsLetter(c) ? Char.IsUpper(c) : true); |
||
| 179 | bool name_contains_underscore = s.Contains("_"); |
||
| 180 | if ((Settings.Compatibility & Settings.Legacy.NoAdvancedEnumProcessing) == Settings.Legacy.None && |
||
| 181 | (name_is_all_caps || name_contains_underscore)) |
||
| 182 | { |
||
| 183 | bool next_char_uppercase = true; |
||
| 184 | bool is_after_digit = false; |
||
| 185 | |||
| 186 | if (!isValue && Char.IsDigit(s[0])) |
||
| 187 | translator.Insert(0, Settings.ConstantPrefix); |
||
| 188 | |||
| 189 | foreach (char c in s) |
||
| 190 | { |
||
| 191 | if (c == '_') |
||
| 192 | next_char_uppercase = true; |
||
| 193 | else if (Char.IsDigit(c)) |
||
| 194 | { |
||
| 195 | is_after_digit = true; |
||
| 196 | translator.Append(c); |
||
| 197 | } |
||
| 198 | else |
||
| 199 | { |
||
| 200 | translator.Append(next_char_uppercase || (is_after_digit && c == 'd') ? Char.ToUpper(c) : Char.ToLower(c)); |
||
| 201 | is_after_digit = next_char_uppercase = false; |
||
| 202 | } |
||
| 203 | } |
||
| 204 | |||
| 205 | translator[0] = Char.ToUpper(translator[0]); |
||
| 206 | } |
||
| 207 | else |
||
| 208 | translator.Append(s); |
||
| 209 | |||
| 210 | return translator.ToString(); |
||
| 211 | } |
||
| 212 | |||
| 213 | #endregion |
||
| 214 | |||
| 215 | /// <summary> |
||
| 216 | /// Replces the Value of the given constant with the value referenced by the [c.Reference, c.Value] pair. |
||
| 217 | /// </summary> |
||
| 218 | /// <param name="c">The Constant to translate</param> |
||
| 219 | /// <param name="enums">The list of enums to check.</param> |
||
| 220 | /// <param name="auxEnums">The list of auxilliary enums to check.</param> |
||
| 221 | /// <returns>True if the reference was found; false otherwise.</returns> |
||
| 222 | public static bool TranslateConstantWithReference(Constant c, EnumCollection enums, EnumCollection auxEnums) |
||
| 223 | { |
||
| 224 | if (!String.IsNullOrEmpty(c.Reference)) |
||
| 225 | { |
||
| 226 | Constant referenced_constant; |
||
| 227 | |||
| 228 | if (enums.ContainsKey(c.Reference) && enums[c.Reference].ConstantCollection.ContainsKey(c.Value)) |
||
| 229 | { |
||
| 230 | TranslateConstantWithReference(enums[c.Reference].ConstantCollection[c.Value] as Constant, enums, auxEnums); |
||
| 231 | referenced_constant = (enums[c.Reference].ConstantCollection[c.Value] as Constant); |
||
| 232 | } |
||
| 233 | else if (auxEnums.ContainsKey(c.Reference) && auxEnums[c.Reference].ConstantCollection.ContainsKey(c.Value)) |
||
| 234 | { |
||
| 235 | TranslateConstantWithReference(auxEnums[c.Reference].ConstantCollection[c.Value] as Constant, enums, auxEnums); |
||
| 236 | referenced_constant = (auxEnums[c.Reference].ConstantCollection[c.Value] as Constant); |
||
| 237 | } |
||
| 238 | else |
||
| 239 | { |
||
| 240 | Console.WriteLine("[Warning] Reference {0} not found for token {1}.", c.Reference, c); |
||
| 241 | return false; |
||
| 242 | } |
||
| 243 | //else throw new InvalidOperationException(String.Format("Unknown Enum \"{0}\" referenced by Constant \"{1}\"", |
||
| 244 | // c.Reference, c.ToString())); |
||
| 245 | |||
| 246 | c.Value = referenced_constant.Value; |
||
| 247 | c.Reference = null; |
||
| 248 | c.Unchecked = referenced_constant.Unchecked; |
||
| 249 | } |
||
| 250 | |||
| 251 | return true; |
||
| 252 | } |
||
| 253 | |||
| 254 | #region public override string ToString() |
||
| 255 | |||
| 256 | /// <summary> |
||
| 257 | /// Returns a string that represents the full constant declaration without decorations |
||
| 258 | /// (eg GL_XXX_YYY = (int)0xDEADBEEF or GL_XXX_YYY = GL_ZZZ.FOOBAR). |
||
| 259 | /// </summary> |
||
| 260 | /// <returns></returns> |
||
| 261 | public override string ToString() |
||
| 262 | { |
||
| 263 | if (String.IsNullOrEmpty(Name)) |
||
| 264 | return ""; |
||
| 265 | return String.Format("{0} = {1}((int){2}{3})", |
||
| 266 | Name, Unchecked ? "unchecked" : "", |
||
| 267 | !String.IsNullOrEmpty(Reference) ? Reference + "." : "", Value); |
||
| 268 | |||
| 269 | //return String.Format("{0} = {1}((int){2})", Name, Unchecked ? "unchecked" : "", Value); |
||
| 270 | } |
||
| 271 | |||
| 272 | #endregion |
||
| 273 | } |
||
| 274 | } |