BufferExtension.cs 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. using System;
  2. using System.IO;
  3. namespace ProtoBuf
  4. {
  5. /// <summary>
  6. /// Provides a simple buffer-based implementation of an <see cref="IExtension">extension</see> object.
  7. /// </summary>
  8. public sealed class BufferExtension : IExtension
  9. {
  10. private byte[] buffer;
  11. int IExtension.GetLength()
  12. {
  13. return buffer == null ? 0 : buffer.Length;
  14. }
  15. Stream IExtension.BeginAppend()
  16. {
  17. return new MemoryStream();
  18. }
  19. void IExtension.EndAppend(Stream stream, bool commit)
  20. {
  21. using (stream)
  22. {
  23. int len;
  24. if (commit && (len = (int)stream.Length) > 0)
  25. {
  26. MemoryStream ms = (MemoryStream)stream;
  27. if (buffer == null)
  28. { // allocate new buffer
  29. buffer = ms.ToArray();
  30. }
  31. else
  32. { // resize and copy the data
  33. // note: Array.Resize not available on CF
  34. int offset = buffer.Length;
  35. byte[] tmp = new byte[offset + len];
  36. Helpers.BlockCopy(buffer, 0, tmp, 0, offset);
  37. #if PORTABLE || WINRT // no GetBuffer() - fine, we'll use Read instead
  38. int bytesRead;
  39. long oldPos = ms.Position;
  40. ms.Position = 0;
  41. while (len > 0 && (bytesRead = ms.Read(tmp, offset, len)) > 0)
  42. {
  43. len -= bytesRead;
  44. offset += bytesRead;
  45. }
  46. if(len != 0) throw new EndOfStreamException();
  47. ms.Position = oldPos;
  48. #else
  49. Helpers.BlockCopy(Helpers.GetBuffer(ms), 0, tmp, offset, len);
  50. #endif
  51. buffer = tmp;
  52. }
  53. }
  54. }
  55. }
  56. Stream IExtension.BeginQuery()
  57. {
  58. return buffer == null ? Stream.Null : new MemoryStream(buffer);
  59. }
  60. void IExtension.EndQuery(Stream stream)
  61. {
  62. using (stream) { } // just clean up
  63. }
  64. }
  65. }