laatzen/Common/modbus_master_csharp/Base/NumberConvert.cs

603 lines
20 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace XYLEM.Base
{
public static class NumberConvert
{
public static readonly string ColumnSeperatorCSV = ((2.3).ToString().Contains(".") ? "," : ";");
private static readonly int base10 = 10;
private static readonly char[] cHexa = new char[] { 'A', 'B', 'C', 'D', 'E', 'F' };
private static readonly int[] iHexaNumeric = new int[] { 10, 11, 12, 13, 14, 15 };
private static readonly int[] iHexaIndices = new int[] { 0, 1, 2, 3, 4, 5 };
private static readonly int asciiDiff = 48;
public static string PadLeft(this String text, int minLength)
{
int iCount = minLength - text.Length;
String textRet = "";
if (iCount > 0)
{
textRet = new String('0', iCount);
}
return textRet + text;
}
/// <summary>
/// Tag for values input is done as "decimal" and is placed ex. in front or behinde the value that needs to be converted
/// </summary>
public static readonly string ValueInputAsDecimalTag = "decimal";
/// <summary>
/// Tag for values input is done as "binary" and is placed ex. in front or behinde the value that needs to be converted
/// </summary>
public static readonly string ValueInputAsBinaryTag = "binary";
/// <summary>
/// Tag for values input is done as "octal" and is placed ex. in front or behinde the value that needs to be converted
/// </summary>
public static readonly string ValueInputAsOctalEndTag = "octal";
/// <summary>
/// Tag for values input is done as "0o" and is placed ex. in front the value that needs to be converted
/// </summary>
public static readonly string ValueInputAsOctalFrontTag = "0o";
/// <summary>
/// Tag for values input is done as "hex" and is placed ex. in front or behinde the value that needs to be converted
/// </summary>
public static readonly string ValueInputAsHexEndTag = "hex";
/// <summary>
/// Tag for values input is done as "0x" and is placed ex. in front the value that needs to be converted
/// </summary>
public static readonly string ValueInputAsHexFrontTag = "0x";
/// <summary>
/// Tag for values input is done as "bin" and is placed ex. in front or behinde the value that needs to be converted
/// </summary>
public static readonly string ValueInputAsBinaryEndTag = "bin";
/// <summary>
/// Tag for values input is done as "0b" and is placed ex. in front the value that needs to be converted
/// </summary>
public static readonly string ValueInputAsBinaryFrontTag = "0b";
/// <summary>
/// Convert byte values as in a string byte array
/// </summary>
/// <param name="byteValues"> must be like "0x12, 0x12, 0x12" or "1010bin; 1010bin; 1010bin" or "decimal 123, 123, 123"</param>
/// <returns></returns>
public static byte[] ValuesToBytes(this string byteValues)
{
try
{
List<byte> ret = new List<byte>();
var isHexadecimal = false;
var isDecimal = false;
var isBinary = false;
byteValues = byteValues.Trim().ToLower();
bool isBinaryMatch = (new Regex(@"^[01 ]+$")).IsMatch(byteValues);
bool isHexMatch = (new Regex(@"^[0-9a-f ]+$")).IsMatch(byteValues);
if (!string.IsNullOrEmpty(byteValues) && (byteValues.Contains(ValueInputAsHexEndTag) || byteValues.Contains("0x") || (isHexMatch && !isBinaryMatch)))
{
byteValues = byteValues.ToLower().Replace(ValueInputAsHexEndTag, "");
isHexadecimal = true;
}
else if (!string.IsNullOrEmpty(byteValues) && (byteValues.Contains(ValueInputAsDecimalTag) || isBinaryMatch))
{
byteValues = byteValues.Replace(ValueInputAsDecimalTag, "");
isDecimal = true;
}
else if (!string.IsNullOrEmpty(byteValues) && byteValues.Contains(ValueInputAsBinaryTag))
{
byteValues = byteValues.Replace(ValueInputAsBinaryTag, "");
isBinary = true;
}
var chunks = byteValues.Trim(new char[] { ' ' }).Split(new string[] { ",", ";", " ", Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
foreach (var value in chunks)
{
var toConvert = value.Trim();
if (!string.IsNullOrEmpty(toConvert))
{
if (isHexadecimal || !isBinary && !isDecimal && (toConvert.StartsWith(ValueInputAsHexFrontTag) || toConvert.ToLower().Contains(ValueInputAsHexEndTag)))
{
ret.Add(Convert.ToByte(toConvert.Replace(ValueInputAsHexFrontTag, "").ToLower().Replace(ValueInputAsHexEndTag, ""), 16));
}
else if (isBinary || !isDecimal && (toConvert.StartsWith(ValueInputAsBinaryFrontTag) || toConvert.ToLower().Contains(ValueInputAsBinaryEndTag)))
{
ret.Add(Convert.ToByte(toConvert.Replace(ValueInputAsBinaryFrontTag, "").ToLower().Replace(ValueInputAsBinaryEndTag, ""), 2));
}
else
{
ret.Add(Convert.ToByte(toConvert, 10));
}
}
}
return ret.ToArray();
}
catch
{
return null; // Error
}
}
public static string UnsignedHexToDecimal(this string Hex)
{
try
{
return Convert.ToUInt64(Hex, 16).ToString();
}
catch
{
return "?";
}
}
public static string UnsignedDecimalToHex(this string iDec, int padLeft, bool Add_0x)
{
try
{
return UnsignedDecimalToHex(Convert.ToUInt64(iDec), padLeft, Add_0x);
}
catch
{
return "?";
}
}
public static string UnsignedDecimalToHex(this UInt32 iDec, int padLeft, bool Add_0x)
{
try
{
return ((Add_0x) ? ValueInputAsHexFrontTag : "") + String.Format("{0:X}", iDec).PadLeft(padLeft, '0');
}
catch
{
return "?";
}
}
public static string DecimalToHex(this Int32 iDec, int padLeft, bool Add_0x)
{
try
{
return ((Add_0x) ? ValueInputAsHexFrontTag : "") + String.Format("{0:X}", iDec).PadLeft(padLeft, '0');
}
catch
{
return "?";
}
}
public static string UnsignedDecimalToHex(this UInt64 iDec, int padLeft, bool Add_0x)
{
try
{
return ((Add_0x) ? ValueInputAsHexFrontTag : "") + String.Format("{0:X}", iDec).PadLeft(padLeft, '0');
}
catch
{
return "?";
}
}
public static string DecimalToHex(this Int64 iDec, int padLeft, bool Add_0x)
{
try
{
return ((Add_0x) ? ValueInputAsHexFrontTag : "") + String.Format("{0:X}", iDec).PadLeft(padLeft, '0');
}
catch
{
return "?";
}
}
public static string UnsignedDecimalToBin(this string dec, bool Add_0b)
{
try
{
return ((Add_0b) ? ValueInputAsBinaryFrontTag : "") + UnsignedDecimalToBase(Convert.ToUInt64(dec), 2);
}
catch
{
return "?";
}
}
static string DoAutoPadLeft(this string valueAsStr)
{
var numberToPad = (valueAsStr.Length <= 8) ? 8 : (valueAsStr.Length <= 16) ? 16 : (valueAsStr.Length <= 32) ? 32 : 64;
return valueAsStr.PadLeft(numberToPad, '0');
}
static string DoAutoSpcaePadEvery4Char(this string ValueAsStr)
{
if (String.IsNullOrEmpty(ValueAsStr))
{
return ValueAsStr;
}
else
{
ValueAsStr = ValueAsStr.Trim();
var MissingChar = ValueAsStr.Length % 4;
ValueAsStr = ValueAsStr.PadLeft(ValueAsStr.Length + 4 - MissingChar, '0');
return Regex.Replace(ValueAsStr.Trim(), @"(.{4})", "$1 ").Trim();
}
}
public static string ToUnsignedBin(this int value, bool Add_0b)
{
try
{
return ((Add_0b) ? ValueInputAsBinaryFrontTag : "") + UnsignedDecimalToBase((UInt32)value, 2).DoAutoPadLeft();
}
catch
{
return "?";
}
}
public static string ToUnsignedBin(this uint value, bool Add_0b)
{
try
{
return ((Add_0b) ? ValueInputAsBinaryFrontTag : "") + UnsignedDecimalToBase(value, 2).DoAutoPadLeft();
}
catch
{
return "?";
}
}
public static string ToUnsignedBin(this Int64 value)
{
try
{
return UnsignedDecimalToBase((UInt32)value, 2).DoAutoPadLeft();
}
catch
{
return "?";
}
}
/// <summary>
/// To string like 0bxxxxxxx depending of selection
/// </summary>
/// <param name="value">what value to show</param>
/// <param name="Add_0b">add 0b in front to indicate it is binary</param>
/// <param name="DoAutoPadLeft">"true" if pad left front with all 0 for the actual value type else "false" only pad with up to 4 bits 0 to easy read</param>
/// <returns></returns>
public static string ToUnsignedBin(this UInt64 value, bool Add_0b, bool DoAutoPadLeft = true)
{
try
{
var ret = UnsignedDecimalToBase(value, 2);
if (ret.Length == 0)
{
ret += "0"; // Always show 0 if no 1 is set
}
if (DoAutoPadLeft)
{
ret = ret.DoAutoPadLeft();
}
else
{
ret = ret.DoAutoSpcaePadEvery4Char();
}
return ((Add_0b) ? ValueInputAsBinaryFrontTag : "") + ret;
}
catch
{
return "?";
}
}
public static string ToBin(this byte value, bool Add_0b)
{
try
{
return ((Add_0b) ? ValueInputAsBinaryFrontTag : "") + UnsignedDecimalToBase(value, 2).DoAutoPadLeft();
}
catch
{
return "?";
}
}
public static string ToDec(this byte value)
{
return value.ToString("D3");
}
public static string ToHex(this byte value, bool Add_0x)
{
return DecimalToHex(value, 2, Add_0x);
}
public static string ToHex(this byte[] values, bool Add_0x, bool seperatorForCSV)
{
if (values == null) { return "Array is empty!"; }
string ret = "";
foreach (var value in values)
{
ret += (!String.IsNullOrEmpty(ret) ? (seperatorForCSV ? ColumnSeperatorCSV + " " : ", ") : "") + value.ToHex(Add_0x);
}
return ret;
}
public static string ToDec(this byte[] values)
{
if (values == null) { return "Array is empty!"; }
string ret = "";
foreach (var value in values)
{
ret += (!String.IsNullOrEmpty(ret) ? ", " : "") + value.ToDec();
}
return ret;
}
public static string ToBin(this byte[] values, bool Add_0b)
{
if (values == null) { return "Array is empty!"; }
string ret = "";
foreach (var value in values)
{
ret += (!String.IsNullOrEmpty(ret) ? ", " : "") + value.ToBin(Add_0b);
}
return ret;
}
public static string ToHex(this Int16 value, bool Add_0x)
{
return DecimalToHex(value, 4, Add_0x);
}
public static string ToHex(this UInt16 value, bool Add_0x)
{
return UnsignedDecimalToHex(value, 4, Add_0x);
}
public static string ToHex(this Int32 value, bool Add_0x)
{
return DecimalToHex(value, 8, Add_0x);
}
public static string ToHex(this UInt32 value, bool Add_0x)
{
return UnsignedDecimalToHex(value, 8, Add_0x);
}
public static string ToHex(this Int64 value, bool Add_0x)
{
return DecimalToHex(value, 16, Add_0x);
}
public static string ToHex(this UInt64 value, bool Add_0x)
{
return UnsignedDecimalToHex(value, 16, Add_0x);
}
public static string UnsignedDecimalToBase(this string iDec, int numbase)
{
try
{
return UnsignedDecimalToBase(Convert.ToUInt64(iDec), numbase);
}
catch
{
return "?";
}
}
public static string UnsignedDecimalToBase(this UInt64 iDec, int numbase)
{
try
{
String strBin = "";
int[] result = new int[64];
int MaxBit = 64;
for (; iDec > 0; iDec /= (UInt64)numbase)
{
int rem = (int)(iDec % Convert.ToUInt64(numbase));
result[--MaxBit] = rem;
}
for (int i = 0; i < result.Length; i++)
{
if ((int)result.GetValue(i) >= base10)
{
strBin += cHexa[(int)result.GetValue(i) % base10];
}
else
{
strBin += result.GetValue(i);
}
}
strBin = strBin.TrimStart(new char[] { '0' });
return strBin;
}
catch
{
return "?";
}
}
/// <summary>
/// Converter string to a value (0x or 0b is not legal)
/// </summary>
/// <param name="sBase"></param>
/// <param name="numbase"></param>
/// <returns></returns>
public static UInt64 UnsignedBaseToDecimal(this String sBase, int numbase)
{
UInt64 result = 0;
UInt64 b;
UInt64 iProduct = 1;
String sHexa = "";
if (numbase > base10)
{
for (int i = 0; i < cHexa.Length; i++)
{
sHexa += cHexa.GetValue(i).ToString();
}
}
for (int i = sBase.Length - 1; i >= 0; i--, iProduct *= (UInt64)numbase)
{
String sValue = sBase[i].ToString();
if (sValue.IndexOfAny(cHexa) >= 0)
{
b = (UInt64)iHexaNumeric[sHexa.IndexOf(sBase[i])];
}
else
{
b = (UInt64)sBase[i] - (UInt64)asciiDiff;
}
result += (b * iProduct);
}
return result;
}
/// <summary>
/// Converter string to a value use 0x or 0b
/// </summary>
/// <param name="sBase"></param>
/// <param name="numbase"></param>
/// <returns></returns>
public static UInt64 ToUInt64(this String sBase)
{
UInt64 result = 0;
UInt64 b;
UInt64 iProduct = 1;
String sHexa = "";
int numbase;
sBase = sBase.Trim().ToLower();
if (sBase.StartsWith(ValueInputAsOctalFrontTag))
{
numbase = 8;
sBase = sBase.Replace(ValueInputAsOctalFrontTag, "");
}
else if (sBase.StartsWith(ValueInputAsHexFrontTag))
{
numbase = 16;
sBase = sBase.Replace(ValueInputAsHexFrontTag, "");
}
else if (sBase.StartsWith(ValueInputAsBinaryFrontTag))
{
numbase = 2;
sBase = sBase.Replace(ValueInputAsBinaryFrontTag, "");
}
else
{
return Convert.ToUInt64(sBase);
}
if (numbase > base10)
{
for (int i = 0; i < cHexa.Length; i++)
{
sHexa += cHexa.GetValue(i).ToString();
}
}
for (int i = sBase.Length - 1; i >= 0; i--, iProduct *= (UInt64)numbase)
{
String sValue = sBase[i].ToString();
if (sValue.IndexOfAny(cHexa) >= 0)
{
b = (UInt64)iHexaNumeric[sHexa.IndexOf(sBase[i])];
}
else
{
b = (UInt64)sBase[i] - (UInt64)asciiDiff;
}
result += (b * iProduct);
}
return result;
}
/// <summary>
/// Converter string to a value use 0x or 0b
/// </summary>
/// <param name="sBase"></param>
/// <param name="numbase"></param>
/// <returns></returns>
public static Int64 ToInt64(this String sBase)
{
Int64 result = 0;
Int64 b;
Int64 iProduct = 1;
String sHexa = "";
int numbase;
bool isNegative = false;
sBase = sBase.Trim().ToLower();
if (sBase.StartsWith("-"))
{
sBase = sBase.TrimStart('-');
isNegative = true;
}
else if (sBase.StartsWith("+"))
{
sBase = sBase.TrimStart('+');
}
if (sBase.StartsWith(ValueInputAsOctalFrontTag))
{
numbase = 8;
sBase = sBase.Replace(ValueInputAsOctalFrontTag, "");
}
else if (sBase.StartsWith(ValueInputAsHexFrontTag))
{
numbase = 16;
sBase = sBase.Replace(ValueInputAsHexFrontTag, "");
}
else if (sBase.StartsWith(ValueInputAsBinaryFrontTag))
{
numbase = 2;
sBase = sBase.Replace(ValueInputAsBinaryFrontTag, "");
}
else
{
return isNegative ? -Convert.ToInt64(sBase) : Convert.ToInt64(sBase);
}
if (numbase > base10)
{
for (int i = 0; i < cHexa.Length; i++)
{
sHexa += cHexa.GetValue(i).ToString();
}
}
for (int i = sBase.Length - 1; i >= 0; i--, iProduct *= (Int64)numbase)
{
String sValue = sBase[i].ToString();
if (sValue.IndexOfAny(cHexa) >= 0)
{
b = (Int64)iHexaNumeric[sHexa.IndexOf(sBase[i])];
}
else
{
b = (Int64)sBase[i] - (Int64)asciiDiff;
}
result += (b * iProduct);
}
return isNegative ? -result : result;
}
public static UInt16 SwapByte(this UInt16 value)
{
return (UInt16)(value >> 8 | (value & 0xFF) << 8);
}
public static UInt64 SwapWord(this UInt64 value)
{
return (UInt64)(value >> 16 | (value & 0xFFFF) << 16);
}
}
}