Skip to content

Commit

Permalink
ProgressOperations.ComputeHash
Browse files Browse the repository at this point in the history
  • Loading branch information
SLaks committed Aug 1, 2011
1 parent 34f5a0f commit 1d256aa
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 4 deletions.
22 changes: 21 additions & 1 deletion SLaks.Progression.Tests/ProgressOperationsTest.cs
Expand Up @@ -2,6 +2,7 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.IO;
using System.Security.Cryptography;

namespace SLaks.Progression.Tests {
[TestClass]
Expand Down Expand Up @@ -53,7 +54,8 @@ public class ProgressOperationsTest {
var source = new MemoryStream(bytes);
var target = new MemoryStream();

ProgressOperations.CopyTo(source, target, null);
var copied = ProgressOperations.CopyTo(source, target, null);
Assert.AreEqual(source.Length, copied);
CollectionAssert.AreEqual(bytes, target.ToArray());
}

Expand All @@ -67,5 +69,23 @@ public class ProgressOperationsTest {
Assert.AreEqual(source.Length, pr.Maximum);
Assert.AreEqual(pr.Maximum, pr.Progress);
}

[TestMethod]
public void ComputeHashTest() {
var bytes = new byte[rand.Next(65536, 1048576)];
rand.NextBytes(bytes);

var source = new MemoryStream(bytes);

var knownHash = new SHA512Managed().ComputeHash(source);
source.Position = 0;

var pr = new EmptyProgressReporter();
var myHash = ProgressOperations.ComputeHash(new SHA512Managed(), source, pr);

CollectionAssert.AreEqual(knownHash, myHash);
Assert.AreEqual(source.Length, pr.Maximum);
Assert.AreEqual(pr.Maximum, pr.Progress);
}
}
}
45 changes: 42 additions & 3 deletions SLaks.Progression/ProgressOperations.cs
Expand Up @@ -3,17 +3,18 @@
using System.Linq;
using System.Text;
using System.IO;
using System.Security.Cryptography;

namespace SLaks.Progression {
///<summary>Contains methods that perform useful operations and report progress.</summary>
public static class ProgressOperations {
///<summary>Copies one stream to another.</summary>
///<summary>Copies one stream to another while reporting progress.</summary>
///<param name="from">The stream to copy from. This stream must be readable.</param>
///<param name="to">The stream to copy to. This stream must be writable.</param>
///<param name="progress">An IProgressReporter implementation to report the progress of the upload.</param>
///<returns>The number of bytes copied.</returns>
public static long CopyTo(this Stream from, Stream to, IProgressReporter progress) { return from.CopyTo(to, null, progress); }
///<summary>Copies one stream to another.</summary>
///<summary>Copies one stream to another while reporting progress.</summary>
///<param name="from">The stream to copy from. This stream must be readable.</param>
///<param name="to">The stream to copy to. This stream must be writable.</param>
///<param name="length">The length of the source stream. This parameter is only used to report progress.</param>
Expand All @@ -30,7 +31,7 @@ public static class ProgressOperations {
if (length == null) {
try {
length = from.Length;
} catch (NotSupportedException) { progress.Maximum = -1; }
} catch (NotSupportedException) { progress.Progress = null; }
}

if (length == null)
Expand All @@ -53,5 +54,43 @@ public static class ProgressOperations {
to.Write(buffer, 0, bytesRead);
}
}

///<summary>Calculates a cryptographic hashcode of a file while reporting progress.</summary>
///<returns>The hash of the data, or null if the user clicked cancel.</returns>
public static byte[] ComputeHash(this HashAlgorithm hasher, string fileName, IProgressReporter progress) {
using (var stream = File.OpenRead(fileName))
return ComputeHash(hasher, stream, progress);
}
///<summary>Calculates a cryptographic hashcode of a stream while reporting progress.</summary>
///<returns>The hash of the data, or null if the user clicked cancel.</returns>
public static byte[] ComputeHash(this HashAlgorithm hasher, Stream stream, IProgressReporter progress) {
if (hasher == null) throw new ArgumentNullException("hasher");
if (stream == null) throw new ArgumentNullException("stream");


if (progress != null) {
try {
progress.Maximum = stream.Length;
} catch (NotSupportedException) { progress.Progress = null; }
}
progress = progress ?? new EmptyProgressReporter();

long totalCopied = 0;
var buffer = new byte[4096];
while (true) {
var bytesRead = stream.Read(buffer, 0, buffer.Length);

if (progress.Progress != null) progress.Progress = totalCopied;
if (progress.WasCanceled) return null;

totalCopied += bytesRead;
if (bytesRead == 0) break;
hasher.TransformBlock(buffer, 0, bytesRead, null, 0);
}
hasher.TransformFinalBlock(new byte[0], 0, 0);
var retVal = (byte[])hasher.Hash.Clone();
hasher.Initialize();
return retVal;
}
}
}

0 comments on commit 1d256aa

Please sign in to comment.