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; } /// /// Tag for values input is done as "decimal" and is placed ex. in front or behinde the value that needs to be converted /// public static readonly string ValueInputAsDecimalTag = "decimal"; /// /// Tag for values input is done as "binary" and is placed ex. in front or behinde the value that needs to be converted /// public static readonly string ValueInputAsBinaryTag = "binary"; /// /// Tag for values input is done as "octal" and is placed ex. in front or behinde the value that needs to be converted /// public static readonly string ValueInputAsOctalEndTag = "octal"; /// /// Tag for values input is done as "0o" and is placed ex. in front the value that needs to be converted /// public static readonly string ValueInputAsOctalFrontTag = "0o"; /// /// Tag for values input is done as "hex" and is placed ex. in front or behinde the value that needs to be converted /// public static readonly string ValueInputAsHexEndTag = "hex"; /// /// Tag for values input is done as "0x" and is placed ex. in front the value that needs to be converted /// public static readonly string ValueInputAsHexFrontTag = "0x"; /// /// Tag for values input is done as "bin" and is placed ex. in front or behinde the value that needs to be converted /// public static readonly string ValueInputAsBinaryEndTag = "bin"; /// /// Tag for values input is done as "0b" and is placed ex. in front the value that needs to be converted /// public static readonly string ValueInputAsBinaryFrontTag = "0b"; /// /// Convert byte values as in a string byte array /// /// must be like "0x12, 0x12, 0x12" or "1010bin; 1010bin; 1010bin" or "decimal 123, 123, 123" /// public static byte[] ValuesToBytes(this string byteValues) { try { List ret = new List(); 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 "?"; } } /// /// To string like 0bxxxxxxx depending of selection /// /// what value to show /// add 0b in front to indicate it is binary /// "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 /// 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 "?"; } } /// /// Converter string to a value (0x or 0b is not legal) /// /// /// /// 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; } /// /// Converter string to a value use 0x or 0b /// /// /// /// 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; } /// /// Converter string to a value use 0x or 0b /// /// /// /// 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); } } }