예제 #1
0
        /// <summary>
        /// Converts a span of 8-bit unsigned integers to its equivalent string representation that is encoded with hex characters.
        /// A parameter specifies whether to insert line breaks in the return value and whether to insert upper- or lowercase hex characters.
        /// </summary>
        /// <param name="bytes">A span of 8-bit unsigned integers.</param>
        /// <param name="options"><see cref="HexFormattingOptions.Lowercase"/> to produce lowercase output. <see cref="HexFormattingOptions.InsertLineBreaks"/> to insert a line break every 72 characters. <see cref="HexFormattingOptions.None"/> to do neither.</param>
        /// <returns>The string representation in hex of the elements in <paramref name="bytes"/>.</returns>
        /// <exception cref="ArgumentException"><paramref name="options"/> is not a valid <see cref="HexFormattingOptions"/> value.</exception>
        public static string ToHexString(ReadOnlySpan <byte> bytes, HexFormattingOptions options = default)
        {
            if (options < HexFormattingOptions.None || options > (HexFormattingOptions.Lowercase | HexFormattingOptions.InsertLineBreaks))
            {
                throw new ArgumentException(SR.Format(SR.Arg_EnumIllegalVal, (int)options), nameof(options));
            }
            if (bytes.Length == 0)
            {
                return(string.Empty);
            }

            var insertLineBreaks = (options & HexFormattingOptions.InsertLineBreaks) != 0;
            var outlen           = ToHex_CalculateAndValidateOutputLength(bytes.Length, insertLineBreaks);

            unsafe
            {
                fixed(byte *bytesPtr = &MemoryMarshal.GetReference(bytes))
                {
                    return(string.Create(outlen, (Bytes: (IntPtr)bytesPtr, bytes.Length, Options: options), (span, state) =>
                    {
                        fixed(char *outPtr = &MemoryMarshal.GetReference(span))
                        {
                            ConvertToHexArray(outPtr, span.Length, (byte *)state.Bytes, state.Length, state.Options);
                        }
                    }));
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Converts a subset of an array of 8-bit unsigned integers to its equivalent string representation that is encoded with hex characters.
        /// Parameters specify the subset as an offset in the input array, the number of elements in the array to convert,
        /// whether to insert line breaks in the return value, and whether to insert upper- or lowercase hex characters.
        /// </summary>
        /// <param name="inArray">An array of 8-bit unsigned integers.</param>
        /// <param name="offset">An offset in <paramref name="inArray"/>.</param>
        /// <param name="length">The number of elements of <paramref name="inArray"/> to convert.</param>
        /// <param name="options"><see cref="HexFormattingOptions.Lowercase"/> to produce lowercase output. <see cref="HexFormattingOptions.InsertLineBreaks"/> to insert a line break every 72 characters. <see cref="HexFormattingOptions.None"/> to do neither.</param>
        /// <returns>The string representation in hex of <paramref name="length"/> elements of <paramref name="inArray"/>, starting at position <paramref name="offset"/>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="inArray"/> is <code>null</code>.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="offset"/> or <paramref name="length"/> is negative.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="offset"/> plus <paramref name="length"/> is greater than the length of <paramref name="inArray"/>.</exception>
        /// <exception cref="ArgumentException"><paramref name="options"/> is not a valid <see cref="HexFormattingOptions"/> value.</exception>
        public static string ToHexString(byte[] inArray, int offset, int length, HexFormattingOptions options = default)
        {
            if (inArray == null)
            {
                throw new ArgumentNullException(nameof(inArray));
            }
            if (length < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_Index);
            }
            if (offset < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_GenericPositive);
            }
            if (offset > (inArray.Length - length))
            {
                throw new ArgumentOutOfRangeException(nameof(offset), SR.ArgumentOutOfRange_OffsetLength);
            }
            if (options < HexFormattingOptions.None || options > (HexFormattingOptions.Lowercase | HexFormattingOptions.InsertLineBreaks))
            {
                throw new ArgumentException(SR.Format(SR.Arg_EnumIllegalVal, (int)options), nameof(options));
            }
            if (length == 0)
            {
                return(string.Empty);
            }

            var insertLineBreaks = (options & HexFormattingOptions.InsertLineBreaks) != 0;
            var outlen           = ToHex_CalculateAndValidateOutputLength(inArray.Length - offset, insertLineBreaks);

#if SPAN
            return(string.Create(outlen, (arr: inArray, off: offset, len: length, opt: options), (span, state) =>
            {
                unsafe
                {
                    fixed(byte *inPtr = state.arr)
                    fixed(char *outPtr = &MemoryMarshal.GetReference(span))
                    {
                        ConvertToHexArray(outPtr, span.Length, inPtr + state.off, state.len, state.opt);
                    }
                }
            }));
#else
            var result = new string('\0', outlen);
            unsafe
            {
                fixed(byte *inPtr = inArray)
                fixed(char *outPtr = result)
                {
                    ConvertToHexArray(outPtr, outlen, inPtr + offset, length, options);
                }
            }

            return(result);
#endif
        }
            public void Encode(int length, HexFormattingOptions options)
            {
                var inArray = new byte[length];

                _random.NextBytes(inArray);

                var expected = EncodeSlow(inArray, options);
                var result   = ProcessBytes(inArray, expected.Length, options);

                Assert.Equal(expected, result);
            }
예제 #4
0
            protected override string ProcessBytes(byte[] bytes, int expectedLength, HexFormattingOptions options)
            {
                var resultLength = _random.Next(expectedLength + 3, expectedLength + 10);
                var resultOffset = _random.Next(0, resultLength - expectedLength);

                var result  = new char[resultLength];
                var written = Convert.ToHexCharArray(bytes, 0, bytes.Length, result, resultOffset, options);

                Assert.Equal(expectedLength, written);

                return(new string(result, resultOffset, written));
            }
            private static string EncodeSlow(byte[] input, HexFormattingOptions options)
            {
                const int insertLineBreaksEvery = 72;
                var       result = BitConverter.ToString(input).Replace("-", string.Empty);

                if (options.HasFlag(HexFormattingOptions.InsertLineBreaks) && result.Length > insertLineBreaksEvery)
                {
                    var newResult = new StringBuilder();
                    for (var i = 0; i < result.Length; i += insertLineBreaksEvery)
                    {
                        newResult.Append(result.Substring(i, Math.Min(insertLineBreaksEvery, result.Length - i)));
                        newResult.Append("\r\n"); // Convert does not add platform-specific new-lines
                    }

                    result = newResult.ToString().TrimEnd();
                }

                if (options.HasFlag(HexFormattingOptions.Lowercase))
                {
                    return(result.ToLower());
                }

                return(result);
            }
 protected abstract void AcceptOptions(HexFormattingOptions options);
예제 #7
0
        private static unsafe void ConvertToHexArray(char *outChars, int outLength, byte *inData, int inLength, HexFormattingOptions options)
        {
            const int perLine   = hexLineBreakPosition / 2;
            var       remaining = inLength;

            var src  = inData + inLength;
            var dest = outChars + outLength;

            var toLower          = (options & HexFormattingOptions.Lowercase) != 0;
            var insertLineBreaks = (options & HexFormattingOptions.InsertLineBreaks) != 0;

            if (!insertLineBreaks)
            {
#if INTRINSICS
                if (Avx2.IsSupported & remaining >= 32)
                {
                    remaining -= Utf16HexFormatter.Avx2.Format(ref src, ref dest, remaining, toLower);
                    Debug.Assert(remaining < 32);
                }

                if (remaining >= 16)
                {
                    if (Ssse3.IsSupported)
                    {
                        remaining -= Utf16HexFormatter.Ssse3.Format(ref src, ref dest, remaining, toLower);
                        Debug.Assert(remaining < 16);
                    }
                    else if (Sse2.IsSupported)
                    {
                        remaining -= Utf16HexFormatter.Sse2.Format(ref src, ref dest, remaining, toLower);
                        Debug.Assert(remaining < 16);
                    }
                }
#endif
                if (remaining > 0)
                {
                    remaining -= Utf16HexFormatter.Fixed.Format(ref src, ref dest, remaining, toLower);
                }
                Debug.Assert(remaining == 0);
            }
            else
            {
                var remainder = remaining % perLine;
                var remainingOnCurrentLine = remainder == 0 ? perLine : remainder;
                var bytesInIteration       = remainingOnCurrentLine;
                while (remaining != 0)
                {
#if INTRINSICS
                    if (Avx2.IsSupported)
                    {
                        if (remainingOnCurrentLine >= 32)
                        {
                            remainingOnCurrentLine -= Utf16HexFormatter.Avx2.Format(ref src, ref dest, remainingOnCurrentLine, toLower);
                            Debug.Assert(remainingOnCurrentLine < 32);
                        }
                    }
                    else if (remainingOnCurrentLine >= 16)
                    {
                        // Never run SSE code if AVX2 is available, as the remaining 8 bytes per line cannot be SSE-processed
                        if (Ssse3.IsSupported)
                        {
                            remainingOnCurrentLine -= Utf16HexFormatter.Ssse3.Format(ref src, ref dest, remainingOnCurrentLine, toLower);
                            Debug.Assert(remainingOnCurrentLine < 16);
                        }
                        else if (Sse2.IsSupported)
                        {
                            remainingOnCurrentLine -= Utf16HexFormatter.Sse2.Format(ref src, ref dest, remainingOnCurrentLine, toLower);
                            Debug.Assert(remainingOnCurrentLine < 16);
                        }
                    }
#endif
                    if (remainingOnCurrentLine > 0)
                    {
                        remainingOnCurrentLine -= Utf16HexFormatter.Fixed.Format(ref src, ref dest, remainingOnCurrentLine, toLower);
                    }
                    Debug.Assert(remainingOnCurrentLine == 0);

                    remaining -= bytesInIteration;
                    if (remaining == 0)
                    {
                        return;
                    }

                    *(--dest) = '\n';
                    *(--dest) = '\r';
                    remainingOnCurrentLine = perLine;
                    bytesInIteration       = remainingOnCurrentLine;
                }
            }
        }
예제 #8
0
        /// <summary>
        /// Converts a span of 8-bit unsigned integers to an equivalent span of a Unicode characters encoded with hex characters.
        /// A parameter specifies whether to insert line breaks in the return value and whether to insert upper- or lowercase hex characters.
        /// </summary>
        /// <param name="bytes">The input span.</param>
        /// <param name="chars">The output span</param>
        /// <param name="charsWritten">The number of bytes written into <paramref name="chars"/>.</param>
        /// <param name="options"><see cref="HexFormattingOptions.Lowercase"/> to produce lowercase output. <see cref="HexFormattingOptions.InsertLineBreaks"/> to insert a line break every 72 characters. <see cref="HexFormattingOptions.None"/> to do neither.</param>
        /// <returns>Whether the conversion operation completed successfully.</returns>
        /// <exception cref="ArgumentException"><paramref name="options"/> is not a valid <see cref="HexFormattingOptions"/> value.</exception>
        public static bool TryToHexChars(ReadOnlySpan <byte> bytes, Span <char> chars, out int charsWritten, HexFormattingOptions options = default)
        {
            if (options < HexFormattingOptions.None || options > (HexFormattingOptions.Lowercase | HexFormattingOptions.InsertLineBreaks))
            {
                throw new ArgumentException(SR.Format(SR.Arg_EnumIllegalVal, (int)options), nameof(options));
            }
            if (bytes.Length == 0)
            {
                charsWritten = 0;
                return(true);
            }

            var insertLineBreaks = (options & HexFormattingOptions.InsertLineBreaks) != 0;
            var outlen           = ToHex_CalculateAndValidateOutputLength(bytes.Length, insertLineBreaks);

            if (chars.Length < outlen)
            {
                charsWritten = 0;
                return(false);
            }

            unsafe
            {
                fixed(byte *inPtr = &MemoryMarshal.GetReference(bytes))
                fixed(char *outPtr = &MemoryMarshal.GetReference(chars))
                {
                    ConvertToHexArray(outPtr, chars.Length, inPtr, bytes.Length, options);
                }
            }

            charsWritten = outlen;
            return(true);
        }
예제 #9
0
        /// <summary>
        /// Converts a subset of an 8-bit unsigned integer array to an equivalent subset of a Unicode character array encoded with hex characters.
        /// Parameters specify the subsets as offsets in the input and output arrays, the number of elements in the input array to convert,
        /// whether line breaks are inserted in the output array, and whether to insert upper- or lowercase hex characters.
        /// </summary>
        /// <param name="inArray">An input array of 8-bit unsigned integers.</param>
        /// <param name="offsetIn">A position within <paramref name="inArray"/>.</param>
        /// <param name="length">The number of elements of <paramref name="inArray"/> to convert.</param>
        /// <param name="outArray">An output array of Unicode characters.</param>
        /// <param name="offsetOut">A position within <paramref name="outArray"/>.</param>
        /// <param name="options"><see cref="HexFormattingOptions.Lowercase"/> to produce lowercase output. <see cref="HexFormattingOptions.InsertLineBreaks"/> to insert a line break every 72 characters. <see cref="HexFormattingOptions.None"/> to do neither.</param>
        /// <returns>A 32-bit signed integer containing the number of bytes in <paramref name="outArray"/>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="inArray"/> or <paramref name="outArray"/> is null.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="offsetIn"/>, <paramref name="offsetOut"/>, or <paramref name="length"/> is negative.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="offsetIn"/> plus <paramref name="length"/> is greater than the length of <paramref name="inArray"/>.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="offsetOut"/> plus the number of elements to return is greater than the length of <paramref name="outArray"/>.</exception>
        /// <exception cref="ArgumentException"><paramref name="options"/> is not a valid <see cref="HexFormattingOptions"/> value.</exception>
        public static int ToHexCharArray(byte[] inArray, int offsetIn, int length, char[] outArray, int offsetOut, HexFormattingOptions options = default)
        {
            if (inArray == null)
            {
                throw new ArgumentNullException(nameof(inArray));
            }
            if (length < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(length), SR.ArgumentOutOfRange_Index);
            }
            if (offsetIn < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(offsetIn), SR.ArgumentOutOfRange_GenericPositive);
            }
            if (offsetIn > (inArray.Length - length))
            {
                throw new ArgumentOutOfRangeException(nameof(offsetIn), SR.ArgumentOutOfRange_OffsetLength);
            }
            if (outArray == null)
            {
                throw new ArgumentNullException(nameof(outArray));
            }
            if (offsetOut < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(offsetOut), SR.ArgumentOutOfRange_GenericPositive);
            }
            if (options < HexFormattingOptions.None || options > (HexFormattingOptions.Lowercase | HexFormattingOptions.InsertLineBreaks))
            {
                throw new ArgumentException(SR.Format(SR.Arg_EnumIllegalVal, (int)options), nameof(options));
            }

            var insertLineBreaks = (options & HexFormattingOptions.InsertLineBreaks) != 0;
            var outlen           = ToHex_CalculateAndValidateOutputLength(inArray.Length - offsetIn, insertLineBreaks);

            if (offsetOut > outArray.Length - outlen)
            {
                throw new ArgumentOutOfRangeException(nameof(offsetOut), SR.ArgumentOutOfRange_OffsetOut);
            }

            unsafe
            {
                fixed(byte *inPtr = inArray)
                fixed(char *outPtr = outArray)
                {
                    ConvertToHexArray(outPtr + offsetOut, outlen, inPtr + offsetIn, length, options);
                }
            }

            return(outlen);
        }
                protected override string ProcessBytes(byte[] bytes, int expectedLength, HexFormattingOptions options)
                {
                    var result = Convert.ToHexString(bytes.AsSpan(), options);

                    Assert.Equal(expectedLength, result.Length);
                    return(result);
                }
 protected override void AcceptOptions(HexFormattingOptions options)
 {
     Convert.ToHexString(ReadOnlySpan <byte> .Empty, options);
 }
예제 #12
0
                protected override string ProcessBytes(byte[] bytes, int expectedLength, HexFormattingOptions options)
                {
                    var buffer = new char[expectedLength];

                    var result = Convert.TryToHexChars(bytes.AsSpan(), buffer.AsSpan(), out var written, options);

                    Assert.Equal(expectedLength, written);
                    Assert.True(result);

                    return(new string(buffer));
                }
예제 #13
0
 protected override void AcceptOptions(HexFormattingOptions options)
 {
     Convert.TryToHexChars(ReadOnlySpan <byte> .Empty, Span <char> .Empty, out _, options);
 }
예제 #14
0
 protected override void AcceptOptions(HexFormattingOptions options)
 {
     Convert.ToHexString(Array.Empty <byte>(), options);
 }
 protected abstract string ProcessBytes(byte[] bytes, int expectedLength, HexFormattingOptions options);
예제 #16
0
 /// <summary>
 /// Converts an array of 8-bit unsigned integers to its equivalent string representation that is encoded with hex characters.
 /// A parameter specifies whether to insert line breaks in the return value and whether to insert upper- or lowercase hex characters.
 /// </summary>
 /// <param name="inArray">An array of 8-bit unsigned integers.</param>
 /// <param name="options"><see cref="HexFormattingOptions.Lowercase"/> to produce lowercase output. <see cref="HexFormattingOptions.InsertLineBreaks"/> to insert a line break every 72 characters. <see cref="HexFormattingOptions.None"/> to do neither.</param>
 /// <returns>The string representation in hex of the elements in <paramref name="inArray"/>.</returns>
 /// <exception cref="ArgumentNullException"><paramref name="inArray"/> is <code>null</code>.</exception>
 /// <exception cref="ArgumentException"><paramref name="options"/> is not a valid <see cref="HexFormattingOptions"/> value.</exception>
 public static string ToHexString(byte[] inArray, HexFormattingOptions options = default)
 => ToHexString(inArray, 0, inArray?.Length ?? 0, options);
예제 #17
0
 protected override void AcceptOptions(HexFormattingOptions options)
 {
     Convert.ToHexCharArray(Array.Empty <byte>(), 0, 0, Array.Empty <char>(), 0, options);
 }