940 lines
27 KiB
C#
940 lines
27 KiB
C#
// ----------------------------------------------------------------------------
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#if BOILER_PLATE
|
|
namespace Bartok.Marshal
|
|
{
|
|
public class CheapState {
|
|
#endif // BOILER_PLATE
|
|
private static CheapState latest;
|
|
|
|
private const uint Limit = 16;
|
|
|
|
public CheapState(int indent)
|
|
{
|
|
used = 0;
|
|
read = 0;
|
|
this.indent = indent;
|
|
|
|
loadPtrs = new object[128 * 1024];
|
|
|
|
regionSize = 8 * 1024 * 1024;
|
|
region = VirtualAlloc(0, regionSize, MEM_COMMIT, PAGE_READWRITE);
|
|
Console.WriteLine("Region = {0:x8}", region);
|
|
|
|
latest = this;
|
|
}
|
|
|
|
public CheapState(CheapState other)
|
|
{
|
|
region = other.region;
|
|
regionSize = other.regionSize;
|
|
|
|
used = 0;
|
|
read = 0;
|
|
indent = 0;
|
|
|
|
loadPtrs = new object[16 * 1024];
|
|
|
|
latest = this;
|
|
}
|
|
|
|
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError=true)]
|
|
private static extern uint VirtualAlloc(uint lpAddress,
|
|
uint dwSize,
|
|
uint flAllocationType,
|
|
uint flProtect);
|
|
private const uint MEM_COMMIT = 0x1000;
|
|
private const uint PAGE_READWRITE = 0x04;
|
|
|
|
private uint region;
|
|
private uint regionSize;
|
|
|
|
private uint used;
|
|
private uint read;
|
|
|
|
private ObjectIDGenerator oig;
|
|
|
|
private object[] loadPtrs;
|
|
private uint loadCount;
|
|
|
|
private uint usedTrace;
|
|
private uint readTrace;
|
|
private int indent;
|
|
|
|
public static System.Collections.Hashtable writeHash;
|
|
public static System.Collections.Hashtable readHash;
|
|
|
|
public void WriteOpen()
|
|
{
|
|
oig = new ObjectIDGenerator();
|
|
#if false
|
|
unsafe {
|
|
byte *ptr = (byte *)region;
|
|
for (uint i = 0; i < used; i++) {
|
|
ptr[i] = 0xdd;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
used = 0;
|
|
usedTrace = 0;
|
|
indent = 0;
|
|
|
|
WriteRaw(used);
|
|
TraceWrite("Zero Buffer Size");
|
|
}
|
|
|
|
public void WriteClose()
|
|
{
|
|
unsafe {
|
|
uint * p = (uint *)region;
|
|
*p = used;
|
|
}
|
|
Trace(0, 4, "Wrote Buffer Size: {0}", used);
|
|
used = 0;
|
|
read = 0;
|
|
}
|
|
|
|
public void ReadOpen()
|
|
{
|
|
read = 0;
|
|
readTrace = 0;
|
|
indent = 0;
|
|
|
|
#if false
|
|
for (uint i = 0; i < loadCount; i++) {
|
|
loadPtrs[i] = null;
|
|
}
|
|
#endif
|
|
loadPtrs[0] = null;
|
|
loadCount = 1;
|
|
|
|
used = 4; // set to 4 so our read don't fail.
|
|
ReadRaw(out used);
|
|
TraceRead("Read Buffer Size: {0}", used);
|
|
}
|
|
|
|
public void ReadClose()
|
|
{
|
|
if (used != read) {
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
read = 0;
|
|
used = 0;
|
|
}
|
|
|
|
[System.Diagnostics.Conditional("TRACE_CHEAP_STATE")]
|
|
public void Trace(uint offset, uint size, string text)
|
|
{
|
|
if (offset > Limit) {
|
|
return;
|
|
}
|
|
|
|
#if !USE_DOT_INDENT
|
|
Console.Write("{0,8:d}: {1}{2}", offset, new String('.', indent), text);
|
|
if (indent + text.Length < 32) {
|
|
Console.Write(new String(' ', 32 - (indent + text.Length)));
|
|
}
|
|
#else
|
|
Console.Write("{0,8:d}: {1,3} {2,-20} ", offset, indent, text);
|
|
#endif
|
|
if (size > 0) {
|
|
if (offset + size > regionSize) {
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
for (uint i = 0; i < size; i++) {
|
|
unsafe {
|
|
byte *p = (byte *)region + offset + i;
|
|
Console.Write("{0:x2}", *p);
|
|
}
|
|
}
|
|
}
|
|
Console.WriteLine();
|
|
}
|
|
|
|
[System.Diagnostics.Conditional("TRACE_CHEAP_STATE")]
|
|
public void Trace(uint offset, uint size, string text, params object[] args)
|
|
{
|
|
Trace(offset, size, String.Format(text, args));
|
|
}
|
|
|
|
[System.Diagnostics.Conditional("TRACE_CHEAP_STATE")]
|
|
public void TraceRead(string text)
|
|
{
|
|
uint offset = readTrace;
|
|
uint size = read - readTrace;
|
|
readTrace = read;
|
|
|
|
Trace(offset, size, text);
|
|
}
|
|
|
|
[System.Diagnostics.Conditional("TRACE_CHEAP_STATE")]
|
|
public void TraceRead(string text, params object[] args)
|
|
{
|
|
TraceRead(String.Format(text, args));
|
|
}
|
|
|
|
[System.Diagnostics.Conditional("TRACE_CHEAP_STATE")]
|
|
public void TraceWrite(string text)
|
|
{
|
|
uint offset = usedTrace;
|
|
uint size = used - usedTrace;
|
|
usedTrace = used;
|
|
|
|
Trace(offset, size, text);
|
|
}
|
|
|
|
[System.Diagnostics.Conditional("TRACE_CHEAP_STATE")]
|
|
public void TraceWrite(string text, params object[] args)
|
|
{
|
|
TraceWrite(String.Format(text, args));
|
|
}
|
|
|
|
[System.Diagnostics.Conditional("TRACE_CHEAP_STATE")]
|
|
public void Trace(string text)
|
|
{
|
|
if (read == 0 && used > Limit) {
|
|
return;
|
|
}
|
|
else if (read > Limit) {
|
|
return;
|
|
}
|
|
|
|
#if !USE_DOT_INDENT
|
|
Console.WriteLine(" : {0}{1}", new String('.', indent), text);
|
|
#else
|
|
Console.WriteLine(" : {0,3} {1}", indent, text);
|
|
#endif
|
|
}
|
|
|
|
[System.Diagnostics.Conditional("TRACE_CHEAP_STATE")]
|
|
public void Trace(string text, params object[] args)
|
|
{
|
|
Trace(String.Format(text, args));
|
|
}
|
|
|
|
[System.Diagnostics.Conditional("TRACE_CHEAP_STATE")]
|
|
public void Trace()
|
|
{
|
|
Console.WriteLine();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
public bool SavePtr(uint id, object ptr)
|
|
{
|
|
bool first;
|
|
long oid = oig.GetId(ptr, out first);
|
|
if (!first) {
|
|
id |= 0x8000;
|
|
WriteType(id);
|
|
WriteRaw(unchecked((uint)oid));
|
|
TraceWrite("** pointer {0} of 0x{1:x}", oid, id);;
|
|
WriteTypeEnd(id);
|
|
return false; // already marshaled.
|
|
}
|
|
else {
|
|
TraceWrite("** Save pointer: {0} of 0x{1:x}", oid, id);;
|
|
}
|
|
return true; // needs to be marshaled.
|
|
}
|
|
|
|
// Remember the pointer as we unmarshal an object.
|
|
public uint AddPtr(object ptr, uint id)
|
|
{
|
|
loadPtrs[loadCount] = ptr;
|
|
Trace(read, 0, "** Load pointer: {0} of 0x{1:x}", loadCount, id);
|
|
return loadCount++;
|
|
}
|
|
|
|
// Only a pointer was saved because the object was already unmarshaled.
|
|
public object LoadPtr(uint id)
|
|
{
|
|
if ((id & 0x8000) == 0) {
|
|
throw new Exception("Bad id for pointer: " + id);
|
|
}
|
|
uint pi;
|
|
ReadRaw(out pi);
|
|
TraceRead("** pointer {0} of 0x{1:x}", pi, id);
|
|
ReadTypeEnd(id);
|
|
|
|
if (pi == 0 || pi > loadCount) {
|
|
throw new Exception("Unexpected object pi: " + pi);
|
|
}
|
|
return loadPtrs[pi];
|
|
}
|
|
|
|
public void WriteRaw(ulong u)
|
|
{
|
|
unsafe {
|
|
if (used + sizeof(ulong) > regionSize) {
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
byte *p = (byte *)region + used;
|
|
*((ulong *)p) = u;
|
|
used += sizeof(ulong);
|
|
}
|
|
}
|
|
|
|
public void WriteRaw(uint u)
|
|
{
|
|
unsafe {
|
|
if (used + sizeof(uint) > regionSize) {
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
byte *p = (byte *)region + used;
|
|
*((uint *)p) = u;
|
|
used += sizeof(uint);
|
|
}
|
|
}
|
|
|
|
public void WriteRaw(ushort u)
|
|
{
|
|
unsafe {
|
|
if (used + sizeof(ushort) > regionSize) {
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
byte *p = (byte *)region + used;
|
|
*((ushort *)p) = u;
|
|
used += sizeof(ushort);
|
|
}
|
|
}
|
|
|
|
public void WriteRaw(byte u)
|
|
{
|
|
unsafe {
|
|
if (used + sizeof(byte) > regionSize) {
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
byte *p = (byte *)region + used;
|
|
*((byte *)p) = u;
|
|
used += sizeof(byte);
|
|
}
|
|
}
|
|
|
|
public void ReadRaw(out ulong u)
|
|
{
|
|
unsafe {
|
|
if (read + sizeof(ulong) > used) {
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
byte *p = (byte *)region + read;
|
|
u = *((ulong *)p);
|
|
read += sizeof(ulong);
|
|
}
|
|
}
|
|
|
|
public void ReadRaw(out uint u)
|
|
{
|
|
unsafe {
|
|
if (read + sizeof(uint) > used) {
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
byte *p = (byte *)region + read;
|
|
u = *((uint *)p);
|
|
read += sizeof(uint);
|
|
}
|
|
}
|
|
|
|
public void ReadRaw(out ushort u)
|
|
{
|
|
unsafe {
|
|
if (read + sizeof(ushort) > used) {
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
byte *p = (byte *)region + read;
|
|
u = *((ushort *)p);
|
|
read += sizeof(ushort);
|
|
}
|
|
}
|
|
|
|
public void ReadRaw(out byte u)
|
|
{
|
|
unsafe {
|
|
if (read + sizeof(byte) > used) {
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
byte *p = (byte *)region + read;
|
|
u = *((byte *)p);
|
|
read += sizeof(byte);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
public void WriteType(uint type)
|
|
{
|
|
WriteRaw(type | 0xbbbb0000);
|
|
TraceWrite("WriteType 0x{0:x}", type);
|
|
if (type != 0) {
|
|
indent++;
|
|
}
|
|
}
|
|
|
|
public void WriteTypeEnd(uint type)
|
|
{
|
|
if (type == 0) {
|
|
throw new Exception("Null type can be an end.");
|
|
}
|
|
indent--;
|
|
WriteRaw(type | 0xeeee0000);
|
|
TraceWrite("WriteTypeEnd 0x{0:x}", type);
|
|
}
|
|
|
|
public uint ReadType()
|
|
{
|
|
uint type;
|
|
ReadRaw(out type);
|
|
TraceRead("ReadType ~0x{0:x}", (type & 0xffff));
|
|
if ((type & 0xffff0000) != 0xbbbb0000) {
|
|
throw new Exception("Missing beg type");
|
|
}
|
|
type &= 0x0000ffff;
|
|
|
|
if (type != 0) {
|
|
indent++;
|
|
}
|
|
return type;
|
|
}
|
|
|
|
public uint ReadType(uint id)
|
|
{
|
|
uint type;
|
|
ReadRaw(out type);
|
|
TraceRead("ReadType 0x{0:x}", id);
|
|
if ((type & 0xffff0000) != 0xbbbb0000) {
|
|
throw new Exception("Missing beg type");
|
|
}
|
|
type &= 0x0000ffff;
|
|
|
|
if (type != 0) {
|
|
indent++;
|
|
}
|
|
if (type != id) {
|
|
throw new Exception("Invalid beg type");
|
|
}
|
|
return type;
|
|
}
|
|
|
|
public uint ReadTypeOrNull(uint id)
|
|
{
|
|
uint type;
|
|
ReadRaw(out type);
|
|
TraceRead("ReadTypeOrNull 0x{0:x}", id);
|
|
if ((type & 0xffff0000) != 0xbbbb0000) {
|
|
throw new Exception("Missing beg type");
|
|
}
|
|
type &= 0x0000ffff;
|
|
|
|
if (type == 0) {
|
|
return 0;
|
|
}
|
|
else if (type == id || type == (id | 0x8000)) {
|
|
indent++;
|
|
return type;
|
|
}
|
|
else {
|
|
throw new Exception("Invalid beg type");
|
|
}
|
|
}
|
|
|
|
public void ReadTypeEnd(uint id)
|
|
{
|
|
uint type;
|
|
indent--;
|
|
ReadRaw(out type);
|
|
TraceRead("ReadTypeEnd 0x{0:x}", id);
|
|
if ((type & 0xffff0000) != 0xeeee0000) {
|
|
throw new Exception("Missing end type");
|
|
}
|
|
type &= 0x0000ffff;
|
|
|
|
if (id != 0 && type != id) {
|
|
throw new Exception("Invalid end type");
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
public void Write(bool value)
|
|
{
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
WriteType((uint)Types.Bool);
|
|
#endif
|
|
if (value) {
|
|
WriteRaw(unchecked((byte)1));
|
|
TraceWrite("true");
|
|
}
|
|
else {
|
|
WriteRaw(unchecked((byte)0));
|
|
TraceWrite("false");
|
|
}
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
WriteTypeEnd((uint)Types.Bool);
|
|
#endif
|
|
}
|
|
|
|
public void Read(out bool value)
|
|
{
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
ReadType((uint)Types.Bool);
|
|
#endif
|
|
byte t;
|
|
ReadRaw(out t);
|
|
TraceRead("bool");
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
ReadTypeEnd((uint)Types.Bool);
|
|
#endif
|
|
value = (t != 0);
|
|
}
|
|
|
|
public void CheapRead(out bool value)
|
|
{
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
ReadType((uint)Types.Bool);
|
|
#endif
|
|
byte t;
|
|
ReadRaw(out t);
|
|
TraceRead("bool");
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
ReadTypeEnd((uint)Types.Bool);
|
|
#endif
|
|
value = (t != 0);
|
|
}
|
|
|
|
public void Write(sbyte value)
|
|
{
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
WriteType((uint)Types.Sbyte);
|
|
#endif
|
|
WriteRaw(unchecked((byte)value));
|
|
TraceWrite("sbyte");
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
WriteTypeEnd((uint)Types.Sbyte);
|
|
#endif
|
|
}
|
|
|
|
public void Read(out sbyte value)
|
|
{
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
ReadType((uint)Types.Sbyte);
|
|
#endif
|
|
byte t;
|
|
ReadRaw(out t);
|
|
TraceRead("sbyte");
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
ReadTypeEnd((uint)Types.Sbyte);
|
|
#endif
|
|
value = unchecked((sbyte)t);
|
|
}
|
|
|
|
public void Write(byte value)
|
|
{
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
WriteType((uint)Types.Byte);
|
|
#endif
|
|
WriteRaw(value);
|
|
TraceWrite("byte");
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
WriteTypeEnd((uint)Types.Byte);
|
|
#endif
|
|
}
|
|
|
|
public void Read(out byte value)
|
|
{
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
ReadType((uint)Types.Byte);
|
|
#endif
|
|
ReadRaw(out value);
|
|
TraceRead("byte");
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
ReadTypeEnd((uint)Types.Byte);
|
|
#endif
|
|
}
|
|
|
|
public void Write(short value)
|
|
{
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
WriteType((uint)Types.Short);
|
|
#endif
|
|
WriteRaw(unchecked((ushort)value));
|
|
TraceWrite("short");
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
WriteTypeEnd((uint)Types.Short);
|
|
#endif
|
|
}
|
|
|
|
public void Read(out short value)
|
|
{
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
ReadType((uint)Types.Short);
|
|
#endif
|
|
ushort t;
|
|
ReadRaw(out t);
|
|
TraceRead("short");
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
ReadTypeEnd((uint)Types.Short);
|
|
#endif
|
|
value = unchecked((short)t);
|
|
}
|
|
|
|
public void Write(char value)
|
|
{
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
WriteType((uint)Types.Char);
|
|
#endif
|
|
WriteRaw(unchecked((ushort)value));
|
|
TraceWrite("char");
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
WriteTypeEnd((uint)Types.Char);
|
|
#endif
|
|
}
|
|
|
|
public void Read(out char value)
|
|
{
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
ReadType((uint)Types.Char);
|
|
#endif
|
|
ushort t;
|
|
ReadRaw(out t);
|
|
TraceRead("char");
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
ReadTypeEnd((uint)Types.Char);
|
|
#endif
|
|
value = unchecked((char)t);
|
|
}
|
|
|
|
public void Write(ushort value)
|
|
{
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
WriteType((uint)Types.Ushort);
|
|
#endif
|
|
WriteRaw(value);
|
|
TraceWrite("ushort");
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
WriteTypeEnd((uint)Types.Ushort);
|
|
#endif
|
|
}
|
|
|
|
public void Read(out ushort value)
|
|
{
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
ReadType((uint)Types.Ushort);
|
|
#endif
|
|
ReadRaw(out value);
|
|
TraceRead("ushort");
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
ReadTypeEnd((uint)Types.Ushort);
|
|
#endif
|
|
}
|
|
|
|
public void Write(int value)
|
|
{
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
WriteType((uint)Types.Int);
|
|
#endif
|
|
WriteRaw(unchecked((uint)value));
|
|
TraceWrite("int");
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
WriteTypeEnd((uint)Types.Int);
|
|
#endif
|
|
}
|
|
|
|
public void Read(out int value)
|
|
{
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
ReadType((uint)Types.Int);
|
|
#endif
|
|
uint t;
|
|
ReadRaw(out t);
|
|
TraceRead("int");
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
ReadTypeEnd((uint)Types.Int);
|
|
#endif
|
|
value = unchecked((int)t);
|
|
}
|
|
|
|
public void Write(uint value)
|
|
{
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
WriteType((uint)Types.Uint);
|
|
#endif
|
|
WriteRaw(value);
|
|
TraceWrite("uint");
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
WriteTypeEnd((uint)Types.Uint);
|
|
#endif
|
|
}
|
|
|
|
public void Read(out uint value)
|
|
{
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
ReadType((uint)Types.Uint);
|
|
#endif
|
|
ReadRaw(out value);
|
|
TraceRead("uint");
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
ReadTypeEnd((uint)Types.Uint);
|
|
#endif
|
|
}
|
|
|
|
public void Write(long value)
|
|
{
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
WriteType((uint)Types.Long);
|
|
#endif
|
|
WriteRaw(unchecked((ulong)value));
|
|
TraceWrite("long");
|
|
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
WriteTypeEnd((uint)Types.Long);
|
|
#endif
|
|
}
|
|
|
|
public void Read(out long value)
|
|
{
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
ReadType((uint)Types.Long);
|
|
#endif
|
|
ulong t;
|
|
ReadRaw(out t);
|
|
TraceRead("long");
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
ReadTypeEnd((uint)Types.Long);
|
|
#endif
|
|
value = unchecked((long)t);
|
|
}
|
|
|
|
public void Write(ulong value)
|
|
{
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
WriteType((uint)Types.Ulong);
|
|
#endif
|
|
WriteRaw(value);
|
|
TraceWrite("ulong");
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
WriteTypeEnd((uint)Types.Ulong);
|
|
#endif
|
|
}
|
|
|
|
public void Read(out ulong value)
|
|
{
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
ReadType((uint)Types.Ulong);
|
|
#endif
|
|
ReadRaw(out value);
|
|
TraceRead("ulong");
|
|
#if USE_TYPE_IDS_ON_VALUES
|
|
ReadTypeEnd((uint)Types.Ulong);
|
|
#endif
|
|
}
|
|
|
|
public void Write(string value)
|
|
{
|
|
if (value == null) {
|
|
WriteType(0);
|
|
}
|
|
else if (SavePtr((uint)Types.String, value)) {
|
|
int len = value.Length;
|
|
WriteType((uint)Types.String);
|
|
WriteRaw(unchecked((uint)len));
|
|
for (int i = 0; i < len; i++) {
|
|
WriteRaw(unchecked((ushort)value[i]));
|
|
}
|
|
TraceWrite("string");
|
|
WriteTypeEnd((uint)Types.String);
|
|
}
|
|
}
|
|
|
|
public void Read(out string value)
|
|
{
|
|
uint id = ReadTypeOrNull((uint)Types.String);
|
|
if ((id & 0x8000) != 0) {
|
|
value = (string)LoadPtr(id);
|
|
}
|
|
else if (id != 0) {
|
|
uint len;
|
|
ReadRaw(out len);
|
|
char[] ta = new char [len];
|
|
for (uint i = 0; i < len; i++) {
|
|
ushort t;
|
|
ReadRaw(out t);
|
|
ta[i] = unchecked((char)t);
|
|
}
|
|
TraceRead("string");
|
|
ReadTypeEnd((uint)Types.String);
|
|
value = new String(ta);
|
|
AddPtr(value, (uint)Types.String);
|
|
}
|
|
else {
|
|
value = null;
|
|
}
|
|
}
|
|
|
|
public void Write(object[] value) {
|
|
Trace("Write object[]");
|
|
if (value == null) {
|
|
WriteType(0);
|
|
}
|
|
else if (SavePtr((uint)Types.ObjectArray, value)) {
|
|
WriteType((uint)Types.ObjectArray);
|
|
WriteRaw((uint)value.Length);
|
|
TraceWrite("[].Length");
|
|
for (int i = 0; i < value.Length; i++) {
|
|
if (value[i] == null) {
|
|
WriteType(0);
|
|
}
|
|
else {
|
|
Write(value[i]);
|
|
}
|
|
}
|
|
WriteTypeEnd((uint)Types.ObjectArray);
|
|
}
|
|
}
|
|
|
|
public void Read(out object[] value) {
|
|
Trace("Read object[] [outer]");
|
|
uint id = ReadTypeOrNull((uint)Types.ObjectArray);
|
|
if ((id & 0x8000) != 0) {
|
|
value = (object[])LoadPtr(id);
|
|
}
|
|
else if (id != 0) {
|
|
uint len;
|
|
ReadRaw(out len);
|
|
TraceRead("[].Length");
|
|
value = new object [len];
|
|
AddPtr(value, (uint)Types.ObjectArray);
|
|
for (int i = 0; i < len; i++) {
|
|
Read(out value[i]);
|
|
}
|
|
ReadTypeEnd((uint)Types.ObjectArray);
|
|
}
|
|
else {
|
|
value = null;
|
|
}
|
|
}
|
|
|
|
public void Write(int[] value) {
|
|
Trace("Write int[]");
|
|
if (value == null) {
|
|
WriteType(0);
|
|
}
|
|
else if (SavePtr((uint)Types.IntArray, value)) {
|
|
WriteType((uint)Types.IntArray);
|
|
WriteRaw((uint)value.Length);
|
|
for (int i = 0; i < value.Length; i++) {
|
|
WriteRaw(unchecked((uint)value[i]));
|
|
}
|
|
TraceWrite("[]");
|
|
WriteTypeEnd((uint)Types.IntArray);
|
|
}
|
|
}
|
|
|
|
public void Read(out int[] value) {
|
|
Trace("Read int[] [outer]");
|
|
uint id = ReadTypeOrNull((uint)Types.IntArray);
|
|
if ((id & 0x8000) != 0) {
|
|
value = (int[])LoadPtr(id);
|
|
}
|
|
else if (id != 0) {
|
|
uint len;
|
|
ReadRaw(out len);
|
|
value = new int [len];
|
|
AddPtr(value, (uint)Types.IntArray);
|
|
for (int i = 0; i < len; i++) {
|
|
uint v;
|
|
ReadRaw(out v);
|
|
value[i] = unchecked((int)v);
|
|
}
|
|
TraceRead("[]");
|
|
ReadTypeEnd((uint)Types.IntArray);
|
|
}
|
|
else {
|
|
value = null;
|
|
}
|
|
}
|
|
|
|
public void Write(uint[] value) {
|
|
Trace("Write uint[]");
|
|
if (value == null) {
|
|
WriteType(0);
|
|
}
|
|
else if (SavePtr((uint)Types.UintArray, value)) {
|
|
WriteType((uint)Types.UintArray);
|
|
WriteRaw((uint)value.Length);
|
|
for (int i = 0; i < value.Length; i++) {
|
|
WriteRaw(value[i]);
|
|
}
|
|
TraceWrite("[]");
|
|
WriteTypeEnd((uint)Types.UintArray);
|
|
}
|
|
}
|
|
|
|
public void Read(out uint[] value) {
|
|
Trace("Read uint[] [outer]");
|
|
uint id = ReadTypeOrNull((uint)Types.UintArray);
|
|
if ((id & 0x8000) != 0) {
|
|
value = (uint[])LoadPtr(id);
|
|
}
|
|
else if (id != 0) {
|
|
uint len;
|
|
ReadRaw(out len);
|
|
value = new uint [len];
|
|
AddPtr(value, (uint)Types.UintArray);
|
|
for (int i = 0; i < len; i++) {
|
|
ReadRaw(out value[i]);
|
|
}
|
|
TraceRead("[]");
|
|
ReadTypeEnd((uint)Types.UintArray);
|
|
}
|
|
else {
|
|
value = null;
|
|
}
|
|
}
|
|
|
|
public void Write(object value)
|
|
{
|
|
Trace("Write object");
|
|
if (value == null) {
|
|
WriteType(0);
|
|
}
|
|
else {
|
|
CheapWriteDelegate wd = writeHash[value.GetType()] as CheapWriteDelegate;
|
|
if (wd != null) {
|
|
wd(this, value);
|
|
}
|
|
else {
|
|
throw new Exception("Unknown type " + value.GetType());
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Read(out object value)
|
|
{
|
|
Trace("Read object");
|
|
uint __id = ReadType();
|
|
if (__id == 0) {
|
|
value = null;
|
|
return;
|
|
}
|
|
if ((__id & 0x8000) != 0) {
|
|
value = LoadPtr(__id);
|
|
return;
|
|
}
|
|
|
|
CheapReadDelegate rd = readHash[(uint)(__id & 0x7fff)] as CheapReadDelegate;
|
|
if (rd != null) {
|
|
value = rd(__id, this);
|
|
return;
|
|
}
|
|
throw new Exception("Unknown type id " + __id);
|
|
}
|
|
#if BOILER_PLATE
|
|
} // class
|
|
} // namespace
|
|
#endif // BOILER_PLATE
|