using System;
using System.Text;
using System.IO;
namespace FSO.Files.Utils
{
///
/// IOBuffer is a very basic wrapper over System.BinaryReader that inherits from IDisposable.
///
public class IoWriter : IDisposable, BCFWriteProxy
{
private Stream Stream;
private BinaryWriter Writer;
private bool FloatSwap = false;
public ByteOrder ByteOrder = ByteOrder.BIG_ENDIAN;
///
/// Creates a new IOBuffer instance from a stream.
///
///
public IoWriter(Stream stream)
{
this.Stream = stream;
this.Writer = new BinaryWriter(stream);
}
///
/// More to read in this stream?
///
public bool HasMore
{
get
{
return Stream.Position < Stream.Length - 1;
}
}
///
/// Skips a number of bytes in the current stream, starting from the current position.
///
/// Number of bytes to skip.
public void Skip(long numBytes)
{
Writer.BaseStream.Seek(numBytes, SeekOrigin.Current);
}
///
/// Seeks in the current stream.
///
/// Where to start from.
/// The offset to seek to.
public void Seek(SeekOrigin origin, long offset)
{
Writer.BaseStream.Seek(offset, origin);
}
///
/// Writes a variable length unsigned integer to the current stream
///
/// Value to write.
public void WriteVarLen(uint value)
{
bool first = true;
while (value > 0 || first)
{
WriteByte((byte)(((value > 127)?(uint)128:0) | (value & 127)));
value >>= 7;
first = false;
}
}
///
/// Writes an unsigned 16bit integer to the current stream.
///
/// A ushort.
public void WriteUInt16(ushort value)
{
if (ByteOrder == ByteOrder.BIG_ENDIAN)
{
value = Endian.SwapUInt16(value);
}
Writer.Write(value);
}
///
/// Writes a 16bit integer to the current stream.
///
/// A short.
public void WriteInt16(short value)
{
if (ByteOrder == ByteOrder.BIG_ENDIAN)
{
value = Endian.SwapInt16(value);
}
Writer.Write(value);
}
///
/// Writes a 32bit integer to the current stream.
///
/// An int.
public void WriteInt32(int value)
{
if (ByteOrder == ByteOrder.BIG_ENDIAN)
{
value = Endian.SwapInt32(value);
}
Writer.Write(value);
}
///
/// Writes a 32bit integer to the current stream.
///
/// An int.
public void WriteInt64(long value)
{
if (ByteOrder == ByteOrder.BIG_ENDIAN)
{
value = Endian.SwapInt64(value);
}
Writer.Write(value);
}
///
/// Writes an unsigned 32bit integer from to current stream.
///
/// A uint.
public void WriteUInt32(uint value)
{
if (ByteOrder == ByteOrder.BIG_ENDIAN)
{
value = Endian.SwapUInt32(value);
}
Writer.Write(value);
}
///
/// Writes a number of ASCII characters to the current stream.
///
/// The string to write.
/// The number of bytes to write into.
public void WriteCString(string value, int num)
{
value = value.PadRight(num, '\0');
Writer.Write(ASCIIEncoding.ASCII.GetBytes(value));
}
public void WriteCString(string value)
{
WriteCString(value, value.Length + 1);
}
///
/// Writes a byte to the current stream.
///
public void WriteByte(byte value)
{
Writer.Write(value);
}
///
/// Writes a number of bytes to the current stream.
///
/// Bytes to write out.
public void WriteBytes(byte[] bytes)
{
Writer.Write(bytes);
}
///
/// Writes a pascal string to the current stream, which is prefixed by a 16bit short.
///
public void WriteLongPascalString(string value)
{
WriteInt16((short)value.Length);
WriteBytes(Encoding.ASCII.GetBytes(value));
}
///
/// Writes a C string to the current stream.
///
public void WriteNullTerminatedString(string value)
{
if (value != null) WriteBytes(Encoding.ASCII.GetBytes(value));
WriteByte(0);
}
///
/// Writes a pascal string to the current stream.
///
public void WriteVariableLengthPascalString(string value)
{
Writer.Write((value == null)?"":value);
}
///
/// Writes a pascal string to the current stream, prefixed by a byte.
///
public void WritePascalString(string value)
{
WriteByte((byte)value.Length);
WriteBytes(Encoding.ASCII.GetBytes(value));
}
///
/// Writes a float to the current stream.
///
public void WriteFloat(float value)
{
var bytes = BitConverter.GetBytes(value);
if (ByteOrder == ByteOrder.BIG_ENDIAN && FloatSwap)
{
Array.Reverse(bytes);
}
Writer.Write(bytes);
}
#region IDisposable Members
public void Dispose()
{
}
#endregion
///
/// Creates a new IoWriter instance from a stream.
///
/// A stream.
/// A new IoWriter instance.
public static IoWriter FromStream(Stream stream)
{
return new IoWriter(stream);
}
///
/// Creates a new IoWriter instance from a stream, using a specified byte order.
///
/// A stream.
/// Byte order to use.
/// A new IoWriter instance.
public static IoWriter FromStream(Stream stream, ByteOrder order)
{
var item = FromStream(stream);
item.ByteOrder = order;
return item;
}
///
/// Creates a new IOBuffer instance from a byte array.
///
/// The byte array to use.
/// A new IOBuffer instance.
public static IoWriter FromBytes(byte[] bytes)
{
return FromStream(new MemoryStream(bytes));
}
///
/// Creates a new IOBuffer instance from a byte array, using a specified byte order.
///
/// The byte array to use.
/// Byte order to use.
/// A new IOBuffer instance.
public static IoWriter FromBytes(byte[] bytes, ByteOrder order)
{
return FromStream(new MemoryStream(bytes), order);
}
///
/// Used by BCFWriteProxy's string mode, but does not do anything here.
///
/// The size of value groups
public void SetGrouping(int groupSize)
{
}
}
}