SamsonGame/dll_src/msgpack/MsgPackWriter.cs

322 lines
6.9 KiB
C#
Raw Permalink Normal View History

2021-12-29 20:50:11 +03:00
//
// Copyright 2011 Kazuki Oikawa, Kazunari Kida
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
using System;
using System.IO;
using System.Text;
namespace MsgPack
{
public class MsgPackWriter
{
Stream _strm;
//Encoding _encoding = Encoding.UTF8;
Encoder _encoder = Encoding.UTF8.GetEncoder ();
byte[] _tmp = new byte[9];
byte[] _buf = new byte[64];
public MsgPackWriter (Stream strm)
{
_strm = strm;
}
public 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);
}
}
public 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 (char x)
{
Write ((ushort)x);
}
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);
}
}
public 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);
}
}
public 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, 0xa0, 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 (x, false);
}
public void Write (string x, bool highProbAscii)
{
Write (x, _buf, highProbAscii);
}
public void Write (string x, byte[] buf)
{
Write (x, buf, false);
}
public void Write (string x, byte[] buf, bool highProbAscii)
{
Encoder encoder = _encoder;
//fixed (char *pstr = x)
//fixed (byte *pbuf = buf) {
char[] str = x.ToCharArray();
if (highProbAscii && x.Length <= buf.Length) {
bool isAsciiFullCompatible = true;
for (int i = 0; i < x.Length; i ++) {
//int v = (int)pstr[i];
int v = (int)(x[i]);
if (v > 0x7f) {
isAsciiFullCompatible = false;
break;
}
buf[i] = (byte)v;
}
if (isAsciiFullCompatible) {
WriteRawHeader (x.Length);
_strm.Write (buf, 0, x.Length);
return;
}
}
//WriteRawHeader (encoder.GetByteCount (pstr, x.Length, true));
WriteRawHeader (encoder.GetByteCount (str, 0, x.Length, true));
int str_len = x.Length;
//char *p = pstr;
int convertedChars, bytesUsed;
bool completed = true;
int j = 0;
while (str_len > 0 || !completed) {
//encoder.Convert (p, str_len, pbuf, buf.Length, false, out convertedChars, out bytesUsed, out completed);
encoder.Convert (str, j, str_len, buf, 0, buf.Length, false, out convertedChars, out bytesUsed, out completed);
_strm.Write (buf, 0, bytesUsed);
str_len -= convertedChars;
//p += convertedChars;
j += convertedChars;
}
//}
}
}
}