WatsonStream.cs 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. namespace WatsonTcp
  2. {
  3. using System;
  4. using System.IO;
  5. /// <summary>
  6. /// Stream containing message data.
  7. /// </summary>
  8. public class WatsonStream : Stream
  9. {
  10. #region Public-Members
  11. /// <summary>
  12. /// Indicates if the stream is readable.
  13. /// This value will always be true.
  14. /// </summary>
  15. public override bool CanRead => true;
  16. /// <summary>
  17. /// Indicates if seek operations are supported.
  18. /// This value will always be false.
  19. /// </summary>
  20. public override bool CanSeek => false;
  21. /// <summary>
  22. /// Indicates if the stream is writeable.
  23. /// This value will always be false.
  24. /// </summary>
  25. public override bool CanWrite => false;
  26. /// <summary>
  27. /// The number of bytes remaining in the stream.
  28. /// </summary>
  29. public override long Length
  30. {
  31. get
  32. {
  33. return _Length;
  34. }
  35. }
  36. /// <summary>
  37. /// The current position within the stream.
  38. /// </summary>
  39. public override long Position
  40. {
  41. get
  42. {
  43. return _Position;
  44. }
  45. set
  46. {
  47. throw new InvalidOperationException("Position may not be modified.");
  48. }
  49. }
  50. #endregion
  51. #region Private-Members
  52. private readonly object _Lock = new object();
  53. private Stream _Stream = null;
  54. private long _Length = 0;
  55. private long _Position = 0;
  56. private long _BytesRemaining
  57. {
  58. get
  59. {
  60. return _Length - _Position;
  61. }
  62. }
  63. #endregion
  64. #region Constructors-and-Factories
  65. internal WatsonStream(long contentLength, Stream stream)
  66. {
  67. if (contentLength < 0) throw new ArgumentException("Content length must be zero or greater.");
  68. if (stream == null) throw new ArgumentNullException(nameof(stream));
  69. if (!stream.CanRead) throw new ArgumentException("Cannot read from supplied stream.");
  70. _Length = contentLength;
  71. _Stream = stream;
  72. }
  73. #endregion
  74. #region Public-Methods
  75. /// <summary>
  76. /// Flushes data awaiting in the stream.
  77. /// </summary>
  78. public override void Flush()
  79. {
  80. }
  81. /// <summary>
  82. /// Read data from the stream.
  83. /// </summary>
  84. /// <param name="buffer">The buffer to which the data should be read.</param>
  85. /// <param name="offset">The offset within the buffer where data should begin.</param>
  86. /// <param name="count">The number of bytes to read.</param>
  87. /// <returns>Number of bytes read.</returns>
  88. public override int Read(byte[] buffer, int offset, int count)
  89. {
  90. if (buffer == null) throw new ArgumentNullException(nameof(buffer));
  91. if (offset < 0) throw new ArgumentException("Offset must be zero or greater.");
  92. if (offset >= buffer.Length) throw new IndexOutOfRangeException("Offset must be less than the buffer length of " + buffer.Length + ".");
  93. if (count < 0) throw new ArgumentException("Count must be zero or greater.");
  94. if (count == 0) return 0;
  95. if (count + offset > buffer.Length) throw new ArgumentException("Offset and count must sum to a value less than the buffer length of " + buffer.Length + ".");
  96. lock (_Lock)
  97. {
  98. byte[] temp = null;
  99. if (_BytesRemaining == 0) return 0;
  100. if (count > _BytesRemaining) temp = new byte[_BytesRemaining];
  101. else temp = new byte[count];
  102. int bytesRead = _Stream.Read(temp, 0, temp.Length);
  103. Buffer.BlockCopy(temp, 0, buffer, offset, bytesRead);
  104. _Position += bytesRead;
  105. return bytesRead;
  106. }
  107. }
  108. /// <summary>
  109. /// Not supported.
  110. /// Seek to a specific position within a stream.
  111. /// </summary>
  112. /// <param name="offset"></param>
  113. /// <param name="origin"></param>
  114. /// <returns></returns>
  115. public override long Seek(long offset, SeekOrigin origin)
  116. {
  117. throw new InvalidOperationException("Seek operations are not supported.");
  118. }
  119. /// <summary>
  120. /// Not supported.
  121. /// Set the length of the stream.
  122. /// </summary>
  123. /// <param name="value">Length.</param>
  124. public override void SetLength(long value)
  125. {
  126. throw new InvalidOperationException("Length may not be modified.");
  127. }
  128. /// <summary>
  129. /// Not supported.
  130. /// Write to the stream.
  131. /// </summary>
  132. /// <param name="buffer">The buffer containing the data that should be written to the stream.</param>
  133. /// <param name="offset">The offset within the buffer from which data should be read.</param>
  134. /// <param name="count">The number of bytes to read.</param>
  135. public override void Write(byte[] buffer, int offset, int count)
  136. {
  137. throw new InvalidOperationException("Stream is not writeable.");
  138. }
  139. #endregion
  140. }
  141. }