laatzen/Common/modbus_master_csharp/Base/ByteArrayExtensionClass.cs

315 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace XYLEM.Base
{
internal static class ByteArrayExtensionClass
{
/// <summary>
/// Compare if values in to array's is equal
/// </summary>
/// <param name="array 1"></param>
/// <param name="array 2"></param>
/// <returns></returns>
public static bool Compare(this byte[] b1, byte[] b2)
{
// Validate buffers are the same length.
// This also ensures that the count does not exceed the length of either buffer.
return b1.SequenceEqual<byte>(b2);
}
/// <summary>
/// Copy a chunk of bytes from start index to a specific LongLength
/// </summary>
/// <param name="from"></param>
/// <param name="startIndex">start offset 0..x</param>
/// <param name="LongLength">LongLength of returned byte data array</param>
/// <returns>Return copy of byte data</returns>
public static byte[] Copy(this byte[] from, long startIndex, long LongLength)
{
try
{
byte[] bArray = new byte[LongLength];
Array.Copy(from, startIndex, bArray, 0, LongLength);
return bArray;
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(ByteArrayExtensionClass).ToString(), "Copy()"));
}
}
/// <summary>
/// Copy a chunk of bytes to the end of array, starting from start offset
/// </summary>
/// <param name="from"></param>
/// <param name="startIndex">start offset 0..x</param>
/// <returns>Return copy of byte data</returns>
public static byte[] Copy(this byte[] from, long startIndex)
{
try
{
long LongLength = from.LongLength - startIndex;
byte[] bArray = new byte[LongLength];
Array.Copy(from, startIndex, bArray, 0, LongLength);
return bArray;
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(ByteArrayExtensionClass).ToString(), "Copy()"));
}
}
/// <summary>
/// Remove a chunk of bytes at the end of array, staring from offset index
/// </summary>
/// <param name="from"></param>
/// <param name="fromIndex">offset 0..x</param>
/// <returns>Return copy of byte data</returns>
public static byte[] Remove(this byte[] from, long fromIndex)
{
try
{
byte[] bArray = new byte[fromIndex];
if (bArray.LongLength < fromIndex)
{
return from;
}
Array.Copy(from, 0, bArray, 0, fromIndex);
return bArray;
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(ByteArrayExtensionClass).ToString(), "Remove()"));
}
}
/// <summary>
/// Copy bytes until this character
/// </summary>
/// <param name="toInSeach">bytes to find character in</param>
/// <param name="untilThisCharacter">detection character</param>
/// <returns></returns>
internal static IEnumerable<byte> CopyUntil(this IEnumerable<byte> toInSeach, char untilThisCharacter)
{
try
{
if (toInSeach != null)
{
var withCharacter = toInSeach.TakeWhile(ch => ch != untilThisCharacter);
// has any data after this
if (withCharacter.Count() > 1)
{
return withCharacter;
}
}
return null; // nothing to return
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(ByteArrayExtensionClass).ToString(), "CopyUntil()"));
}
}
/// <summary>
/// Copy bytes after this character
/// </summary>
/// <param name="toInSeach">bytes to find character in</param>
/// <param name="afterFirstCharacterOfThis">detection character</param>
/// <returns></returns>
internal static IEnumerable<byte> CopyAfterThis(this IEnumerable<byte> toInSeach, char afterFirstCharacterOfThis)
{
try
{
if (toInSeach != null)
{
var withCharacter = toInSeach.SkipWhile(ch => ch != afterFirstCharacterOfThis);
// has any data after this
if (withCharacter.Count() > 1)
{
return withCharacter.Skip(1);
}
}
return null; // nothing to return
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(ByteArrayExtensionClass).ToString(), "CopyAfterThis()"));
}
}
/// <summary>
/// Copy bytes after this sequence of bytes
/// </summary>
/// <param name="toSeachIn">bytes to find character in</param>
/// <param name="afterFirstCharacterOfThis">detection sequence</param>
/// <returns></returns>
internal static IEnumerable<byte> CopyAfterThis(this IEnumerable<byte> toSeachIn, IEnumerable<byte> afterSequenceThis)
{
try
{
var toSeachNow = toSeachIn;
while ((toSeachNow != null) && (toSeachNow.Count() > 0) && (afterSequenceThis != null))
{
var startCh = afterSequenceThis.First();
var sequenceLng = afterSequenceThis.Count();
toSeachNow = toSeachNow.SkipWhile(ch => ch != startCh);
// If there is data after a possible sequence.. check if it have sequnece
if ((toSeachNow.Count() > sequenceLng) && afterSequenceThis.SequenceEqual(toSeachNow.Take(sequenceLng)))
{
if (toSeachNow.Count() > sequenceLng)
{
return toSeachNow.Skip(afterSequenceThis.Count());
}
return null; // nothing after sequence to return
}
// Not found
if ((toSeachNow == null) || (toSeachNow.Count() == 0))
{
return null; // nothing to return
}
// increase to next to find next start
toSeachNow = toSeachNow.Skip(1);
}
return null; // nothing to return
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(ByteArrayExtensionClass).ToString(), "CopyAfterThis()"));
}
}
/// <summary>
/// Swap high and low byte in a word(16bit) for all words in a byte array (use ex. to a line data correct for conversion to computer U16 from modbus u16)
/// </summary>
/// <param name="data">Data to swap (SWAP IS NOT DONE ON A COPY, BUT ON THE ARRAY GIVEN AS INPUT</param>
/// <returns>return swapped input array reference (done to help supporting single line code use ex. "var data = byteArrayNeedingSwap.SwapByteInWord();") </returns>
public static byte[] SwapByteInWord(this byte[] data)
{
try
{
if (data != null)
{
for (long i = 0; i < data.LongLength; i += 2)
{
byte b = data[i];
data[i] = data[i + 1];
data[i + 1] = b;
}
}
return data;
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(ByteArrayExtensionClass).ToString(), "SwapByteInWord()"));
}
}
/// <summary>
/// Compare if to array's has the same content (like array1 == array2)
/// </summary>
/// <param name="array1"></param>
/// <param name="array2"></param>
/// <returns>return true if the same</returns>
public static bool IsEqual(this byte[] array1, byte[] array2)
{
try
{
if ((array1 != null) && (array2 != null) && (array1.LongLength == array2.LongLength))
{
// To speed up
var result = array1.SequenceEqual(array2);
//{
//#if (!DEBUG)
//#error Test code!!!
//#endif
//if (!result) {
// var test = "Not the same!!";
// }
//}
return result;
}
return false;// not the same
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(ByteArrayExtensionClass).ToString(), "IsEqual()"));
}
}
/// <summary>
/// Slice an array of bytes in the same sizes
/// </summary>
/// <param name="source">Data to slice an array of bytes from</param>
/// <param name="startIndex">start in data for beginning slice of bytes</param>
/// <param name="eachSliceLength">The length of each slice of bytes</param>
/// <returns>List of byte slices with the same size</returns>
public static List<byte[]> SliceSameSize(this byte[] source, long startIndex, long eachSliceLength)
{
try
{
if (source == null)
{
return null;
}
var LongLength = source.LongLength;
var slices = new List<byte[]>();
for (long offset = startIndex; offset < LongLength; offset += eachSliceLength)
{
slices.Add(Copy(source, offset, eachSliceLength));
}
return slices;
}
catch (Exception ex)
{
throw new Exception(ex.ToFuncErrorText(typeof(ByteArrayExtensionClass).ToString(), "SliceSameSize()"));
}
}
/// <summary>
/// Slice a single array with a specific length
/// </summary>
/// <param name="source">Data to slice an array of bytes from </param>
/// <param name="startIndex">start in data for beginning slice of bytes</param>
/// <param name="length">how long is the slice from start index</param>
/// <returns></returns>
public static byte[] Slice(this byte[] source, long startIndex, long length)
{
try
{
var returnValue = new byte[length];
Array.Copy(source, startIndex, returnValue, 0, length);
return returnValue;
}
catch (Exception ex)
{
throw new InvalidOperationException(ex.ToFuncErrorText(typeof(ByteArrayExtensionClass).ToString(), "Slice()"));
}
}
/// <summary>
/// Fill or pad array with a specific value
/// </summary>
/// <param name="data"></param>
/// <param name="valueForFill"></param>
/// <returns></returns>
public static byte[] Fill(this byte[] data, byte valueForFill)
{
if (data != null)
{
for (long i = 0; i < data.LongLength; i++)
{
data[i] = valueForFill;
}
}
return data;
}
}
}