msgpack/csharp/msgpack/MsgPackReader.cs
2011-04-09 21:17:05 +09:00

170 lines
4.9 KiB
C#

using System;
using System.IO;
namespace msgpack
{
public class MsgPackReader
{
Stream _strm;
byte[] _tmp0 = new byte[8];
byte[] _tmp1 = new byte[8];
public MsgPackReader (Stream strm)
{
_strm = strm;
}
public TypePrefixes Type { get; private set; }
public bool ValueBoolean { get; private set; }
public uint Length { get; private set; }
public uint ValueUnsigned { get; private set; }
public ulong ValueUnsigned64 { get; private set; }
public int ValueSigned { get; private set; }
public long ValueSigned64 { get; private set; }
public float ValueFloat { get; private set; }
public double ValueDouble { get; private set; }
public bool Read ()
{
byte[] tmp0 = _tmp0, tmp1 = _tmp1;
int x = _strm.ReadByte ();
if (x < 0)
return false; // EOS
if (x >= 0x00 && x <= 0x7f) {
this.Type = TypePrefixes.PositiveFixNum;
} else if (x >= 0xe0 && x <= 0xff) {
this.Type = TypePrefixes.NegativeFixNum;
} else if (x >= 0xa0 && x <= 0xbf) {
this.Type = TypePrefixes.FixRaw;
} else if (x >= 0x90 && x <= 0x9f) {
this.Type = TypePrefixes.FixArray;
} else if (x >= 0x80 && x <= 0x8f) {
this.Type = TypePrefixes.FixMap;
} else {
this.Type = (TypePrefixes)x;
}
switch (this.Type) {
case TypePrefixes.Nil:
break;
case TypePrefixes.False:
ValueBoolean = false;
break;
case TypePrefixes.True:
ValueBoolean = true;
break;
case TypePrefixes.Float:
_strm.Read (tmp0, 0, 4);
if (BitConverter.IsLittleEndian) {
tmp1[0] = tmp0[3];
tmp1[1] = tmp0[2];
tmp1[2] = tmp0[1];
tmp1[3] = tmp0[0];
ValueFloat = BitConverter.ToSingle (tmp1, 0);
} else {
ValueFloat = BitConverter.ToSingle (tmp0, 0);
}
break;
case TypePrefixes.Double:
_strm.Read (tmp0, 0, 8);
if (BitConverter.IsLittleEndian) {
tmp1[0] = tmp0[7];
tmp1[1] = tmp0[6];
tmp1[2] = tmp0[5];
tmp1[3] = tmp0[4];
tmp1[4] = tmp0[3];
tmp1[5] = tmp0[2];
tmp1[6] = tmp0[1];
tmp1[7] = tmp0[0];
ValueDouble = BitConverter.ToDouble (tmp1, 0);
} else {
ValueDouble = BitConverter.ToDouble (tmp0, 0);
}
break;
case TypePrefixes.NegativeFixNum:
ValueSigned = (x & 0x1f) - 0x20;
break;
case TypePrefixes.PositiveFixNum:
ValueSigned = x & 0x7f;
break;
case TypePrefixes.UInt8:
x = _strm.ReadByte ();
if (x < 0)
throw new FormatException ();
ValueUnsigned = (uint)x;
break;
case TypePrefixes.UInt16:
if (_strm.Read (tmp0, 0, 2) != 2)
throw new FormatException ();
ValueUnsigned = ((uint)tmp0[0] << 8) | (uint)tmp0[1];
break;
case TypePrefixes.UInt32:
if (_strm.Read (tmp0, 0, 4) != 4)
throw new FormatException ();
ValueUnsigned = ((uint)tmp0[0] << 24) | ((uint)tmp0[1] << 16) | ((uint)tmp0[2] << 8) | (uint)tmp0[3];
break;
case TypePrefixes.UInt64:
if (_strm.Read (tmp0, 0, 8) != 8)
throw new FormatException ();
ValueUnsigned64 = ((ulong)tmp0[0] << 56) | ((ulong)tmp0[1] << 48) | ((ulong)tmp0[2] << 40) | ((ulong)tmp0[3] << 32) | ((ulong)tmp0[4] << 24) | ((ulong)tmp0[5] << 16) | ((ulong)tmp0[6] << 8) | (ulong)tmp0[7];
break;
case TypePrefixes.Int8:
x = _strm.ReadByte ();
if (x < 0)
throw new FormatException ();
ValueSigned = (sbyte)x;
break;
case TypePrefixes.Int16:
if (_strm.Read (tmp0, 0, 2) != 2)
throw new FormatException ();
ValueSigned = (short)((tmp0[0] << 8) | tmp0[1]);
break;
case TypePrefixes.Int32:
if (_strm.Read (tmp0, 0, 4) != 4)
throw new FormatException ();
ValueSigned = (tmp0[0] << 24) | (tmp0[1] << 16) | (tmp0[2] << 8) | tmp0[3];
break;
case TypePrefixes.Int64:
if (_strm.Read (tmp0, 0, 8) != 8)
throw new FormatException ();
ValueSigned64 = ((long)tmp0[0] << 56) | ((long)tmp0[1] << 48) | ((long)tmp0[2] << 40) | ((long)tmp0[3] << 32) | ((long)tmp0[4] << 24) | ((long)tmp0[5] << 16) | ((long)tmp0[6] << 8) | (long)tmp0[7];
break;
case TypePrefixes.FixRaw:
Length = (uint)(x & 0x1f);
break;
case TypePrefixes.FixArray:
case TypePrefixes.FixMap:
Length = (uint)(x & 0xf);
break;
case TypePrefixes.Raw16:
case TypePrefixes.Array16:
case TypePrefixes.Map16:
if (_strm.Read (tmp0, 0, 2) != 2)
throw new FormatException ();
Length = ((uint)tmp0[0] << 8) | (uint)tmp0[1];
break;
case TypePrefixes.Raw32:
case TypePrefixes.Array32:
case TypePrefixes.Map32:
if (_strm.Read (tmp0, 0, 4) != 4)
throw new FormatException ();
Length = ((uint)tmp0[0] << 24) | ((uint)tmp0[1] << 16) | ((uint)tmp0[2] << 8) | (uint)tmp0[3];
break;
default:
throw new FormatException ();
}
return true;
}
public int ReadValueRaw (byte[] buf, int offset, int count)
{
return _strm.Read (buf, offset, count);
}
}
}