using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace XYLEM.Base { internal static class ByteArrayExtensionClass { /// /// Compare if values in to array's is equal /// /// /// /// 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(b2); } /// /// Copy a chunk of bytes from start index to a specific LongLength /// /// /// start offset 0..x /// LongLength of returned byte data array /// Return copy of byte data 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()")); } } /// /// Copy a chunk of bytes to the end of array, starting from start offset /// /// /// start offset 0..x /// Return copy of byte data 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()")); } } /// /// Remove a chunk of bytes at the end of array, staring from offset index /// /// /// offset 0..x /// Return copy of byte data 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()")); } } /// /// Copy bytes until this character /// /// bytes to find character in /// detection character /// internal static IEnumerable CopyUntil(this IEnumerable 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()")); } } /// /// Copy bytes after this character /// /// bytes to find character in /// detection character /// internal static IEnumerable CopyAfterThis(this IEnumerable 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()")); } } /// /// Copy bytes after this sequence of bytes /// /// bytes to find character in /// detection sequence /// internal static IEnumerable CopyAfterThis(this IEnumerable toSeachIn, IEnumerable 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()")); } } /// /// 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) /// /// Data to swap (SWAP IS NOT DONE ON A COPY, BUT ON THE ARRAY GIVEN AS INPUT /// return swapped input array reference (done to help supporting single line code use ex. "var data = byteArrayNeedingSwap.SwapByteInWord();") 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()")); } } /// /// Compare if to array's has the same content (like array1 == array2) /// /// /// /// return true if the same 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()")); } } /// /// Slice an array of bytes in the same sizes /// /// Data to slice an array of bytes from /// start in data for beginning slice of bytes /// The length of each slice of bytes /// List of byte slices with the same size public static List SliceSameSize(this byte[] source, long startIndex, long eachSliceLength) { try { if (source == null) { return null; } var LongLength = source.LongLength; var slices = new List(); 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()")); } } /// /// Slice a single array with a specific length /// /// Data to slice an array of bytes from /// start in data for beginning slice of bytes /// how long is the slice from start index /// 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()")); } } /// /// Fill or pad array with a specific value /// /// /// /// 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; } } }