/*
OpenNxSerialization Framework
Copyright (C) 2006 - 2008 "NeXtreme Innovations"
[The Next Xtreme Innovations]
This program is free software, distributed under the terms of
the GNU General Public License Version 2. See the "License.txt" file
at the top of the source tree.
*/
using System;
using System.IO;
using System.Text;
using System.Runtime.Serialization;
using System.Runtime.Remoting.Messaging;
using NeXtreme.OpenNxSerialization.Surrogates;
namespace NeXtreme.OpenNxSerialization.IO
{
/// <summary>
/// This class encapsulates a <see cref="BinaryReader"/> object. It also provides an extra
/// Read method for <see cref="System.Object"/> types.
/// </summary>
public class NxBinaryReader : IDisposable, INxBinaryReader
{
private NxSerializationContext mContext;
private BinaryReader mBaseReader;
/// <summary>
/// Constructs a compact reader over a <see cref="Stream"/> object.
/// </summary>
/// <param name="input"><see cref="Stream"/> object</param>
/// <exception cref="ArgumentNullException">If <paramref name="input"/> is null</exception>
public NxBinaryReader(Stream input)
: this(input, Encoding.Default, new NxSerializationContext())
{
}
/// <summary>
/// Constructs a compact reader over a <see cref="Stream"/> object.
/// </summary>
/// <param name="input"><see cref="Stream"/> object</param>
/// <param name="encoding"><see cref="System.Text.Encoding"/> object</param>
/// <exception cref="ArgumentNullException">If <paramref name="input"/> is null</exception>
public NxBinaryReader(Stream input, Encoding encoding)
: this(input, Encoding.Default, new NxSerializationContext())
{
mContext = new NxSerializationContext();
mBaseReader = new BinaryReader(input, encoding);
}
/// <summary>
/// Constructs a compact reader over a <see cref="Stream"/> object.
/// </summary>
/// <param name="input"><see cref="Stream"/> object</param>
/// <param name="encoding"><see cref="System.Text.Encoding"/> object</param>
/// <param name="context"><see cref="NxSerializationContext"/> object</param>
/// <exception cref="ArgumentNullException">If <paramref name="input"/> is null</exception>
/// <exception cref="ArgumentNullException">If <paramref name="context"/> is null</exception>
public NxBinaryReader(Stream input, Encoding encoding, NxSerializationContext context)
{
if (input == null)
throw new ArgumentNullException("input");
if (context == null)
throw new ArgumentNullException("context");
this.mContext = context;
this.mBaseReader = new BinaryReader(input, encoding);
}
/// <summary>
/// Finalizer
/// </summary>
~NxBinaryReader()
{
Dispose(false);
}
/// <summary> Returns the underlying <see cref="Stream"/> object. </summary>
public Stream BaseStream { get { return mBaseReader.BaseStream; } }
/// <summary> Returns the current <see cref="NxSerializationContext"/> object. </summary>
public NxSerializationContext Context { get { return mContext; } }
/// <summary>Returns the associated <see cref="INxTypeSurrogateSelector"/> instance.</summary>
public INxTypeSurrogateSelector SurrogateSelector { get { return mContext.SurrogateSelector; } }
/// <summary>
/// Close the underlying <see cref="BinaryWriter"/>.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Close the underlying <see cref="BinaryWriter"/>.
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
}
}
/// <summary>
/// Reads an object of type <see cref="object"/> from the current stream
/// and advances the stream position.
/// </summary>
/// <returns>The root of the deserialized object graph</returns>
public object ReadObject()
{
// read type handle
short handle = ReadInt16();
// Find an appropriate surrogate by handle
INxSerializationSurrogate surrogate =
mContext.SurrogateSelector.GetSurrogateForTypeHandle(handle);
return surrogate.Read(this);
}
/// <summary>
/// Reads an object of type <see cref="object"/> from the current stream
/// and advances the stream position.
/// </summary>
/// <param name="handler">The delegate designed to handle <see cref="Header"/> objects. Can be a null reference</param>
/// <returns>The root of the deserialized object graph</returns>
public object ReadObject(HeaderHandler handler)
{
// read type handle
short handle = ReadInt16();
// Find an appropriate surrogate by handle
INxSerializationSurrogate surrogate = mContext.SurrogateSelector.GetSurrogateForTypeHandle(handle);
if (surrogate is INxRemotingSerializationSurrogate)
return ((INxRemotingSerializationSurrogate)surrogate).Read(this, handler);
else
{
Header[] headers = (Header[])ReadObjectAs(typeof(Header[]));
if (handler != null)
handler(headers);
return surrogate.Read(this);
}
}
/// <summary>
/// Reads an object of type <see cref="object"/> from the current stream
/// and advances the stream position.
/// </summary>
/// <param name="type">Reads the object using surrogate for type <paramref name="type"/></param>
/// <returns>object read from the stream</returns>
public object ReadObjectAs(Type type)
{
if (type == null)
throw new ArgumentNullException("type");
// Find an appropriate surrogate by type
INxSerializationSurrogate surrogate =
mContext.SurrogateSelector.GetSurrogateForType(type);
return surrogate.Read(this);
}
/// <summary>
/// Reads an object of type <see cref="object"/> from the current stream
/// and advances the stream position.
/// </summary>
/// <param name="type">Reads the object using surrogate for type <paramref name="type"/></param>
/// <param name="handler">The delegate designed to handle <see cref="Header"/> objects. Can be a null reference</param>
/// <returns>The root of the deserialized object graph</returns>
/// <returns>object read from the stream</returns>
public object ReadObjectAs(Type type, HeaderHandler handler)
{
if (type == null)
throw new ArgumentNullException("type");
// Find an appropriate surrogate by type
INxSerializationSurrogate surrogate = mContext.SurrogateSelector.GetSurrogateForType(type);
if (surrogate is INxRemotingSerializationSurrogate)
return ((INxRemotingSerializationSurrogate)surrogate).Read(this, handler);
else
{
Header[] headers = (Header[])ReadObjectAs(typeof(Header[]));
if (handler != null)
handler(headers);
return surrogate.Read(this);
}
}
/// <summary>
/// Reads an object of type <see cref="object"/> from the current stream
/// and advances the stream position.
/// </summary>
/// <returns>object read from the stream</returns>
public T ReadObjectAs<T>()
{
// Find an appropriate surrogate by type
INxSerializationSurrogate surrogate =
mContext.SurrogateSelector.GetSurrogateForType(typeof(T));
return (T)surrogate.Read(this);
}
/// <summary>
/// Reads an object of type T from the current stream
/// and advances the stream position.
/// </summary>
/// <param name="handler">The delegate designed to handle <see cref="Header"/> objects. Can be a null reference</param>
/// <returns>The root of the deserialized object graph</returns>
/// <returns>object of type T read from the stream</returns>
public T ReadObjectAs<T>(HeaderHandler handler)
{
// Find an appropriate surrogate by type
INxSerializationSurrogate surrogate =
mContext.SurrogateSelector.GetSurrogateForType(typeof(T));
if (surrogate is INxRemotingSerializationSurrogate)
return (T)((INxRemotingSerializationSurrogate)surrogate).Read(this, handler);
else
{
Header[] headers = (Header[])ReadObjectAs(typeof(Header[]));
if (handler != null)
handler(headers);
return (T)surrogate.Read(this);
}
}
#region / NxBinaryReader.ReadXXX /
/// <summary>
/// Reads an object of type <see cref="bool"/> from the current stream
/// and advances the stream position.
/// This method reads directly from the underlying stream.
/// </summary>
/// <returns>object read from the stream</returns>
public bool ReadBoolean() { return mBaseReader.ReadBoolean(); }
/// <summary>
/// Reads an object of type <see cref="byte"/> from the current stream
/// and advances the stream position.
/// This method reads directly from the underlying stream.
/// </summary>
/// <returns>object read from the stream</returns>
public byte ReadByte() { return mBaseReader.ReadByte(); }
/// <summary>
/// Reads an object of type <see cref="byte"/>[] from the current stream
/// and advances the stream position.
/// This method reads directly from the underlying stream.
/// </summary>
/// <param name="count">number of bytes read</param>
/// <returns>object read from the stream</returns>
public byte[] ReadBytes(int count) { return mBaseReader.ReadBytes(count); }
/// <summary>
/// Reads an object of type <see cref="char"/> from the current stream
/// and advances the stream position.
/// This method reads directly from the underlying stream.
/// </summary>
/// <returns>object read from the stream</returns>
public char ReadChar() { return mBaseReader.ReadChar(); }
/// <summary>
/// Reads an object of type <see cref="char"/>[] from the current stream
/// and advances the stream position.
/// This method reads directly from the underlying stream.
/// </summary>
/// <returns>object read from the stream</returns>
public char[] ReadChars(int count) { return mBaseReader.ReadChars(count); }
/// <summary>
/// Reads an object of type <see cref="decimal"/> from the current stream
/// and advances the stream position.
/// This method reads directly from the underlying stream.
/// </summary>
/// <returns>object read from the stream</returns>
public decimal ReadDecimal() { return mBaseReader.ReadDecimal(); }
/// <summary>
/// Reads an object of type <see cref="float"/> from the current stream
/// and advances the stream position.
/// This method reads directly from the underlying stream.
/// </summary>
/// <returns>object read from the stream</returns>
public float ReadSingle() { return mBaseReader.ReadSingle(); }
/// <summary>
/// Reads an object of type <see cref="double"/> from the current stream
/// and advances the stream position.
/// This method reads directly from the underlying stream.
/// </summary>
/// <returns>object read from the stream</returns>
public double ReadDouble() { return mBaseReader.ReadDouble(); }
/// <summary>
/// Reads an object of type <see cref="short"/> from the current stream
/// and advances the stream position.
/// This method reads directly from the underlying stream.
/// </summary>
/// <returns>object read from the stream</returns>
public short ReadInt16() { return mBaseReader.ReadInt16(); }
/// <summary>
/// Reads an object of type <see cref="int"/> from the current stream
/// and advances the stream position.
/// This method reads directly from the underlying stream.
/// </summary>
/// <returns>object read from the stream</returns>
public int ReadInt32() { return mBaseReader.ReadInt32(); }
/// <summary>
/// Reads an object of type <see cref="long"/> from the current stream
/// and advances the stream position.
/// This method reads directly from the underlying stream.
/// </summary>
/// <returns>object read from the stream</returns>
public long ReadInt64() { return mBaseReader.ReadInt64(); }
/// <summary>
/// Reads an object of type <see cref="string"/> from the current stream
/// and advances the stream position.
/// This method reads directly from the underlying stream.
/// </summary>
/// <returns>object read from the stream</returns>
public string ReadString() { return mBaseReader.ReadString(); }
/// <summary>
/// Reads an object of type <see cref="DateTime"/> from the current stream
/// and advances the stream position.
/// This method reads directly from the underlying stream.
/// </summary>
/// <returns>object read from the stream</returns>
public DateTime ReadDateTime() { return DateTime.FromBinary(mBaseReader.ReadInt64()); }
/// <summary>
/// Reads an object of type <see cref="Guid"/> from the current stream
/// and advances the stream position.
/// This method reads directly from the underlying stream.
/// </summary>
/// <returns>object read from the stream</returns>
public Guid ReadGuid() { return new Guid(mBaseReader.ReadBytes(16)); }
/// <summary>
/// Reads the specifies number of bytes into <paramref name="buffer"/>.
/// This method reads directly from the underlying stream.
/// </summary>
/// <param name="buffer">buffer to read into</param>
/// <param name="index">starting position in the buffer</param>
/// <param name="count">number of bytes to write</param>
/// <returns>number of buffer read</returns>
public int Read(byte[] buffer, int index, int count) { return mBaseReader.Read(buffer, index, count); }
/// <summary>
/// Reads the specifies number of bytes into <paramref name="buffer"/>.
/// This method reads directly from the underlying stream.
/// </summary>
/// <param name="buffer">buffer to read into</param>
/// <param name="index">starting position in the buffer</param>
/// <param name="count">number of bytes to write</param>
/// <returns>number of chars read</returns>
public int Read(char[] buffer, int index, int count) { return mBaseReader.Read(buffer, index, count); }
/// <summary>
/// Reads an object of type <see cref="sbyte"/> from the current stream
/// and advances the stream position.
/// This method reads directly from the underlying stream.
/// </summary>
/// <returns>object read from the stream</returns>
[CLSCompliant(false)]
public sbyte ReadSByte() { return mBaseReader.ReadSByte(); }
/// <summary>
/// Reads an object of type <see cref="ushort"/> from the current stream
/// and advances the stream position.
/// This method reads directly from the underlying stream.
/// </summary>
/// <returns>object read from the stream</returns>
[CLSCompliant(false)]
public ushort ReadUInt16() { return mBaseReader.ReadUInt16(); }
/// <summary>
/// Reads an object of type <see cref="uint"/> from the current stream
/// and advances the stream position.
/// This method reads directly from the underlying stream.
/// </summary>
/// <returns>object read from the stream</returns>
[CLSCompliant(false)]
public uint ReadUInt32() { return mBaseReader.ReadUInt32(); }
/// <summary>
/// Reads an object of type <see cref="ulong"/> from the current stream
/// and advances the stream position.
/// This method reads directly from the underlying stream.
/// </summary>
/// <returns>object read from the stream</returns>
[CLSCompliant(false)]
public ulong ReadUInt64() { return mBaseReader.ReadUInt64(); }
#endregion
}
}