// SNMP INTEGER type.
// Copyright (C) 2008-2010 Malcolm Crowe, Lex Li, and other contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Globalization;
using System.IO;
// ASN.1 BER encoding library by Malcolm Crowe at the University of the West of Scotland
// See http://cis.paisley.ac.uk/crow-ci0
// This is version 0 of the library, please advise me about any bugs
// mailto:malcolm.crowe@paisley.ac.uk
// Restrictions: It is assumed that no encoding has index length greater than 2^31-1.
// UNIVERSAL TYPES
// Some of the more unusual Universal encodings are supported but not fully implemented
// Should you require these types, as an alternative to changing this code
// you can catch the exception that is thrown and examine the contents yourself.
// APPLICATION TYPES
// If you want to handle Application types systematically, you can derive index class from
// Universal, and provide the Creator and Creators methods for your class
// You will see an example of how to do this in the Snmplib
// CONTEXT AND PRIVATE TYPES
// Ad hoc coding can be used for these, as an alterative to derive index class as above.
namespace GSF.Net.Snmp
{
///
/// Integer32 type in SMIv2 (or INTEGER in SMIv1).
///
public sealed class Integer32 // This namespace has its own concept of Integer
: ISnmpData, IEquatable
{
private readonly int _int;
private readonly byte[] _length;
///
/// Zero.
///
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
public static readonly Integer32 Zero = new Integer32(0);
private byte[] _raw;
///
/// Creates an instance.
///
/// Raw bytes
internal Integer32(byte[] raw) : this(new Tuple(raw.Length, raw.Length.WritePayloadLength()), new MemoryStream(raw))
{
// IMPORTANT: for test project only.
}
///
/// Creates an instance with a specific .
///
/// Value
public Integer32(int value)
{
_int = value;
}
///
/// Initializes a new instance of the class.
///
/// The length.
/// The stream.
public Integer32(Tuple length, Stream stream)
{
if (length == null)
{
throw new ArgumentNullException(nameof(length));
}
if (stream == null)
{
throw new ArgumentNullException(nameof(stream));
}
if (length.Item1 <= 0)
{
throw new ArgumentException("Byte length cannot be 0.", nameof(length));
}
if (length.Item1 > 4)
{
throw new ArgumentException("Truncation error for 32-bit integer coding.", nameof(length));
}
_raw = new byte[length.Item1];
stream.Read(_raw, 0, length.Item1);
_int = ((_raw[0] & 0x80) == 0x80) ? -1 : 0; // sign extended! Guy McIlroy
for (int j = 0; j < length.Item1; j++)
{
_int = (_int << 8) | _raw[j];
}
_length = length.Item2;
}
///
/// Returns an that represents this .
///
///
public int ToInt32()
{
return _int;
}
///
/// Converts to .
///
///
public ErrorCode ToErrorCode()
{
if (_int > 19 || _int < 0)
{
throw new InvalidCastException();
}
return (ErrorCode)_int;
}
///
/// Returns a that represents this .
///
///
public override string ToString()
{
return _int.ToString(CultureInfo.InvariantCulture);
}
///
/// Type code.
///
public SnmpType TypeCode
{
get
{
return SnmpType.Integer32;
}
}
///
/// Appends the bytes to .
///
/// The stream.
public void AppendBytesTo(Stream stream)
{
if (stream == null)
{
throw new ArgumentNullException(nameof(stream));
}
stream.AppendBytes(TypeCode, _length, _raw ?? (_raw = ByteTool.GetRawBytes(BitConverter.GetBytes(_int), _int < 0)));
}
///
/// Serves as a hash function for a particular type.
///
/// A hash code for the current .
public override int GetHashCode()
{
return ToInt32().GetHashCode();
}
///
/// Determines whether the specified is equal to the current .
///
/// The to compare with the current .
/// true if the specified is equal to the current ; otherwise, false.
///
public override bool Equals(object obj)
{
return Equals(this, obj as Integer32);
}
///
/// Indicates whether the current object is equal to another object of the same type.
///
/// An object to compare with this object.
/// true if the current object is equal to the parameter; otherwise, false.
///
public bool Equals(Integer32 other)
{
return Equals(this, other);
}
///
/// The equality operator.
///
/// Left object
/// Right object
///
/// Returns true if the values of its operands are equal, false otherwise.
public static bool operator ==(Integer32 left, Integer32 right)
{
return Equals(left, right);
}
///
/// The inequality operator.
///
/// Left object
/// Right object
///
/// Returns true if the values of its operands are not equal, false otherwise.
public static bool operator !=(Integer32 left, Integer32 right)
{
return !(left == right);
}
///
/// The comparison.
///
/// Left object
/// Right object
///
/// Returns true if the values of its operands are not equal, false otherwise.
private static bool Equals(Integer32 left, Integer32 right)
{
object lo = left;
object ro = right;
if (lo == ro)
{
return true;
}
if (lo == null || ro == null)
{
return false;
}
return left.ToInt32() == right.ToInt32();
}
}
// all references here are to ITU-X.690-12/97
}