Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ByteUtility. #8

Merged
merged 1 commit into from
Sep 20, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions VersionHistory.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ is updated in preparation for publishing an updated NuGet package.

Prefix the description of the change with `[major]`, `[minor]` or `[patch]` in accordance with [SemVer](http://semver.org).

* [minor] Add `ByteUtility`.

## Released

### 0.3.0
Expand Down
3 changes: 2 additions & 1 deletion docs/Faithlife.Utility.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# Faithlife.Utility assembly

The assembly `Faithlife.Utility.dll` has 60 public types in 3 namespaces.
The assembly `Faithlife.Utility.dll` has 61 public types in 3 namespaces.

## Faithlife.Utility namespace

| public type | description |
| --- | --- |
| static class [ArrayUtility](Faithlife.Utility/ArrayUtility.md) | Provides methods for manipulating arrays. |
| static class [ByteUtility](Faithlife.Utility/ByteUtility.md) | Provides helper methods for working with Byte. |
| class [CachingStream](Faithlife.Utility/CachingStream.md) | A [`WrappingStream`](Faithlife.Utility/WrappingStream.md) that caches all data read from the underlying Stream. |
| enum [CaseSensitivity](Faithlife.Utility/CaseSensitivity.md) | Indicates whether an operation should be sensitive to case. |
| static class [CollectionImpl](Faithlife.Utility/CollectionImpl.md) | Provides implementations of common methods needed by an implementer of ICollection. |
Expand Down
21 changes: 21 additions & 0 deletions docs/Faithlife.Utility/ByteUtility.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# ByteUtility class

Provides helper methods for working with Byte.

```csharp
public static class ByteUtility
```

## Public Members

| name | description |
| --- | --- |
| static [ToBytes](ByteUtility/ToBytes.md)(…) | Converts the specified string representation of bytes into a byte array. |
| static [ToString](ByteUtility/ToString.md)(…) | Converts the specified byte array to a string of hex digits. |

## See Also

* namespace [Faithlife.Utility](../Faithlife.Utility.md)
* [ByteUtility.cs](https://github.com/Faithlife/FaithlifeUtility/tree/master/src/Faithlife.Utility/ByteUtility.cs)

<!-- DO NOT EDIT: generated by xmldocmd for Faithlife.Utility.dll -->
22 changes: 22 additions & 0 deletions docs/Faithlife.Utility/ByteUtility/ToBytes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# ByteUtility.ToBytes method

Converts the specified string representation of bytes into a byte array.

```csharp
public static byte[] ToBytes(string value)
```

| parameter | description |
| --- | --- |
| value | The byte values; these must be hexadecimal numbers with no padding or separators. |

## Return Value

A byte array containing the bytes represented in the string.

## See Also

* class [ByteUtility](../ByteUtility.md)
* namespace [Faithlife.Utility](../../Faithlife.Utility.md)

<!-- DO NOT EDIT: generated by xmldocmd for Faithlife.Utility.dll -->
22 changes: 22 additions & 0 deletions docs/Faithlife.Utility/ByteUtility/ToString.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# ByteUtility.ToString method

Converts the specified byte array to a string of hex digits.

```csharp
public static string ToString(byte[] bytes)
```

| parameter | description |
| --- | --- |
| bytes | The byte array to convert. |

## Return Value

A string containing two hexadecimal digits for each input byte.

## See Also

* class [ByteUtility](../ByteUtility.md)
* namespace [Faithlife.Utility](../../Faithlife.Utility.md)

<!-- DO NOT EDIT: generated by xmldocmd for Faithlife.Utility.dll -->
65 changes: 65 additions & 0 deletions src/Faithlife.Utility/ByteUtility.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System;

namespace Faithlife.Utility
{
/// <summary>
/// Provides helper methods for working with <see cref="byte"/>.
/// </summary>
public static class ByteUtility
{
/// <summary>
/// Converts the specified string representation of bytes into a byte array.
/// </summary>
/// <param name="value">The byte values; these must be hexadecimal numbers with no padding or separators.</param>
/// <returns>A byte array containing the bytes represented in the string.</returns>
public static byte[] ToBytes(string value)
{
if (value == null)
throw new ArgumentNullException(nameof(value));
if (value.Length % 2 != 0)
throw new ArgumentException("There must be an even number of characters in the string.", nameof(value));

byte[] bytes = new byte[value.Length / 2];
for (int nByte = 0; nByte < bytes.Length; nByte++)
bytes[nByte] = (byte) (ConvertToNibble(value[nByte * 2]) * 16 + ConvertToNibble(value[nByte * 2 + 1]));

return bytes;
}

/// <summary>
/// Converts the specified byte array to a string of hex digits.
/// </summary>
/// <param name="bytes">The byte array to convert.</param>
/// <returns>A string containing two hexadecimal digits for each input byte.</returns>
public static string ToString(byte[] bytes)
{
if (bytes == null)
throw new ArgumentNullException(nameof(bytes));

const string c_strHexDigits = "0123456789ABCDEF";

// allocate char array and fill it with high and low nibbles of each byte
char[] chars = new char[bytes.Length * 2];
for (int nIndex = 0; nIndex < chars.Length; nIndex += 2)
{
byte by = bytes[nIndex / 2];
chars[nIndex] = c_strHexDigits[by / 16];
chars[nIndex + 1] = c_strHexDigits[by % 16];
}

return new string(chars);
}

private static int ConvertToNibble(char ch)
{
if (ch >= '0' && ch <= '9')
return ch - '0';
else if (ch >= 'A' && ch <= 'F')
return ch - 'A' + 10;
else if (ch >= 'a' && ch <= 'f')
return ch - 'a' + 10;
else
throw new ArgumentOutOfRangeException(nameof(ch));
}
}
}
37 changes: 37 additions & 0 deletions tests/Faithlife.Utility.Tests/ByteUtilityTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using NUnit.Framework;

namespace Faithlife.Utility.Tests
{
[TestFixture]
public class ByteUtilityTests
{
[Test]
public void ToBytesArguments()
{
Assert.Throws<ArgumentNullException>(() => ByteUtility.ToBytes(null));
Assert.Throws<ArgumentException>(() => ByteUtility.ToBytes("1"));
Assert.Throws<ArgumentOutOfRangeException>(() => ByteUtility.ToBytes("XY"));
}

[Test]
public void ToStringArguments()
{
Assert.Throws<ArgumentNullException>(() => ByteUtility.ToString(null));
}

[TestCase("", new byte[0])]
[TestCase("12", new byte[] { 0x12 })]
[TestCase("abCDEf", new byte[] { 0xab, 0xcd, 0xef })]
[TestCase("000102030405060708090A0B0C0D0E0F", new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 })]
[TestCase("00102030405060708090A0B0C0D0E0F0", new byte[] { 0, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 208, 224, 240 })]
public void RoundTrip(string input, byte[] expected)
{
byte[] actual = ByteUtility.ToBytes(input);
CollectionAssert.AreEqual(expected, actual);

string output = ByteUtility.ToString(actual);
Assert.AreEqual(input.ToUpperInvariant(), output);
}
}
}