BufferExtension.cs 2.3 KB

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