namespace Sick.SafetyScanners.Helpers; /// /// Helper functions for reading and writing data with Big/Little Endian support /// Matches the logic from C++ ReadWriteHelper.hpp exactly /// Pure implementation without external dependencies /// public static class ReadWriteHelper { /// /// Safely gets a byte from ReadOnlySpan, returns 0 if out of range /// private static byte GetByte(ReadOnlySpan span, int offset) { return (offset < 0 || offset >= span.Length) ? (byte)0 : span[offset]; } /// /// Safely gets a byte from Span, returns 0 if out of range /// private static byte GetByte(Span span, int offset) { return (offset < 0 || offset >= span.Length) ? (byte)0 : span[offset]; } #region Write Operations - No Endian (8-bit only) /// /// Writes an unsigned 8-bit integer to a buffer at offset (no endianness for 1 byte) /// Matches: writeUint8 in C++ - *(it + 0) = v; /// public static void WriteUint8(Span span, int offset, byte value) { if (offset >= 0 && offset < span.Length) { span[offset] = value; } } /// /// Writes a signed 8-bit integer to a buffer at offset (no endianness for 1 byte) /// Matches: writeInt8 in C++ - writeUint8(it, v); /// public static void WriteInt8(Span span, int offset, sbyte value) { WriteUint8(span, offset, unchecked((byte)value)); } #endregion #region Write Operations - Big Endian /// /// Writes an unsigned 8-bit integer in big endian encoding /// Matches: writeUint8BigEndian in C++ - writeUint8(it, v); /// public static void WriteUint8BigEndian(Span span, int offset, byte value) { WriteUint8(span, offset, value); } /// /// Writes a signed 8-bit integer in big endian encoding /// Matches: writeInt8BigEndian in C++ - writeInt8(it, v); /// public static void WriteInt8BigEndian(Span span, int offset, sbyte value) { WriteInt8(span, offset, value); } /// /// Writes an unsigned 16-bit integer in big endian encoding /// Matches: writeUint16BigEndian in C++ - *(it + 0) = (v & 0xff00) >> 8; *(it + 1) = v & 0xff; /// public static void WriteUint16BigEndian(Span span, int offset, ushort value) { if (offset >= 0 && offset + 1 < span.Length) { span[offset + 0] = (byte)((value & 0xff00) >> 8); span[offset + 1] = (byte)(value & 0xff); } } /// /// Writes an unsigned 32-bit integer in big endian encoding /// Matches: writeUint32BigEndian in C++ - *(it + 0) = (v & 0xff000000) >> 24; ... /// public static void WriteUint32BigEndian(Span span, int offset, uint value) { if (offset >= 0 && offset + 3 < span.Length) { span[offset + 0] = (byte)((value & 0xff000000) >> 24); span[offset + 1] = (byte)((value & 0xff0000) >> 16); span[offset + 2] = (byte)((value & 0xff00) >> 8); span[offset + 3] = (byte)(value & 0xff); } } /// /// Writes a signed 16-bit integer in big endian encoding /// Matches: readInt16BigEndian calls readUint16BigEndian in C++ /// public static void WriteInt16BigEndian(Span span, int offset, short value) { WriteUint16BigEndian(span, offset, unchecked((ushort)value)); } /// /// Writes a signed 32-bit integer in big endian encoding /// Matches: readInt32BigEndian calls readUint32BigEndian in C++ /// public static void WriteInt32BigEndian(Span span, int offset, int value) { WriteUint32BigEndian(span, offset, unchecked((uint)value)); } #endregion #region Write Operations - Little Endian /// /// Writes an unsigned 8-bit integer in little endian encoding /// Matches: writeUint8LittleEndian in C++ - writeUint8(it, v); /// public static void WriteUint8LittleEndian(Span span, int offset, byte value) { WriteUint8(span, offset, value); } /// /// Writes a signed 8-bit integer in little endian encoding /// Matches: writeInt8LittleEndian in C++ - writeInt8(it, v); /// public static void WriteInt8LittleEndian(Span span, int offset, sbyte value) { WriteInt8(span, offset, value); } /// /// Writes an unsigned 16-bit integer in little endian encoding /// Matches: writeUint16LittleEndian in C++ - *(it + 0) = v & 0xff; *(it + 1) = (v & 0xff00) >> 8; /// public static void WriteUint16LittleEndian(Span span, int offset, ushort value) { if (offset >= 0 && offset + 1 < span.Length) { span[offset + 0] = (byte)(value & 0xff); span[offset + 1] = (byte)((value & 0xff00) >> 8); } } /// /// Writes an unsigned 32-bit integer in little endian encoding /// Matches: writeUint32LittleEndian in C++ - *(it + 3) = (v & 0xff000000) >> 24; ... /// public static void WriteUint32LittleEndian(Span span, int offset, uint value) { if (offset >= 0 && offset + 3 < span.Length) { span[offset + 3] = (byte)((value & 0xff000000) >> 24); span[offset + 2] = (byte)((value & 0xff0000) >> 16); span[offset + 1] = (byte)((value & 0xff00) >> 8); span[offset + 0] = (byte)(value & 0xff); } } /// /// Writes a signed 16-bit integer in little endian encoding /// Matches: readInt16LittleEndian calls readUint16LittleEndian in C++ /// public static void WriteInt16LittleEndian(Span span, int offset, short value) { WriteUint16LittleEndian(span, offset, unchecked((ushort)value)); } /// /// Writes a signed 32-bit integer in little endian encoding /// Matches: writeInt32LittleEndian in C++ - *(it + 3) = (v & 0xff000000) >> 24; ... /// public static void WriteInt32LittleEndian(Span span, int offset, int value) { if (offset >= 0 && offset + 3 < span.Length) { span[offset + 3] = (byte)((unchecked((uint)value) & 0xff000000) >> 24); span[offset + 2] = (byte)((unchecked((uint)value) & 0xff0000) >> 16); span[offset + 1] = (byte)((unchecked((uint)value) & 0xff00) >> 8); span[offset + 0] = (byte)(unchecked((uint)value) & 0xff); } } #endregion #region Read Operations - No Endian (8-bit only) /// /// Reads an unsigned 8-bit integer at offset (no endianness for 1 byte) /// Matches: readUint8 in C++ - return *(it + 0); /// public static byte ReadUint8(ReadOnlySpan span, int offset) { return GetByte(span, offset); } /// /// Reads a signed 8-bit integer at offset (no endianness for 1 byte) /// Matches: readInt8 in C++ - return readUint8(it); /// public static sbyte ReadInt8(ReadOnlySpan span, int offset) { return unchecked((sbyte)ReadUint8(span, offset)); } #endregion #region Read Operations - Big Endian /// /// Reads an unsigned 8-bit integer in big endian encoding /// Matches: readUint8BigEndian in C++ - return readUint8(it); /// public static byte ReadUint8BigEndian(ReadOnlySpan span, int offset) { return ReadUint8(span, offset); } /// /// Reads a signed 8-bit integer in big endian encoding /// Matches: readInt8BigEndian in C++ - return readInt8(it); /// public static sbyte ReadInt8BigEndian(ReadOnlySpan span, int offset) { return ReadInt8(span, offset); } /// /// Reads an unsigned 16-bit integer in big endian encoding /// Matches: readUint16BigEndian in C++ - return (*(it + 0) << 8) + *(it + 1); /// public static ushort ReadUint16BigEndian(ReadOnlySpan span, int offset) { return (ushort)((GetByte(span, offset + 0) << 8) + GetByte(span, offset + 1)); } /// /// Reads an unsigned 32-bit integer in big endian encoding /// Matches: readUint32BigEndian in C++ - return (*(it + 0) << 24) + (*(it + 1) << 16) + (*(it + 2) << 8) + *(it + 3); /// public static uint ReadUint32BigEndian(ReadOnlySpan span, int offset) { return ((uint)GetByte(span, offset + 0) << 24) + ((uint)GetByte(span, offset + 1) << 16) + ((uint)GetByte(span, offset + 2) << 8) + GetByte(span, offset + 3); } /// /// Reads a signed 16-bit integer in big endian encoding /// Matches: readInt16BigEndian in C++ - return readUint16BigEndian(it); /// public static short ReadInt16BigEndian(ReadOnlySpan span, int offset) { return unchecked((short)ReadUint16BigEndian(span, offset)); } /// /// Reads a signed 32-bit integer in big endian encoding /// Matches: readInt32BigEndian in C++ - return readUint32BigEndian(it); /// public static int ReadInt32BigEndian(ReadOnlySpan span, int offset) { return unchecked((int)ReadUint32BigEndian(span, offset)); } #endregion #region Read Operations - Little Endian /// /// Reads an unsigned 8-bit integer in little endian encoding /// Matches: readUint8LittleEndian in C++ - return readUint8(it); /// public static byte ReadUint8LittleEndian(ReadOnlySpan span, int offset) { return ReadUint8(span, offset); } /// /// Reads a signed 8-bit integer in little endian encoding /// Matches: readInt8LittleEndian in C++ - return readInt8(it); /// public static sbyte ReadInt8LittleEndian(ReadOnlySpan span, int offset) { return ReadInt8(span, offset); } /// /// Reads an unsigned 16-bit integer in little endian encoding /// Matches: readUint16LittleEndian in C++ - return (*(it + 1) << 8) + *(it + 0); /// public static ushort ReadUint16LittleEndian(ReadOnlySpan span, int offset) { return (ushort)((GetByte(span, offset + 1) << 8) + GetByte(span, offset + 0)); } /// /// Reads an unsigned 32-bit integer in little endian encoding /// Matches: readUint32LittleEndian in C++ - return (*(it + 3) << 24) + (*(it + 2) << 16) + (*(it + 1) << 8) + *(it + 0); /// public static uint ReadUint32LittleEndian(ReadOnlySpan span, int offset) { return ((uint)GetByte(span, offset + 3) << 24) + ((uint)GetByte(span, offset + 2) << 16) + ((uint)GetByte(span, offset + 1) << 8) + GetByte(span, offset + 0); } /// /// Reads a signed 16-bit integer in little endian encoding /// Matches: readInt16LittleEndian in C++ - return readUint16LittleEndian(it); /// public static short ReadInt16LittleEndian(ReadOnlySpan span, int offset) { return unchecked((short)ReadUint16LittleEndian(span, offset)); } /// /// Reads a signed 32-bit integer in little endian encoding /// Matches: readInt32LittleEndian in C++ - return readUint32LittleEndian(it); /// public static int ReadInt32LittleEndian(ReadOnlySpan span, int offset) { return unchecked((int)ReadUint32LittleEndian(span, offset)); } #endregion }