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) { } } }