context: // This file is part of SNMP#NET
  // 
  // SNMP#NET is free software: you can redistribute it and/or modify
  // it under the terms of the GNU Lesser Public License as published by
  // the Free Software Foundation, either version 3 of the License, or
  // (at your option) any later version.
  // 
  // SNMP#NET is distributed in the hope that it will be useful,
  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  // GNU General Public License for more details.
  // 
  // You should have received a copy of the GNU General Public License
  // along with SNMP#NET.  If not, see <http://www.gnu.org/licenses/>.
  //
  using System;
  using System.Globalization;
  using System.Collections.Generic;
  using System.Text;
  namespace SnmpSharpNet
  {
  	
  	/// <summary>
  	/// SMI Object Identifier type implementation.
  	/// </summary>
  	[Serializable]
  	public class Oid: AsnType, ICloneable, IComparable, IEnumerable<UInt32>
  	{
  		/// <summary>Internal buffer</summary>
  		protected UInt32[] _data;
  
  		#region Constructors
  
  		/// <summary> Creates a default empty object identifier.
  		/// </summary>
  		public Oid()
  		{
  			_asnType = SnmpConstants.SMI_OBJECTID;
  			_data = null;
  		}
  		
  		/// <summary>Constructor. Initialize ObjectId value to the unsigned integer array</summary>
  		/// <param name="data">Integer array representing objectId</param>
  		public Oid(UInt32[] data)
  			:this()
  		{
  			Set(data);
  		}
  
  		/// <summary>Constructor. Initialize ObjectId value to integer array</summary>
  		/// <param name="data">Integer array representing objectId</param>
  		public Oid(int[] data)
  			:this()
  		{
  			Set(data);
  		}
  		
  		/// <summary>Constructor. Duplicate objectId value from argument.</summary>
  		/// <param name="second">objectId whose value is used to initilize this class value</param>
  		public Oid(Oid second)
  			:this()
  		{
  			Set(second);
  		}
  		
  		/// <summary>Constructor. Initialize objectId value from string argument.</summary>
  		/// <param name="value">String value representing objectId</param>
  		public Oid(System.String value)
  			: this()
  		{
  			Set(value);
  		}
  
  		#endregion Constructors
  
  		#region Set members
  
  		/// <summary>
  		/// Set Oid value from integer array. If integer array is null or length == 0, internal buffer is set to null.
  		/// </summary>
  		/// <param name="value">Integer array</param>
  		/// <exception cref="ArgumentNullException">Parameter is null</exception>
  		/// <exception cref="ArgumentOutOfRangeException">Parameter contains less then 2 integer values</exception>
  		/// <exception cref="OverflowException">Paramater contains a value that is less then zero. This is an invalid instance value</exception>
  		public virtual void Set(int[] value)
  		{
  			if (value == null)
  				_data = null;
  			else
  			{
  				// Verify all values are greater then or equal 0
  				foreach (int i in value)
  				{
  					if (i < 0)
  						throw new OverflowException("OID instance value cannot be less then zero.");
  				}
  				_data = new UInt32[value.Length];
  				for (int i = 0; i < value.Length; i++)
  				{
  					_data[i] = (UInt32)value[i];
  				}
  			}
  		}
  
  		/// <summary>
  		/// Set Oid value from integer array. If integer array is null or length == 0, internal buffer is set to null.
  		/// </summary>
  		/// <param name="value">Integer array</param>
  		/// <exception cref="ArgumentNullException">Parameter is null</exception>
  		/// <exception cref="ArgumentOutOfRangeException">Parameter contains less then 2 integer values</exception>
  		public virtual void Set(UInt32[] value)
  		{
  			if (value == null)
  				_data = null;
  			else
  			{
  				_data = new UInt32[value.Length];
  				Array.Copy(value, 0, _data, 0, value.Length);
  			}
  		}
  
  		/// <summary>
  		/// Set class value from another Oid class.
  		/// </summary>
  		/// <param name="value">Oid class</param>
  		/// <exception cref="ArgumentNullException">Thrown when parameter is null</exception>
  		public void Set(Oid value)
  		{
  			if (value == null)
  				throw new ArgumentNullException("value");
  			Set(value.GetData());
  		}
  
  		/// <summary> Sets the object to the passed dotted decimal 
  		/// object identifier string.
  		/// </summary>
  		/// <param name="value">The dotted decimal object identifier.
  		/// </param>
  		public void Set(System.String value)
  		{
  			if (value == null || value.Length == 0)
  			{
  				_data = null;
  			}
  			else
  			{
  				_data = Parse(value);
  			}
  		}
  
  		#endregion Set members
  
  		/// <summary> Gets the number of object identifiers
  		/// in the object.
  		/// </summary>
  		/// <returns> Returns the number of object identifiers
  		/// </returns>
  		virtual public int Length
  		{
  			get
  			{
  				if (_data == null)
  					return 0;
  				return _data.Length;
  			}
  
  		}
  		
  		/// <summary> Add an array of identifiers to the current object.</summary>
  		/// <param name="ids">The array Int32 identifiers to append to the object</param>
  		/// <exception cref="OverflowException">Thrown when one of the instance IDs to add are less then zero</exception>
  		public virtual void Add(int[] ids)
  		{
  			if (ids == null || ids.Length == 0)
  			{
  				return;
  			}
  			if (_data != null)
  			{
  				if (ids != null && ids.Length != 0)
  				{
  					UInt32[] tmp = new UInt32[_data.Length + ids.Length];
  					Array.Copy(_data, 0, tmp, 0, _data.Length);
  					for (int i = 0; i < ids.Length; i++)
  					{
  						if (ids[i] < 0)
  						{
  							throw new OverflowException("Instance value cannot be less then zero.");
  						}
  						tmp[_data.Length + i] = (UInt32)ids[i];
  					}
  					_data = tmp;
  				}
  			}
  			else
  			{
  				_data = new UInt32[ids.Length];
  				for (int i = 0; i < ids.Length; i++)
  				{
  					if (ids[i] < 0)
  					{
  						throw new OverflowException("Instance value cannot be less then zero.");
  					}
  					_data[i] = (UInt32)ids[i];
  				}
  			}
  		}
  
  		/// <summary> Add UInt32 identifiers to the current object.</summary>
  		/// <param name="ids">The array of identifiers to append</param>
  		/// <exception cref="OverflowException">Thrown when one of the instance IDs to add are less then zero</exception>
  		public virtual void Add(UInt32[] ids)
  		{
  			if (ids == null || ids.Length == 0)
  			{
  				return;
  			}
  			if (_data != null)
  			{
  				if (ids != null && ids.Length != 0)
  				{
  					UInt32[] tmp = new UInt32[_data.Length + ids.Length];
  					Array.Copy(_data, 0, tmp, 0, _data.Length);
  					Array.Copy(ids, 0, tmp, _data.Length, ids.Length);
  					_data = tmp;
  				}
  			}
  			else
  			{
  				_data = new UInt32[ids.Length];
  				Array.Copy(ids, _data, ids.Length);
  			}
  		}
  
  		/// <summary>Add a single UInt32 id to the end of the object</summary>
  		/// <param name="id">Id to add to the oid</param>
  		public virtual void Add(UInt32 id)
  		{
  			if (_data != null)
  			{
  				UInt32[] tmp = new UInt32[_data.Length + 1];
  				Array.Copy(_data, 0, tmp, 0, _data.Length);
  				tmp[_data.Length] = id;
  				_data = tmp;
  			}
  			else
  			{
  				_data = new UInt32[1];
  				_data[0] = id;
  			}
  		}
  
  		/// <summary>Add a single Int32 id to the end of the object</summary>
  		/// <param name="id">Id to add to the oid</param>
  		/// <exception cref="OverflowException">Thrown when id value is less then zero</exception>
  		public virtual void Add(int id)
  		{
  			if (id < 0)
  			{
  				throw new OverflowException("Instance id is less then zero.");
  			}
  			if (_data != null)
  			{
  				UInt32[] tmp = new UInt32[_data.Length + 1];
  				Array.Copy(_data, 0, tmp, 0, _data.Length);
  				tmp[_data.Length] = (UInt32)id;
  				_data = tmp;
  			}
  			else
  			{
  				_data = new UInt32[1];
  				_data[0] = (UInt32)id;
  			}
  		}
  
  		/// <summary> Converts the passed string to an object identifier
  		/// and appends them to the current object.
  		/// </summary>
  		/// <param name="strOids">The dotted decimal identifiers to Append
  		/// </param>
  		public virtual void Add(string strOids)
  		{
  			UInt32[] oids = Parse(strOids);
  			Add(oids);
  		}
  
  		/// <summary> Appends the passed Oid object to 
  		/// self.
  		/// </summary>
  		/// <param name="second">The object to Append to self
  		/// </param>
  		public virtual void Add(Oid second)
  		{
  			Add(second.GetData());
  		}
  		
  
  		#region Comparison methods
  
  		/// <summary>Compare Oid value with array of UInt32 integers</summary>
  		/// <param name="ids">Array of integers</param>
  		/// <returns>-1 if class is less then, 0 if the same or 1 if greater then the integer array value</returns>
  		public virtual int Compare(UInt32[] ids)
  		{
  			if (ids == null && _data == null)
  				return 0;
  			else if (ids != null && _data == null)
  				return 1;
  			else if (ids == null && _data != null)
  				return -1;
  			return Compare(ids, _data.Length > ids.Length ? ids.Length : _data.Length);
  		}
  
  		/// <summary>Compare class value with the contents of the array. Compare up to dist number of Oid values
  		/// to determine equality.</summary>
  		/// <param name="ids">Unsigned integer array to Compare with</param>
  		/// <param name="dist">Number of oid instance values to compare</param>
  		/// <returns>0 if equal, -1 if less then and 1 if greater then.</returns>
  		public virtual int Compare(UInt32[] ids, int dist)
  		{
  			if (_data == null)
  			{
  				if (ids == null)
  					return 0;
  				return -1;
  			}
  			if (ids == null)
  			{
  				return 1;
  			}
  			if (ids.Length < dist || _data.Length < dist)
  			{
  				if (_data.Length < ids.Length || _data.Length == ids.Length)
  				{
  					return -1;
  				}
  				return 1;
  			}
  			for (int cnt = 0; cnt < dist; cnt++)
  			{
  				if (_data[cnt] < ids[cnt])
  				{
  					return -1;
  				}
  				else if (_data[cnt] > ids[cnt])
  				{
  					return 1;
  				}
  			}
  			// If we made it all the way through, the Oids are the same
  			return 0;
  		}
  
  		/// <summary>
  		/// Exact comparison of two Oid values
  		/// </summary>
  		/// <param name="oid">Oid to compare against</param>
  		/// <returns>1 if class is greater then argument, -1 if class value is less then argument, 0 if the same</returns>
  		public int CompareExact(Oid oid)
  		{
  			return CompareExact(oid.GetData());
  		}
  		/// <summary>
  		/// Exact comparison of two Oid values
  		/// </summary>
  		/// <remarks>
  		/// This method is required for cases when exact comparison is required and not lexographical comparison.
  		/// 
  		/// This method will compare the lengths first and, if not the same, make a comparison determination based
  		/// on it before looking into the data.
  		/// </remarks>
  		/// <param name="ids">Array of unsigned integers to compare against</param>
  		/// <returns>1 if class is greater then argument, -1 if class value is less then argument, 0 if the same</returns>
  		public int CompareExact(UInt32[] ids)
  		{
  			int cmpVal = Compare(ids);
  			if (cmpVal == 0)
  			{
  				if (ids == null)
  				{
  					if (_data == null)
  						return 0;
  					return 1;
  				}
  				if (_data == null)
  					return -1;
  				if (_data.Length != ids.Length)
  				{
  					if (_data.Length > ids.Length)
  						return 1;
  					else if (_data.Length < ids.Length)
  						return -1;
  				}
  			}
  			return cmpVal;
  			/*
  			for (int i = 0; i < _data.Length; i++)
  			{
  				if (_data[i] != ids[i])
  				{
  					if (_data[i] > ids[i])
  						return 1;
  					else if (_data[i] < ids[i])
  						return -1;
  				}
  			}
  			return 0;
  			 */
  		}
  
  		/// <summary>Compare objectId values</summary>
  		/// <param name="cmp">ObjectId to Compare with</param>
  		/// <returns>0 if equal, -1 if less then and 1 if greater then.</returns>
  		public virtual int Compare(Oid cmp)
  		{
  			if (((Object)cmp) == null)
  				return 1;
  			if (cmp.GetData() == null && _data == null)
  				return 0;
  			else if (cmp.GetData() != null && _data == null)
  				return 1;
  			else if (cmp.GetData() == null && _data != null)
  				return -1;
  			return Compare(cmp.GetData());
  		}
  
  		/// <summary> Test for equality. Returns true if 'o' is an instance of an Oid and is equal to self.</summary>
  		/// <param name="obj">The object to be tested for equality.</param>
  		/// <returns> True if the object is an Oid and is equal to self. False otherwise.</returns>
  		public override bool Equals(System.Object obj)
  		{
  			if (obj == null)
  			{
  				return false;
  			}
  			if (obj is Oid)
  			{
  				return (CompareExact(((Oid)obj)._data) == 0);
  			}
  			else if (obj is System.String)
  			{
  				return (CompareExact(Parse((System.String)obj)) == 0);
  			}
  			else if (obj is UInt32[])
  			{
  				return (CompareExact((UInt32[])obj) == 0);
  			}
  			return false;
  		}
  
  		/// <summary>Compares the passed object identifier against self
  		/// to determine if self is the root of the passed object.
  		/// If the passed object is in the same root tree as self
  		/// then a true value is returned. Otherwise a false value
  		/// is returned from the object.
  		/// </summary>
  		/// <param name="leaf">The object to be tested
  		/// </param>
  		/// <returns> True if leaf is in the tree.
  		/// </returns>
  		public virtual bool IsRootOf(Oid leaf)
  		{
  			return (Compare(leaf._data, _data == null ? 0 : _data.Length) == 0);
  		}
  
  		/// <summary>
  		/// IComparable interface implementation. Internally uses <see cref="Oid.CompareExact(Oid)"/> method to perform comparisons.
  		/// </summary>
  		/// <param name="obj"></param>
  		/// <returns>1 if class is greater then argument, -1 if class value is less then argument, 0 if the same</returns>
  		public int CompareTo(object obj)
  		{
  			if (obj == null)
  				return 1;
  			if( obj is Oid )
  				return CompareExact((Oid)obj);
  			return 1;
  		}
  		#endregion Comparison methods
  
  		/// <summary>
  		/// Return internal integer array. This is required by static members of the class and other methods in
  		/// this library so internal attribute is applied to it.
  		/// </summary>
  		/// <returns>Internal unsigned integer array buffer.</returns>
  		protected UInt32[] GetData()
  		{
  			return _data;
  		}
  
  		/// <summary>
  		/// Reset class value to null
  		/// </summary>
  		public void Reset()
  		{
  			if (_data != null)
  			{
  				_data = null;
  			}
  		}
  
  		/// <summary>
  		/// Is Oid a null value or Oid equivalent (0.0)
  		/// </summary>
  		public bool IsNull
  		{
  			get
  			{
  				if (Length == 0)
  					return true;
  				if (Length == 2 && _data[0] == 0 && _data[1] == 0)
  					return true;
  				return false;
  			}
  		}
  
  		/// <summary>
  		/// Convert the Oid class to a integer array. Internal class data buffer is *copied* and not passed to the caller.
  		/// </summary>
  		/// <returns>Unsigned integer array representing the Oid class IDs</returns>
  		public UInt32[] ToArray()
  		{
  
gt: 			if (_data == null || _data.Length == 0)