// Byte related function helper.
// 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.
/*
* Created by SharpDevelop.
* User: lextm
* Date: 2008/5/1
* Time: 12:31
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
*/
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
namespace GSF.Net.Snmp
{
///
/// Helper utility that performs data conversions from/to bytes.
///
public static class ByteTool
{
///
/// Converts decimal string to bytes.
///
/// The decimal string.
/// The converted bytes.
/// " 16 18 " is converted to new byte[] { 0x10, 0x12 }.
public static byte[] ConvertDecimal(string description)
{
if (description == null)
{
throw new ArgumentNullException(nameof(description));
}
List result = new List();
string[] content = description.Trim().Split(new[] { ' ' });
foreach (string part in content)
{
byte temp;
if (byte.TryParse(part, out temp))
{
result.Add(temp);
}
}
return result.ToArray();
}
///
/// Converts the byte string to bytes.
///
/// The HEX string.
/// The converted bytes.
/// "80 00" is converted to new byte[] { 0x80, 0x00 }.
public static byte[] Convert(IEnumerable description)
{
if (description == null)
{
throw new ArgumentNullException(nameof(description));
}
List result = new List();
StringBuilder buffer = new StringBuilder(2);
foreach (char c in description.Where(c => !char.IsWhiteSpace(c)))
{
if (!char.IsLetterOrDigit(c))
{
throw new ArgumentException("Illegal character found.", nameof(description));
}
buffer.Append(c);
if (buffer.Length != 2)
{
continue;
}
byte temp;
if (byte.TryParse(buffer.ToString(), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out temp))
{
result.Add(temp);
}
buffer.Length = 0;
}
if (buffer.Length != 0)
{
throw new ArgumentException("Not a complete byte string.", nameof(description));
}
return result.ToArray();
}
///
/// Converts bytes to a byte string.
///
/// The bytes.
/// The formatted string.
/// new byte[] { 0x80, 0x00 } is converted to "80 00".
public static string Convert(byte[] buffer)
{
if (buffer == null)
{
throw new ArgumentNullException(nameof(buffer));
}
return BitConverter.ToString(buffer).Replace('-', ' ');
}
internal static byte[] ParseItems(params ISnmpData[] items)
{
if (items == null)
{
throw new ArgumentNullException(nameof(items));
}
using (MemoryStream result = new MemoryStream())
{
foreach (ISnmpData item in items)
{
if (item == null)
{
throw new ArgumentException("Item in the collection cannot be null.", nameof(items));
}
item.AppendBytesTo(result);
}
return result.ToArray();
}
}
internal static byte[] ParseItems(IEnumerable items)
{
if (items == null)
{
throw new ArgumentNullException(nameof(items));
}
using (MemoryStream result = new MemoryStream())
{
foreach (ISnmpData item in items)
{
item.AppendBytesTo(result);
}
return result.ToArray();
}
}
internal static byte[] GetRawBytes(IEnumerable orig, bool negative)
{
if (orig == null)
{
throw new ArgumentNullException(nameof(orig));
}
byte flag;
byte sign;
if (negative)
{
flag = 0xff;
sign = 0x80;
}
else
{
flag = 0x0;
sign = 0x0;
}
List list = new List(orig);
while (list.Count > 1)
{
if (list[list.Count - 1] == flag)
{
list.RemoveAt(list.Count - 1);
}
else
{
break;
}
}
// if sign bit is not correct, add an extra byte
if ((list[list.Count - 1] & 0x80) != sign)
{
list.Add(flag);
}
list.Reverse();
return list.ToArray();
}
///
/// Packs parts into a single message body.
///
/// Message length.
/// Message version.
/// Header.
/// Security parameters.
/// Scope data.
/// The object that represents the message body.
public static Sequence PackMessage(byte[] length, VersionCode version, ISegment header, ISegment parameters, ISnmpData data)
{
if (header == null)
{
throw new ArgumentNullException(nameof(header));
}
if (parameters == null)
{
throw new ArgumentNullException(nameof(parameters));
}
if (data == null)
{
throw new ArgumentNullException(nameof(data));
}
ISnmpData[] items = new[]
{
new Integer32((int)version),
header.GetData(version),
parameters.GetData(version),
data
};
return new Sequence(length, items);
}
internal static byte[] WritePayloadLength(this int length) // excluding initial octet
{
if (length < 0)
{
throw new ArgumentException("length cannot be negative.", nameof(length));
}
MemoryStream stream = new MemoryStream();
if (length < 127)
{
stream.WriteByte((byte)length);
return stream.ToArray();
}
byte[] c = new byte[16];
int j = 0;
while (length > 0)
{
c[j++] = (byte)(length & 0xff);
length = length >> 8;
}
stream.WriteByte((byte)(0x80 | j));
while (j > 0)
{
int x = c[--j];
stream.WriteByte((byte)x);
}
return stream.ToArray();
}
}
}