Writer.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. using System;
  2. using System.Collections;
  3. using System.Text;
  4. namespace XGame.Framework.Serialization
  5. {
  6. public class Writer : IWriter
  7. {
  8. private const int DefaultLength = 2048;
  9. private byte[] _buffer;
  10. private int _size;
  11. public Writer()
  12. {
  13. _buffer = new byte[DefaultLength];
  14. _size = 0;
  15. }
  16. public void Write(bool value)
  17. {
  18. var bytes = BitConverter.GetBytes(value);
  19. var length = bytes.Length;
  20. if (_size + length >= _buffer.Length)
  21. AllocateMore();
  22. Buffer.BlockCopy(bytes, 0, _buffer, _size, length);
  23. _size += length;
  24. }
  25. public void Write(sbyte value)
  26. {
  27. var bytes = BitConverter.GetBytes(value);
  28. var length = bytes.Length;
  29. if (_size + length >= _buffer.Length)
  30. AllocateMore();
  31. Buffer.BlockCopy(bytes, 0, _buffer, _size, length);
  32. _size += length;
  33. }
  34. public void Write(byte value)
  35. {
  36. var bytes = BitConverter.GetBytes(value);
  37. var length = bytes.Length;
  38. if (_size + length >= _buffer.Length)
  39. AllocateMore();
  40. Buffer.BlockCopy(bytes, 0, _buffer, _size, length);
  41. _size += length;
  42. }
  43. public void Write(short value)
  44. {
  45. var bytes = BitConverter.GetBytes(value);
  46. var length = bytes.Length;
  47. if (_size + length >= _buffer.Length)
  48. AllocateMore();
  49. Buffer.BlockCopy(bytes, 0, _buffer, _size, length);
  50. _size += length;
  51. }
  52. public void Write(ushort value)
  53. {
  54. var bytes = BitConverter.GetBytes(value);
  55. var length = bytes.Length;
  56. if (_size + length >= _buffer.Length)
  57. AllocateMore();
  58. Buffer.BlockCopy(bytes, 0, _buffer, _size, length);
  59. _size += length;
  60. }
  61. public void Write(int value)
  62. {
  63. var bytes = BitConverter.GetBytes(value);
  64. var length = bytes.Length;
  65. if (_size + length >= _buffer.Length)
  66. AllocateMore();
  67. Buffer.BlockCopy(bytes, 0, _buffer, _size, length);
  68. _size += length;
  69. }
  70. public void Write(uint value)
  71. {
  72. var bytes = BitConverter.GetBytes(value);
  73. var length = bytes.Length;
  74. if (_size + length >= _buffer.Length)
  75. AllocateMore();
  76. Buffer.BlockCopy(bytes, 0, _buffer, _size, length);
  77. _size += length;
  78. }
  79. public void Write(long value)
  80. {
  81. var bytes = BitConverter.GetBytes(value);
  82. var length = bytes.Length;
  83. if (_size + length >= _buffer.Length)
  84. AllocateMore();
  85. Buffer.BlockCopy(bytes, 0, _buffer, _size, length);
  86. _size += length;
  87. }
  88. public void Write(ulong value)
  89. {
  90. var bytes = BitConverter.GetBytes(value);
  91. var length = bytes.Length;
  92. if (_size + length >= _buffer.Length)
  93. AllocateMore();
  94. Buffer.BlockCopy(bytes, 0, _buffer, _size, length);
  95. _size += length;
  96. }
  97. public void Write(float value)
  98. {
  99. var bytes = BitConverter.GetBytes(value);
  100. var length = bytes.Length;
  101. if (_size + length >= _buffer.Length)
  102. AllocateMore();
  103. Buffer.BlockCopy(bytes, 0, _buffer, _size, length);
  104. _size += length;
  105. }
  106. public void Write(double value)
  107. {
  108. var bytes = BitConverter.GetBytes(value);
  109. var length = bytes.Length;
  110. if (_size + length >= _buffer.Length)
  111. AllocateMore();
  112. Buffer.BlockCopy(bytes, 0, _buffer, _size, length);
  113. _size += length;
  114. }
  115. public void Write(char value)
  116. {
  117. var bytes = BitConverter.GetBytes(value);
  118. var length = bytes.Length;
  119. if (_size + length >= _buffer.Length)
  120. AllocateMore();
  121. Buffer.BlockCopy(bytes, 0, _buffer, _size, length);
  122. _size += length;
  123. }
  124. public void Write(string value)
  125. {
  126. if (value == null)
  127. {
  128. Write(-1);
  129. return;
  130. }
  131. if (value == string.Empty)
  132. {
  133. Write(0);
  134. return;
  135. }
  136. var bytes = Encoding.UTF8.GetBytes(value);
  137. var length = bytes.Length;
  138. Write(length);
  139. if (_size + length >= _buffer.Length)
  140. AllocateMore();
  141. Buffer.BlockCopy(bytes, 0, _buffer, _size, length);
  142. _size += length;
  143. }
  144. public void Write(byte[] value)
  145. {
  146. if (value == null)
  147. {
  148. Write(-1);
  149. return;
  150. }
  151. ;
  152. var length = value.Length;
  153. Write(length);
  154. if (_size + length >= _buffer.Length)
  155. AllocateMore();
  156. Buffer.BlockCopy(value, 0, _buffer, _size, length);
  157. _size += length;
  158. }
  159. public void Write(ISerializable data)
  160. {
  161. bool isNull = data == null;
  162. Write(isNull);
  163. if (isNull) return;
  164. data.Serialize(this);
  165. }
  166. public void Write(IEnumerable enumerable)
  167. {
  168. if (null == enumerable)
  169. {
  170. Write(-1);
  171. return;
  172. }
  173. Assert.IsTrue(!(enumerable is Array array) || array.Rank == 1, "");
  174. switch (enumerable)
  175. {
  176. case IDictionary dic:
  177. WriteDictionary(dic);
  178. break;
  179. case IList ls: // Array & List
  180. WriteList(ls);
  181. break;
  182. default:
  183. throw new NotSupportedException($"不支持序列化 {enumerable.GetType()} 类型的字段");
  184. }
  185. }
  186. public byte[] Finish()
  187. {
  188. var resBuffer = new byte[_size];
  189. Buffer.BlockCopy(_buffer, 0, resBuffer, 0, _size);
  190. _buffer = null;
  191. _size = 0;
  192. return resBuffer;
  193. }
  194. private void WriteList(IList list)
  195. {
  196. Write(list.Count);
  197. var e = list.GetEnumerator();
  198. while (e.MoveNext())
  199. {
  200. WriteObject(e.Current);
  201. }
  202. }
  203. private void WriteDictionary(IDictionary dic)
  204. {
  205. Write(dic.Count);
  206. var e = dic.GetEnumerator();
  207. while (e.MoveNext())
  208. {
  209. WriteObject(e.Key);
  210. WriteObject(e.Value);
  211. }
  212. }
  213. private void WriteObject(object data)
  214. {
  215. if (null == data)
  216. {
  217. var isNull = true;
  218. Write(isNull);
  219. return;
  220. }
  221. if (data.GetType().IsEnum)
  222. {
  223. var type = data.GetType().GetEnumUnderlyingType();
  224. data = Convert.ChangeType(data, type);
  225. }
  226. switch (data)
  227. {
  228. case bool value: Write(value); break;
  229. case byte value: Write(value); break;
  230. case sbyte value: Write(value); break;
  231. case short value: Write(value); break;
  232. case ushort value: Write(value); break;
  233. case int value: Write(value); break;
  234. case uint value: Write(value); break;
  235. case long value: Write(value); break;
  236. case ulong value: Write(value); break;
  237. case float value: Write(value); break;
  238. case double value: Write(value); break;
  239. case char value: Write(value); break;
  240. case string value: Write(value); break;
  241. case byte[] value: Write(value); break;
  242. case IEnumerable value: Write(value); break;
  243. case ISerializable value: Write(value); break;
  244. default: throw new NotSupportedException($"Reader::ReadEnumerable: {data.GetType()} is unsupported.");
  245. }
  246. return;
  247. }
  248. private void AllocateMore(int length = 0)
  249. {
  250. var size = _buffer.Length << (length / _buffer.Length / 2 + 1);
  251. var array = new byte[size];
  252. if (_buffer != null && _size > 0)
  253. {
  254. _buffer.CopyTo(array, 0);
  255. }
  256. _buffer = array;
  257. }
  258. }
  259. }