250 lines
6.8 KiB
Plaintext
250 lines
6.8 KiB
Plaintext
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Text;
|
|
using Microsoft.Singularity;
|
|
using Microsoft.SingSharp;
|
|
using Microsoft.Singularity.Channels;
|
|
|
|
namespace Smb.Shared
|
|
{
|
|
public class ByteWriter
|
|
{
|
|
byte[]! _buffer;
|
|
int _length;
|
|
int _pos;
|
|
|
|
// requires _pos >= 0;
|
|
// requires _pos <= _length;
|
|
// requires _length <= _buffer.Length;
|
|
|
|
public ByteWriter()
|
|
{
|
|
_buffer = new byte[0x100];
|
|
_length = 0;
|
|
_pos = 0;
|
|
}
|
|
|
|
public int Position
|
|
{
|
|
get { return _pos; }
|
|
set { _pos = value; }
|
|
}
|
|
|
|
public int Length
|
|
{
|
|
get
|
|
// ensures _length >= 0;
|
|
{ return _length; }
|
|
|
|
set
|
|
requires value >= 0;
|
|
{
|
|
if (value < 0)
|
|
throw new Exception("Length cannot be negative");
|
|
InsureCapacity(value);
|
|
_length = value;
|
|
}
|
|
}
|
|
|
|
public void InsureCapacity(int capacity)
|
|
requires capacity >= 0;
|
|
{
|
|
if (capacity < 0)
|
|
throw new Exception("Capacity cannot be negative");
|
|
|
|
if (capacity <= _buffer.Length)
|
|
return;
|
|
|
|
int newsize = capacity * 3 / 2 + 0x20;
|
|
byte[] newbuffer = new byte[newsize];
|
|
if (_length > 0)
|
|
Buffer.BlockCopy(_buffer, 0, newbuffer, 0, _length);
|
|
_buffer = newbuffer;
|
|
}
|
|
|
|
public void Write(byte b)
|
|
{
|
|
if (_pos < _length)
|
|
{
|
|
_buffer[_pos++] = b;
|
|
return;
|
|
}
|
|
|
|
if (_length == _buffer.Length)
|
|
InsureCapacity(_length + 1);
|
|
_buffer[_length] = b;
|
|
_length++;
|
|
_pos = _length;
|
|
}
|
|
|
|
public void WriteZero(int count)
|
|
{
|
|
if (count == 0)
|
|
return;
|
|
if (count < 0)
|
|
throw new Exception("Count cannot be negative.");
|
|
|
|
InsureCapacity(_pos + count);
|
|
for (int i = 0; i < count; i++)
|
|
_buffer[_pos + i] = 0;
|
|
_pos += count;
|
|
if (_pos > _length)
|
|
_length = _pos;
|
|
}
|
|
|
|
#if ENABLE_GENERICS
|
|
public void Write(ArraySpan<byte> span)
|
|
{
|
|
Write(span.ContainingArray, span.Offset, span.Length);
|
|
}
|
|
#else
|
|
public void Write(ArraySpan_byte span)
|
|
{
|
|
Write(span.ContainingArray, span.Offset, span.Length);
|
|
}
|
|
#endif
|
|
|
|
public void Write(byte[]! data, int offset, int length)
|
|
{
|
|
if (length == 0)
|
|
return;
|
|
if (length < 0)
|
|
throw new Exception("Length cannot be negative.");
|
|
if (offset < 0)
|
|
throw new Exception("Index cannot be negative.");
|
|
if (offset + length > data.Length)
|
|
throw new Exception("Length and offset exceed the length of the input buffer.");
|
|
|
|
InsureCapacity(_pos + length);
|
|
Buffer.BlockCopy(data, offset, _buffer, _pos, length);
|
|
_pos += length;
|
|
if (_pos > _length)
|
|
_length = _pos;
|
|
}
|
|
|
|
public void Write(ByteWriter! data)
|
|
{
|
|
Write(data._buffer, 0, data._length);
|
|
}
|
|
|
|
public void Write(byte[]! data)
|
|
{
|
|
Write(data, 0, data.Length);
|
|
}
|
|
|
|
public void WriteUInt64Le(ulong value)
|
|
{
|
|
Write((byte)(value & 0xff));
|
|
Write((byte)((value >> 0x08) & 0xff));
|
|
Write((byte)((value >> 0x10) & 0xff));
|
|
Write((byte)((value >> 0x18) & 0xff));
|
|
Write((byte)((value >> 0x20) & 0xff));
|
|
Write((byte)((value >> 0x28) & 0xff));
|
|
Write((byte)((value >> 0x30) & 0xff));
|
|
Write((byte)((value >> 0x38) & 0xff));
|
|
}
|
|
|
|
public void WriteUInt32Le(uint value)
|
|
{
|
|
Write((byte)(value & 0xff));
|
|
Write((byte)((value >> 8) & 0xff));
|
|
Write((byte)((value >> 16) & 0xff));
|
|
Write((byte)((value >> 24) & 0xff));
|
|
}
|
|
|
|
public void WriteUInt16Le(ushort value)
|
|
{
|
|
Write((byte)(value & 0xff));
|
|
Write((byte)((value >> 8) & 0xff));
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
typedef struct _STRING32 {
|
|
USHORT Length;
|
|
USHORT MaximumLength;
|
|
ULONG Buffer;
|
|
} STRING32;
|
|
typedef STRING32 *PSTRING32;
|
|
*/
|
|
|
|
// This writes a STRING32 header into the buffer at the specified position
|
|
// offset - the offset of the string data (somewhere else)
|
|
// length - the total length
|
|
public void WriteCountedHeader(int offset, int length)
|
|
{
|
|
WriteUInt16Le((ushort)length); // Length
|
|
WriteUInt16Le((ushort)length); // MaximumLength
|
|
WriteUInt16Le((ushort)offset);
|
|
WriteUInt16Le(0);
|
|
}
|
|
|
|
|
|
public byte[]! ToArray()
|
|
{
|
|
byte[]! result = new byte[_length];
|
|
Buffer.BlockCopy(_buffer, 0, result, 0, _length);
|
|
return result;
|
|
}
|
|
|
|
public byte[]! in ExHeap ToArrayEx()
|
|
{
|
|
return Bitter.FromByteArray(_buffer, 0, _length);
|
|
}
|
|
|
|
public void CopyTo(byte[]! in ExHeap dest, int dest_offset, int src_offset, int length)
|
|
requires dest_offset >= 0;
|
|
requires length >= 0;
|
|
requires dest_offset + length <= dest.Length;
|
|
requires src_offset >= 0;
|
|
requires src_offset + length <= Length;
|
|
{
|
|
Bitter.FromByteArray(dest, dest_offset, length, _buffer, 0);
|
|
}
|
|
|
|
public void CopyTo(byte[]! in ExHeap dest, int dest_offset)
|
|
requires dest_offset >= 0;
|
|
// requires dest_offset + _length <= dest.Length;
|
|
{
|
|
Bitter.FromByteArray(dest, dest_offset, _length, _buffer, 0);
|
|
}
|
|
|
|
public void WriteStringUnicode(string! text, bool terminate)
|
|
{
|
|
for (int i = 0; i < text.Length; i++) {
|
|
char c = text[i];
|
|
Write((byte)(c & 0xff));
|
|
Write((byte)(c >> 8));
|
|
}
|
|
|
|
if (terminate)
|
|
{
|
|
Write((byte)0);
|
|
Write((byte)0);
|
|
}
|
|
}
|
|
|
|
public void WriteStringAscii(string! text, bool terminate)
|
|
{
|
|
for (int i = 0; i < text.Length; i++)
|
|
{
|
|
char c = text[i];
|
|
Write((byte)(c & 0xff));
|
|
}
|
|
|
|
if (terminate)
|
|
{
|
|
Write((byte)0);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|