Skip to content

Instantly share code, notes, and snippets.

@clausjoergensen
Created January 7, 2012 14:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save clausjoergensen/1574856 to your computer and use it in GitHub Desktop.
Save clausjoergensen/1574856 to your computer and use it in GitHub Desktop.
Marshall Extensions for System.IO.Stream
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