msgpack/csharp/msgpack/MsgPackWriter.cs
2011-04-09 21:22:15 +09:00

247 lines
4.7 KiB
C#

using System;
using System.IO;
using System.Text;
namespace msgpack
{
public class MsgPackWriter
{
Stream _strm;
Encoding _encoding = Encoding.UTF8;
byte[] _tmp = new byte[9];
public MsgPackWriter (Stream strm)
{
_strm = strm;
}
void Write (byte x)
{
if (x < 128) {
_strm.WriteByte (x);
} else {
byte[] tmp = _tmp;
tmp[0] = 0xcc;
tmp[1] = x;
_strm.Write (tmp, 0, 2);
}
}
void Write (ushort x)
{
if (x < 0x100) {
Write ((byte)x);
} else {
byte[] tmp = _tmp;
tmp[0] = 0xcd;
tmp[1] = (byte)(x >> 8);
tmp[2] = (byte)x;
_strm.Write (tmp, 0, 3);
}
}
public void Write (uint x)
{
if (x < 0x10000) {
Write ((ushort)x);
} else {
byte[] tmp = _tmp;
tmp[0] = 0xce;
tmp[1] = (byte)(x >> 24);
tmp[2] = (byte)(x >> 16);
tmp[3] = (byte)(x >> 8);
tmp[4] = (byte)x;
_strm.Write (tmp, 0, 5);
}
}
public void Write (ulong x)
{
if (x < 0x100000000) {
Write ((uint)x);
} else {
byte[] tmp = _tmp;
tmp[0] = 0xcf;
tmp[1] = (byte)(x >> 56);
tmp[2] = (byte)(x >> 48);
tmp[3] = (byte)(x >> 40);
tmp[4] = (byte)(x >> 32);
tmp[5] = (byte)(x >> 24);
tmp[6] = (byte)(x >> 16);
tmp[7] = (byte)(x >> 8);
tmp[8] = (byte)x;
_strm.Write (tmp, 0, 9);
}
}
void Write (sbyte x)
{
if (x >= -32 && x <= -1) {
_strm.WriteByte ((byte)(0xe0 | (byte)x));
} else if (x >= 0 && x <= 127) {
_strm.WriteByte ((byte)x);
} else {
byte[] tmp = _tmp;
tmp[0] = 0xd0;
tmp[1] = (byte)x;
_strm.Write (tmp, 0, 2);
}
}
void Write (short x)
{
if (x >= sbyte.MinValue && x <= sbyte.MaxValue) {
Write ((sbyte)x);
} else {
byte[] tmp = _tmp;
tmp[0] = 0xd1;
tmp[1] = (byte)(x >> 8);
tmp[2] = (byte)x;
_strm.Write (tmp, 0, 3);
}
}
public void Write (int x)
{
if (x >= short.MinValue && x <= short.MaxValue) {
Write ((short)x);
} else {
byte[] tmp = _tmp;
tmp[0] = 0xd2;
tmp[1] = (byte)(x >> 24);
tmp[2] = (byte)(x >> 16);
tmp[3] = (byte)(x >> 8);
tmp[4] = (byte)x;
_strm.Write (tmp, 0, 5);
}
}
public void Write (long x)
{
if (x >= int.MinValue && x <= int.MaxValue) {
Write ((int)x);
} else {
byte[] tmp = _tmp;
tmp[0] = 0xd3;
tmp[1] = (byte)(x >> 56);
tmp[2] = (byte)(x >> 48);
tmp[3] = (byte)(x >> 40);
tmp[4] = (byte)(x >> 32);
tmp[5] = (byte)(x >> 24);
tmp[6] = (byte)(x >> 16);
tmp[7] = (byte)(x >> 8);
tmp[8] = (byte)x;
_strm.Write (tmp, 0, 9);
}
}
public void WriteNil ()
{
_strm.WriteByte (0xc0);
}
public void Write (bool x)
{
_strm.WriteByte ((byte)(x ? 0xc3 : 0xc2));
}
public void Write (float x)
{
byte[] raw = BitConverter.GetBytes (x); // unsafeコードを使う?
byte[] tmp = _tmp;
tmp[0] = 0xca;
if (BitConverter.IsLittleEndian) {
tmp[1] = raw[3];
tmp[2] = raw[2];
tmp[3] = raw[1];
tmp[4] = raw[0];
} else {
tmp[1] = raw[0];
tmp[2] = raw[1];
tmp[3] = raw[2];
tmp[4] = raw[3];
}
_strm.Write (tmp, 0, 5);
}
public void Write (double x)
{
byte[] raw = BitConverter.GetBytes (x); // unsafeコードを使う?
byte[] tmp = _tmp;
tmp[0] = 0xcb;
if (BitConverter.IsLittleEndian) {
tmp[1] = raw[7];
tmp[2] = raw[6];
tmp[3] = raw[5];
tmp[4] = raw[4];
tmp[5] = raw[3];
tmp[6] = raw[2];
tmp[7] = raw[1];
tmp[8] = raw[0];
} else {
tmp[1] = raw[0];
tmp[2] = raw[1];
tmp[3] = raw[2];
tmp[4] = raw[3];
tmp[5] = raw[4];
tmp[6] = raw[5];
tmp[7] = raw[6];
tmp[8] = raw[7];
}
_strm.Write (tmp, 0, 9);
}
public void Write (byte[] bytes)
{
WriteRawHeader (bytes.Length);
_strm.Write (bytes, 0, bytes.Length);
}
public void WriteRawHeader (int N)
{
WriteLengthHeader (N, 32, 0x96, 0xda, 0xdb);
}
public void WriteArrayHeader (int N)
{
WriteLengthHeader (N, 16, 0x90, 0xdc, 0xdd);
}
public void WriteMapHeader (int N)
{
WriteLengthHeader (N, 16, 0x80, 0xde, 0xdf);
}
void WriteLengthHeader (int N, int fix_length, byte fix_prefix, byte len16bit_prefix, byte len32bit_prefix)
{
if (N < fix_length) {
_strm.WriteByte ((byte)(fix_prefix | N));
} else {
byte[] tmp = _tmp;
int header_len;
if (N < 0x10000) {
tmp[0] = len16bit_prefix;
tmp[1] = (byte)(N >> 8);
tmp[2] = (byte)N;
header_len = 3;
} else {
tmp[0] = len32bit_prefix;
tmp[1] = (byte)(N >> 24);
tmp[2] = (byte)(N >> 16);
tmp[3] = (byte)(N >> 8);
tmp[4] = (byte)N;
header_len = 5;
}
_strm.Write (tmp, 0, header_len);
}
}
public void Write (String x)
{
Write (_encoding.GetBytes (x));
}
}
}