Created
January 7, 2012 14:20
-
-
Save clausjoergensen/1574856 to your computer and use it in GitHub Desktop.
Marshall Extensions for System.IO.Stream
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Text; | |
using System.Diagnostics.Contracts; | |
namespace System.Runtime.InteropServices | |
{ | |
/// <summary> | |
/// Marshall Extensions for <typeparamref name="System.IO.Stream"/>. | |
/// </summary> | |
public static class MarshallExtensions | |
{ | |
/// <summary> | |
/// Reads a struct of type <typeparamref name="T"/> from the input <paramref name="stream"/>. | |
/// </summary> | |
/// <typeparam name="T">The element type of the struct to be read.</typeparam> | |
/// <param name="stream">Input stream.</param> | |
/// <returns>The stream marshalled into a struct of type <typeparamref name="T"/>.</returns> | |
public static T Read<T>(this Stream stream) where T : struct | |
{ | |
Contract.Requires(stream != null); | |
if (stream == null) | |
{ | |
throw new ArgumentNullException("stream"); | |
} | |
byte[] buffer = new byte[Marshal.SizeOf(typeof(T))]; | |
stream.Read(buffer, 0, Marshal.SizeOf(typeof(T))); | |
GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); | |
T temp = default(T); | |
try | |
{ | |
temp = (T)Marshal.PtrToStructure( | |
handle.AddrOfPinnedObject(), typeof(T)); | |
} | |
finally | |
{ | |
handle.Free(); | |
} | |
return temp; | |
} | |
/// <summary> | |
/// Read a given amount of structs of type <typeparamref name="T"/> from the input <paramref name="stream"/>. | |
/// </summary> | |
/// <typeparam name="T">The element type of the struct to be read.</typeparam> | |
/// <param name="stream">Input stream.</param> | |
/// <param name="offset">Stream offset.</param> | |
/// <param name="count">Amount of items to read.</param> | |
/// <returns>A enumerator to the given amount of items of type <typeparamref name="T"/> read from the stream.</returns> | |
public static IEnumerable<T> Read<T>(this Stream stream, long offset, | |
int count) where T : struct | |
{ | |
Contract.Requires(stream != null); | |
Contract.Requires(offset >= 0); | |
Contract.Requires(count > 0); | |
if (stream == null) | |
throw new ArgumentNullException("stream"); | |
if (offset < 0) | |
throw new ArgumentException("Offset must be greater than or equal zero."); | |
if (count <= 0) | |
throw new ArgumentException("Count must be greater than zero."); | |
stream.Position = offset; | |
for (int i = 0; i < count; i++) | |
yield return Read<T>(stream); | |
stream.Position = 0; | |
} | |
/// <summary> | |
/// Reads a string from a stream, give a offset and the length of the string, | |
/// using the system default encoding. | |
/// </summary> | |
/// <param name="stream">Stream to read from.</param> | |
/// <param name="offset">Stream offset.</param> | |
/// <param name="length">String length.</param> | |
/// <returns>The string read from the stream.</returns> | |
public static string ReadString(this Stream stream, long offset, int length) | |
{ | |
Contract.Requires(stream != null); | |
Contract.Requires(offset >= 0); | |
Contract.Requires(length > 0); | |
if (stream == null) | |
throw new ArgumentNullException("stream"); | |
if (offset < 0) | |
throw new ArgumentException("Offset must be greater than or equal zero."); | |
if (length <= 0) | |
throw new ArgumentException("Length must be greater than zero."); | |
byte[] value = new byte[length]; | |
stream.Position = offset; | |
stream.Read(value, 0, length); | |
stream.Position = 0; | |
return Encoding.Default.GetString(value.Take(value.Length - 1).ToArray()); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment