1 /* 2 * Created by SharpDevelop. 3 * User: lextm 4 * Date: 2008/5/17 5 * Time: 17:14 6 * 7 * To change this template use Tools | Options | Coding | Edit Standard Headers. 8 */ 9 10 using System; 11 using System.Configuration; 12 using System.Globalization; 13 using System.Text; 14 15 namespace Lextm.SharpSnmpLib.Mib 16 { 17 /// <summary> 18 /// Description of Symbol. 19 /// </summary> 20 public sealed class Symbol : IEquatable<Symbol> 21 { 22 private readonly string _text; 23 private readonly int _row; 24 private readonly int _column; 25 private readonly string _file; 26 Symbol(string text)27 private Symbol(string text) : this(null, text, -1, -1) 28 { 29 } 30 31 /// <summary> 32 /// Creates a <see cref="Symbol"/>. 33 /// </summary> 34 /// <param name="file">File</param> 35 /// <param name="text">Text</param> 36 /// <param name="row">Row number</param> 37 /// <param name="column">column number</param> Symbol(string file, string text, int row, int column)38 public Symbol(string file, string text, int row, int column) 39 { 40 _file = file; 41 _text = text; 42 _row = row; 43 _column = column; 44 } 45 46 /// <summary> 47 /// File. 48 /// </summary> 49 public string File 50 { 51 get 52 { 53 return _file; 54 } 55 } 56 57 /// <summary> 58 /// Row number. 59 /// </summary> 60 public int Row 61 { 62 get 63 { 64 return _row; 65 } 66 } 67 68 /// <summary> 69 /// Column number. 70 /// </summary> 71 public int Column 72 { 73 get 74 { 75 return _column; 76 } 77 } 78 79 /// <summary> 80 /// Returns a <see cref="String"/> that represents this <see cref="Symbol"/>. 81 /// </summary> 82 /// <returns></returns> ToString()83 public override string ToString() 84 { 85 return _text; 86 } 87 88 /// <summary> 89 /// Determines whether the specified <see cref="Object"/> is equal to the current <see cref="Symbol"/>. 90 /// </summary> 91 /// <param name="obj">The <see cref="Object"/> to compare with the current <see cref="Symbol"/>. </param> 92 /// <returns><value>true</value> if the specified <see cref="Object"/> is equal to the current <see cref="Symbol"/>; otherwise, <value>false</value>. 93 /// </returns> Equals(object obj)94 public override bool Equals(object obj) 95 { 96 if (obj == null) 97 { 98 return false; 99 } 100 101 if (ReferenceEquals(this, obj)) 102 { 103 return true; 104 } 105 106 return GetType() == obj.GetType() && Equals((Symbol)obj); 107 } 108 109 /// <summary> 110 /// Serves as a hash function for a particular type. 111 /// </summary> 112 /// <returns>A hash code for the current <see cref="Symbol"/>.</returns> GetHashCode()113 public override int GetHashCode() 114 { 115 return _text.GetHashCode(); 116 } 117 118 /// <summary> 119 /// The equality operator. 120 /// </summary> 121 /// <param name="left">Left <see cref="Symbol"/> object</param> 122 /// <param name="right">Right <see cref="Symbol"/> object</param> 123 /// <returns> 124 /// Returns <c>true</c> if the values of its operands are equal, <c>false</c> otherwise.</returns> operator ==(Symbol left, Symbol right)125 public static bool operator ==(Symbol left, Symbol right) 126 { 127 return Equals(left, right); 128 } 129 130 /// <summary> 131 /// Determines whether the specified <see cref="Symbol"/> is equal to the current <see cref="Symbol"/>. 132 /// </summary> 133 /// <param name="left">Left <see cref="Symbol"/> object</param> 134 /// <param name="right">Right <see cref="Symbol"/> object</param> 135 /// <returns> 136 /// Returns <c>true</c> if the values of its operands are equal, <c>false</c> otherwise.</returns> Equals(Symbol left, Symbol right)137 public static bool Equals(Symbol left, Symbol right) 138 { 139 object l = left; 140 object r = right; 141 if (l == r) 142 { 143 return true; 144 } 145 146 if (l == null || r == null) 147 { 148 return false; 149 } 150 151 return left._text.Equals(right._text); 152 } 153 154 /// <summary> 155 /// The inequality operator. 156 /// </summary> 157 /// <param name="left">Left <see cref="Symbol"/> object</param> 158 /// <param name="right">Right <see cref="Symbol"/> object</param> 159 /// <returns> 160 /// Returns <c>true</c> if the values of its operands are not equal, <c>false</c> otherwise.</returns> operator !=(Symbol left, Symbol right)161 public static bool operator !=(Symbol left, Symbol right) 162 { 163 return !(left == right); 164 } 165 166 #region IEquatable<Symbol> Members 167 /// <summary> 168 /// Indicates whether the current object is equal to another object of the same type. 169 /// </summary> 170 /// <param name="other">An object to compare with this object.</param> 171 /// <returns><value>true</value> if the current object is equal to the <paramref name="other"/> parameter; otherwise, <value>false</value>. 172 /// </returns> Equals(Symbol other)173 public bool Equals(Symbol other) 174 { 175 return Equals(this, other); 176 } 177 178 #endregion 179 180 public static readonly Symbol Definitions = new Symbol("DEFINITIONS"); 181 public static readonly Symbol Begin = new Symbol("BEGIN"); 182 public static readonly Symbol Object = new Symbol("OBJECT"); 183 public static readonly Symbol Identifier = new Symbol("IDENTIFIER"); 184 public static readonly Symbol Assign = new Symbol("::="); 185 public static readonly Symbol OpenBracket = new Symbol("{"); 186 public static readonly Symbol CloseBracket = new Symbol("}"); 187 public static readonly Symbol Comment = new Symbol("--"); 188 public static readonly Symbol Imports = new Symbol("IMPORTS"); 189 public static readonly Symbol Semicolon = new Symbol(";"); 190 public static readonly Symbol From = new Symbol("FROM"); 191 public static readonly Symbol ModuleIdentity = new Symbol("MODULE-IDENTITY"); 192 public static readonly Symbol ObjectType = new Symbol("OBJECT-TYPE"); 193 public static readonly Symbol ObjectGroup = new Symbol("OBJECT-GROUP"); 194 public static readonly Symbol NotificationGroup = new Symbol("NOTIFICATION-GROUP"); 195 public static readonly Symbol ModuleCompliance = new Symbol("MODULE-COMPLIANCE"); 196 public static readonly Symbol Sequence = new Symbol("SEQUENCE"); 197 public static readonly Symbol NotificationType = new Symbol("NOTIFICATION-TYPE"); 198 public static readonly Symbol EOL = new Symbol(Environment.NewLine); 199 public static readonly Symbol ObjectIdentity = new Symbol("OBJECT-IDENTITY"); 200 public static readonly Symbol End = new Symbol("END"); 201 public static readonly Symbol Macro = new Symbol("MACRO"); 202 public static readonly Symbol Choice = new Symbol("CHOICE"); 203 public static readonly Symbol TrapType = new Symbol("TRAP-TYPE"); 204 public static readonly Symbol AgentCapabilities = new Symbol("AGENT-CAPABILITIES"); 205 public static readonly Symbol Comma = new Symbol(","); 206 public static readonly Symbol TextualConvention = new Symbol("TEXTUAL-CONVENTION"); 207 public static readonly Symbol Syntax = new Symbol("SYNTAX"); 208 public static readonly Symbol Bits = new Symbol("BITS"); 209 public static readonly Symbol Octet = new Symbol("OCTET"); 210 public static readonly Symbol String = new Symbol("STRING"); 211 public static readonly Symbol OpenParentheses = new Symbol("("); 212 public static readonly Symbol CloseParentheses = new Symbol(")"); 213 public static readonly Symbol Exports = new Symbol("EXPORTS"); 214 public static readonly Symbol DisplayHint = new Symbol("DISPLAY-HINT"); 215 public static readonly Symbol Status = new Symbol("STATUS"); 216 public static readonly Symbol Description = new Symbol("DESCRIPTION"); 217 public static readonly Symbol Reference = new Symbol("REFERENCE"); 218 public static readonly Symbol DoubleDot = new Symbol(".."); 219 public static readonly Symbol Pipe = new Symbol("|"); 220 public static readonly Symbol Size = new Symbol("SIZE"); 221 public static readonly Symbol Units = new Symbol("UNITS"); 222 public static readonly Symbol MaxAccess = new Symbol("MAX-ACCESS"); 223 public static readonly Symbol Access = new Symbol("ACCESS"); 224 public static readonly Symbol Index = new Symbol("INDEX"); 225 public static readonly Symbol Augments = new Symbol("AUGMENTS"); 226 public static readonly Symbol DefVal = new Symbol("DEFVAL"); 227 public static readonly Symbol Of = new Symbol("OF"); 228 public static readonly Symbol Integer = new Symbol("INTEGER"); 229 public static readonly Symbol Integer32 = new Symbol("Integer32"); 230 public static readonly Symbol IpAddress = new Symbol("IpAddress"); 231 public static readonly Symbol Counter32 = new Symbol("Counter32"); 232 public static readonly Symbol Counter = new Symbol("Counter"); 233 public static readonly Symbol TimeTicks = new Symbol("TimeTicks"); 234 public static readonly Symbol Opaque = new Symbol("Opaque"); 235 public static readonly Symbol Counter64 = new Symbol("Counter64"); 236 public static readonly Symbol Unsigned32 = new Symbol("Unsigned32"); 237 public static readonly Symbol Gauge32 = new Symbol("Gauge32"); 238 public static readonly Symbol Gauge = new Symbol("Gauge"); 239 public static readonly Symbol TruthValue = new Symbol("TruthValue"); 240 public static readonly Symbol Implied = new Symbol("IMPLIED"); 241 Expect(Symbol expected, params Symbol[] orExpected)242 internal void Expect(Symbol expected, params Symbol[] orExpected) 243 { 244 bool isExpected = (this == expected); 245 246 if (!isExpected && (orExpected != null) && (orExpected.Length > 0)) 247 { 248 // check the alternatives 249 for (int i=0; i<orExpected.Length; i++) 250 { 251 if (this == orExpected[i]) 252 { 253 isExpected = true; 254 break; 255 } 256 } 257 } 258 259 if (!isExpected) 260 { 261 if ((orExpected == null) || (orExpected.Length == 0)) 262 { 263 Assert(false, "Unexpected symbol found! Expected '" + expected.ToString() + "'"); 264 } 265 else 266 { 267 StringBuilder msg = new StringBuilder("Unexpected symbol found! Expected one of the following: '"); 268 msg.Append(expected); 269 270 // check the alternatives 271 for (int i=0; i<orExpected.Length; i++) 272 { 273 msg.Append("', '"); 274 msg.Append(expected); 275 } 276 msg.Append("'"); 277 278 Assert(false, msg.ToString()); 279 } 280 } 281 } 282 Assert(bool condition, string message)283 internal void Assert(bool condition, string message) 284 { 285 if (!condition) 286 { 287 throw MibException.Create(message, this); 288 } 289 } 290 AssertIsValidIdentifier()291 internal void AssertIsValidIdentifier() 292 { 293 string message; 294 bool isValid = IsValidIdentifier(ToString(), out message); 295 Assert(isValid, message); 296 } 297 IsValidIdentifier()298 internal bool IsValidIdentifier() 299 { 300 string message; 301 return IsValidIdentifier(ToString(), out message); 302 } 303 IsValidIdentifier(string name, out string message)304 private static bool IsValidIdentifier(string name, out string message) 305 { 306 if (UseStricterValidation && (name.Length < 1 || name.Length > 64)) 307 { 308 message = "an identifier must consist of 1 to 64 letters, digits, and hyphens"; 309 return false; 310 } 311 312 if (!Char.IsLetter(name[0])) 313 { 314 message = "the initial character must be a letter"; 315 return false; 316 } 317 318 if (name.EndsWith("-", StringComparison.Ordinal)) 319 { 320 message = "a hyphen cannot be the last character of an identifier"; 321 return false; 322 } 323 324 if (name.Contains("--")) 325 { 326 message = "a hyphen cannot be immediately followed by another hyphen in an identifier"; 327 return false; 328 } 329 330 if (UseStricterValidation && name.Contains("_")) 331 { 332 message = "underscores are not allowed in identifiers"; 333 return false; 334 } 335 336 // TODO: SMIv2 forbids "-" except in module names and keywords 337 message = null; 338 return true; 339 } 340 341 private static bool? _useStricterValidation; 342 343 private static bool UseStricterValidation 344 { 345 get 346 { 347 if (_useStricterValidation == null) 348 { 349 object setting = ConfigurationManager.AppSettings["StricterValidationEnabled"]; 350 _useStricterValidation = setting != null && Convert.ToBoolean(setting.ToString(), CultureInfo.InvariantCulture); 351 } 352 353 return _useStricterValidation.Value; 354 } 355 } 356 } 357 }