Innovenergy_trunk/csharp/Lib/Protocols/DBus/Utils/HexView.cs

173 lines
4.8 KiB
C#

using System.Drawing;
using System.Text;
using static System.Drawing.Color;
namespace InnovEnergy.Lib.Protocols.DBus.Utils;
public static class HexView
{
public static String ToHexView2(this ArraySegment<Byte> segment, Boolean upToSegment = true, Int32 lineWith = 16)
{
var sbHex = new StringBuilder();
var sbAsc = new StringBuilder();
var sbLines = new StringBuilder();
var data = segment.Array!;
var end = upToSegment ? segment.Offset + segment.Count : data.Length;
for (var lineStart = 0; lineStart < end; lineStart += lineWith)
{
sbHex.Clear();
sbAsc.Clear();
for (var pos = lineStart; pos < lineStart + lineWith; pos++)
{
if (pos >= data.Length)
{
sbHex.Append("".PadRight((lineWith - (pos % lineWith)) * 3));
break;
}
var color = IsInsideSegment(pos) ? Red : Black;
var octet = data[pos];
sbHex.Append(octet.ToString("X2").Color(color));
sbHex.Append(" ");
sbAsc.Append(Printable(octet).Color(color));
}
sbLines.Append(lineStart.ToString().PadLeft(4) + ": ");
sbLines.Append(sbHex.ToString());
sbLines.Append(" ");
sbLines.AppendLine(sbAsc.ToString());
}
return sbLines.ToString();
Boolean IsInsideSegment(Int32 pos) => pos >= segment.Offset && pos < segment.Offset + segment.Count;
}
public static String ToHexView(this ArraySegment<Byte> data, Int32 lineWith = 16, params (ArraySegment<Byte> segment, Color color)[] colored)
{
var sbHex = new StringBuilder();
var sbAsc = new StringBuilder();
var sbLines = new StringBuilder();
for (var i = 0; i < data.Count; i += lineWith)
{
sbHex.Clear();
sbAsc.Clear();
for (var pos = i; pos < i + lineWith; pos++)
{
if (pos >= data.Count)
{
sbHex.Append("".PadRight((lineWith - (pos % lineWith)) * 3));
break;
}
var color = colored
.Where(c => Inside(pos, c.segment))
.Select(c => c.color)
.FirstOrDefault();
sbHex.Append(data[pos].ToString("X2").Color(color));
sbHex.Append(" ");
sbAsc.Append(Printable(data[pos]).Color(color));
}
sbLines.Append(i.ToString().PadLeft(4) + ": ");
sbLines.Append(sbHex.ToString());
sbLines.Append(" ");
sbLines.AppendLine(sbAsc.ToString());
}
return sbLines.ToString();
Boolean Inside(Int32 pos, ArraySegment<Byte> segment)
{
pos += data.Offset ;
return pos >= segment.Offset && pos < segment.Offset + segment.Count;
}
}
public static String ToHexView(this IEnumerable<Byte> data, Int32 lineWith = 16)
{
var sbHex = new StringBuilder();
var sbAsc = new StringBuilder();
var sbLine = new StringBuilder();
using var e = data.GetEnumerator();
var more = true;
var address = 0;
do
{
var l = lineWith;
while (l-- > 0)
{
more = e.MoveNext();
if (!more)
break;
sbHex.Append(e.Current.ToString("X2") + " ");
sbAsc.Append(Printable(e.Current));
}
sbLine.Append(address.ToString().PadLeft(4) + ": ");
sbLine.Append(sbHex.ToString().PadRight(lineWith * 3 + 2));
sbLine.AppendLine(sbAsc.ToString());
sbHex.Clear();
sbAsc.Clear();
address += lineWith;
}
while (more);
return sbLine.ToString();
}
private static String Printable(Byte b)
{
var ch = (Char) b;
if (Char.IsLetterOrDigit(ch) || Char.IsPunctuation(ch) || Char.IsSymbol(ch) || ch == ' ')
return ch.ToString();
return ".";
}
private static String Color(this String txt, Color fg = default, Color bg = default)
{
const String startFg = "\u001b[38;2;";
const String startBg = "\u001b[48;2;";
const String end = "\u001b[0m";
if (fg == default && bg == default)
return txt;
var sb = new StringBuilder();
if (fg != default)
{
sb.Append(startFg);
sb.Append($"{fg.R};{fg.G};{fg.B}m");
}
if (bg != default)
{
sb.Append(startBg);
sb.Append($"{fg.R};{fg.G};{fg.B}m");
}
sb.Append(txt);
sb.Append(end);
return sb.ToString();
}
}