• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }