using System;
using System.Text;
namespace DTS.Common.Utilities
{
///
/// Summary description for HexEncoding.
///
/// This class has only static methods and appears to never be instantiated,
/// so I'm marking it static as well
/// there are built in classes for encoding and converting hex as well, but the behavior
/// here may deviate slightly
///
public static class HexEncoding
{
///
/// returns the number of bytes needed to represent hex string
///
/// hex string to calculate
/// number of bytes
/// doesn't count non hex characters
/// odd number of characters, last character is discarded
///
public static int GetByteCount(string hexString)
{
var numHexChars = 0;
char c;
// remove all none A-F, 0-9, characters
for (var i = 0; i < hexString.Length; i++)
{
c = hexString[i];
if (IsHexDigit(c))
numHexChars++;
}
// if odd number of characters, discard last character
if (numHexChars % 2 != 0)
{
numHexChars--;
}
return numHexChars / 2; // 2 characters per byte
}
///
/// Creates a byte array from the hexadecimal string. Each two characters are combined
/// to create one byte. First two hexadecimal characters become first byte in returned array.
/// Non-hexadecimal characters are ignored.
///
/// string to convert to byte array
/// number of characters in string ignored
/// byte array, in the same left-to-right order as the hexString
public static byte[] GetBytes(string hexString, out int discarded)
{
discarded = 0;
var newString = "";
char c;
// remove all none A-F, 0-9, characters
for (var i = 0; i < hexString.Length; i++)
{
c = hexString[i];
if (IsHexDigit(c))
newString += c;
else
discarded++;
}
// if odd number of characters, discard last character
if (newString.Length % 2 != 0)
{
discarded++;
newString = newString.Substring(0, newString.Length - 1);
}
var byteLength = newString.Length / 2;
var bytes = new byte[byteLength];
string hex;
var j = 0;
for (var i = 0; i < bytes.Length; i++)
{
hex = new String(new Char[] { newString[j], newString[j + 1] });
bytes[i] = HexToByte(hex);
j = j + 2;
}
return bytes;
}
///
/// returns a string representation out of byte array
///
/// an array of hex characters packed 2 per byte
/// string representation of hex characters in byte array, no spaces between bytes
public static string ToString(byte[] bytes)
{
var hexString = "";
for (var i = 0; i < bytes.Length; i++)
{
hexString += bytes[i].ToString("X2");
}
return hexString;
}
///
/// Determines if given string is in proper hexadecimal string format
///
/// string representing sequence of hex digits, no spaces
/// true if all characters are hex digits, false otherwise
public static bool InHexFormat(string hexString)
{
var hexFormat = true;
foreach (var digit in hexString)
{
if (!IsHexDigit(digit))
{
hexFormat = false;
break;
}
}
return hexFormat;
}
///
/// Returns true is c is a hexadecimal digit (A-F, a-f, 0-9)
///
/// Character to test
/// true if hex digit, false if not
public static bool IsHexDigit(char c)
{
int numChar;
var numA = Convert.ToInt32('A');
var num1 = Convert.ToInt32('0');
c = char.ToUpper(c);
numChar = Convert.ToInt32(c);
if (numChar >= numA && numChar < (numA + 6))
return true;
if (numChar >= num1 && numChar < (num1 + 10))
return true;
return false;
}
///
/// Converts 1 or 2 character string into equivalant byte value
///
/// 1 or 2 character string
/// byte
private static byte HexToByte(string hex)
{
if (hex.Length > 2 || hex.Length <= 0)
throw new ArgumentException("hex must be 1 or 2 characters in length");
var newByte = byte.Parse(hex, System.Globalization.NumberStyles.HexNumber);
return newByte;
}
public static string HexAsciiConvert(string hex)
{
var sb = new StringBuilder();
for (var i = 0; i < hex.Length; i += 2)
{
var hs = hex.Substring(i, 2);
var converted = Convert.ToUInt32(hs, 16);
if (converted == 0)
{
break;
}
sb.Append(Convert.ToChar(converted));
}
return sb.ToString();
}
}
}