123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- using System;
- using System.Collections;
- using System.Text;
- namespace XGame.Framework.Serialization
- {
- public class Writer : IWriter
- {
- private const int DefaultLength = 2048;
- private byte[] _buffer;
- private int _size;
- public Writer()
- {
- _buffer = new byte[DefaultLength];
- _size = 0;
- }
- public void Write(bool value)
- {
- var bytes = BitConverter.GetBytes(value);
- var length = bytes.Length;
- if (_size + length >= _buffer.Length)
- AllocateMore();
- Buffer.BlockCopy(bytes, 0, _buffer, _size, length);
- _size += length;
- }
- public void Write(sbyte value)
- {
- var bytes = BitConverter.GetBytes(value);
- var length = bytes.Length;
- if (_size + length >= _buffer.Length)
- AllocateMore();
- Buffer.BlockCopy(bytes, 0, _buffer, _size, length);
- _size += length;
- }
- public void Write(byte value)
- {
- var bytes = BitConverter.GetBytes(value);
- var length = bytes.Length;
- if (_size + length >= _buffer.Length)
- AllocateMore();
- Buffer.BlockCopy(bytes, 0, _buffer, _size, length);
- _size += length;
- }
- public void Write(short value)
- {
- var bytes = BitConverter.GetBytes(value);
- var length = bytes.Length;
- if (_size + length >= _buffer.Length)
- AllocateMore();
- Buffer.BlockCopy(bytes, 0, _buffer, _size, length);
- _size += length;
- }
- public void Write(ushort value)
- {
- var bytes = BitConverter.GetBytes(value);
- var length = bytes.Length;
- if (_size + length >= _buffer.Length)
- AllocateMore();
- Buffer.BlockCopy(bytes, 0, _buffer, _size, length);
- _size += length;
- }
- public void Write(int value)
- {
- var bytes = BitConverter.GetBytes(value);
- var length = bytes.Length;
- if (_size + length >= _buffer.Length)
- AllocateMore();
- Buffer.BlockCopy(bytes, 0, _buffer, _size, length);
- _size += length;
- }
- public void Write(uint value)
- {
- var bytes = BitConverter.GetBytes(value);
- var length = bytes.Length;
- if (_size + length >= _buffer.Length)
- AllocateMore();
- Buffer.BlockCopy(bytes, 0, _buffer, _size, length);
- _size += length;
- }
- public void Write(long value)
- {
- var bytes = BitConverter.GetBytes(value);
- var length = bytes.Length;
- if (_size + length >= _buffer.Length)
- AllocateMore();
- Buffer.BlockCopy(bytes, 0, _buffer, _size, length);
- _size += length;
- }
- public void Write(ulong value)
- {
- var bytes = BitConverter.GetBytes(value);
- var length = bytes.Length;
- if (_size + length >= _buffer.Length)
- AllocateMore();
- Buffer.BlockCopy(bytes, 0, _buffer, _size, length);
- _size += length;
- }
- public void Write(float value)
- {
- var bytes = BitConverter.GetBytes(value);
- var length = bytes.Length;
- if (_size + length >= _buffer.Length)
- AllocateMore();
- Buffer.BlockCopy(bytes, 0, _buffer, _size, length);
- _size += length;
- }
- public void Write(double value)
- {
- var bytes = BitConverter.GetBytes(value);
- var length = bytes.Length;
- if (_size + length >= _buffer.Length)
- AllocateMore();
- Buffer.BlockCopy(bytes, 0, _buffer, _size, length);
- _size += length;
- }
- public void Write(char value)
- {
- var bytes = BitConverter.GetBytes(value);
- var length = bytes.Length;
- if (_size + length >= _buffer.Length)
- AllocateMore();
- Buffer.BlockCopy(bytes, 0, _buffer, _size, length);
- _size += length;
- }
- public void Write(string value)
- {
- if (value == null)
- {
- Write(-1);
- return;
- }
- if (value == string.Empty)
- {
- Write(0);
- return;
- }
- var bytes = Encoding.UTF8.GetBytes(value);
- var length = bytes.Length;
- Write(length);
- if (_size + length >= _buffer.Length)
- AllocateMore();
- Buffer.BlockCopy(bytes, 0, _buffer, _size, length);
- _size += length;
- }
- public void Write(byte[] value)
- {
- if (value == null)
- {
- Write(-1);
- return;
- }
- ;
- var length = value.Length;
- Write(length);
- if (_size + length >= _buffer.Length)
- AllocateMore();
- Buffer.BlockCopy(value, 0, _buffer, _size, length);
- _size += length;
- }
- public void Write(ISerializable data)
- {
- bool isNull = data == null;
- Write(isNull);
- if (isNull) return;
- data.Serialize(this);
- }
- public void Write(IEnumerable enumerable)
- {
- if (null == enumerable)
- {
- Write(-1);
- return;
- }
- Assert.IsTrue(!(enumerable is Array array) || array.Rank == 1, "");
- switch (enumerable)
- {
- case IDictionary dic:
- WriteDictionary(dic);
- break;
- case IList ls: // Array & List
- WriteList(ls);
- break;
- default:
- throw new NotSupportedException($"不支持序列化 {enumerable.GetType()} 类型的字段");
- }
- }
- public byte[] Finish()
- {
- var resBuffer = new byte[_size];
- Buffer.BlockCopy(_buffer, 0, resBuffer, 0, _size);
- _buffer = null;
- _size = 0;
- return resBuffer;
- }
- private void WriteList(IList list)
- {
- Write(list.Count);
- var e = list.GetEnumerator();
- while (e.MoveNext())
- {
- WriteObject(e.Current);
- }
- }
- private void WriteDictionary(IDictionary dic)
- {
- Write(dic.Count);
- var e = dic.GetEnumerator();
- while (e.MoveNext())
- {
- WriteObject(e.Key);
- WriteObject(e.Value);
- }
- }
- private void WriteObject(object data)
- {
- if (null == data)
- {
- var isNull = true;
- Write(isNull);
- return;
- }
- if (data.GetType().IsEnum)
- {
- var type = data.GetType().GetEnumUnderlyingType();
- data = Convert.ChangeType(data, type);
- }
- switch (data)
- {
- case bool value: Write(value); break;
- case byte value: Write(value); break;
- case sbyte value: Write(value); break;
- case short value: Write(value); break;
- case ushort value: Write(value); break;
- case int value: Write(value); break;
- case uint value: Write(value); break;
- case long value: Write(value); break;
- case ulong value: Write(value); break;
- case float value: Write(value); break;
- case double value: Write(value); break;
- case char value: Write(value); break;
- case string value: Write(value); break;
- case byte[] value: Write(value); break;
- case IEnumerable value: Write(value); break;
- case ISerializable value: Write(value); break;
- default: throw new NotSupportedException($"Reader::ReadEnumerable: {data.GetType()} is unsupported.");
- }
- return;
- }
- private void AllocateMore(int length = 0)
- {
- var size = _buffer.Length << (length / _buffer.Length / 2 + 1);
- var array = new byte[size];
- if (_buffer != null && _size > 0)
- {
- _buffer.CopyTo(array, 0);
- }
- _buffer = array;
- }
- }
- }
|