NetMQMessage.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. namespace NetMQ
  7. {
  8. #region Doc-stuff
  9. /// <summary>
  10. /// This namespace encompasses the NetMQ message-queueing library
  11. /// and attendant utility software.
  12. /// </summary>
  13. public static class NamespaceDoc
  14. {
  15. // This class exists only to provide a hook for adding summary documentation
  16. // for the NetMQ namespace.
  17. }
  18. #endregion
  19. /// <summary>
  20. /// A NetMQMessage is basically a collection of NetMQFrames, and is the basic message-unit that is sent and received
  21. /// across this message-queueing subsystem.
  22. /// </summary>
  23. public class NetMQMessage : IEnumerable<NetMQFrame>
  24. {
  25. /// <summary>
  26. /// This is the frame-stack that comprises the message-content of this message.
  27. /// </summary>
  28. private readonly List<NetMQFrame> m_frames;
  29. #region Constructors
  30. /// <summary>
  31. /// The default-constructor for NetMQMessage: create a new instance of NetMQMessage
  32. /// with an empty frame-stack.
  33. /// </summary>
  34. public NetMQMessage(int expectedFrameCount = 4)
  35. {
  36. m_frames = new List<NetMQFrame>(expectedFrameCount);
  37. }
  38. /// <summary>
  39. /// Create a new instance of a NetMQMessage that contains the given collection of NetMQFrames as its frame-stack.
  40. /// </summary>
  41. /// <param name="frames">a collection of NetMQFrames, to form the frame-stack</param>
  42. /// <exception cref="ArgumentNullException">The value of 'frames' cannot be null. </exception>
  43. public NetMQMessage(IEnumerable<NetMQFrame> frames)
  44. {
  45. if (frames == null)
  46. throw new ArgumentNullException(nameof(frames));
  47. m_frames = new List<NetMQFrame>(frames);
  48. }
  49. /// <summary>
  50. /// Create a new instance of a NetMQMessage that contains the given collection of byte-arrays as its frame-stack.
  51. /// </summary>
  52. /// <param name="buffers">a collection of byte-array buffers, to form the frame-stack</param>
  53. /// <exception cref="ArgumentNullException">The value of 'buffers' cannot be null. </exception>
  54. public NetMQMessage(IEnumerable<byte[]> buffers)
  55. {
  56. if (buffers == null)
  57. throw new ArgumentNullException(nameof(buffers));
  58. m_frames = buffers.Select(buf => new NetMQFrame(buf)).ToList();
  59. }
  60. #endregion
  61. #region Properties
  62. /// <summary>
  63. /// Gets the first frame in the current message.
  64. /// </summary>
  65. public NetMQFrame First => m_frames[0];
  66. /// <summary>
  67. /// Gets the last frame in the current message.
  68. /// </summary>
  69. public NetMQFrame Last => m_frames[m_frames.Count - 1];
  70. /// <summary>
  71. /// Gets a value indicating whether the current message is empty.
  72. /// </summary>
  73. public bool IsEmpty => m_frames.Count == 0;
  74. /// <summary>
  75. /// Gets the number of <see cref="NetMQFrame"/> objects contained by this message.
  76. /// </summary>
  77. public int FrameCount => m_frames.Count;
  78. /// <summary>
  79. /// Gets the <see cref="NetMQFrame"/> at the specified index.
  80. /// </summary>
  81. /// <param name="index">The zero-based index of the <see cref="NetMQFrame"/> to get.</param>
  82. /// <returns>The <see cref="NetMQFrame"/> at the specified index.</returns>
  83. /// <exception cref="ArgumentOutOfRangeException">
  84. /// <paramref name="index"/>is less than 0 -or- <paramref name="index"/> is equal to or greater than <see cref="FrameCount"/>.
  85. /// </exception>
  86. public NetMQFrame this[int index] => m_frames[index];
  87. #endregion
  88. #region Appending frames
  89. /// <summary>
  90. /// Add the given NetMQFrame to this NetMQMessage, at the highest-indexed position of the frame-stack.
  91. /// </summary>
  92. /// <param name="frame">a NetMQFrame object comprising the frame to be appended onto the frame-stack</param>
  93. public void Append(NetMQFrame frame)
  94. {
  95. m_frames.Add(frame);
  96. }
  97. /// <summary>
  98. /// Add the given data (in this case a byte-array) to this NetMQMessage, at the highest-indexed position of the frame-stack.
  99. /// Data is not copied.
  100. /// </summary>
  101. /// <param name="buffer">a byte-array containing the message to append onto the frame-stack of this NetMQMessage</param>
  102. public void Append(byte[] buffer)
  103. {
  104. m_frames.Add(new NetMQFrame(buffer));
  105. }
  106. /// <summary>
  107. /// Add the given string - which gets converted into a NetMQFrame - onto
  108. /// the highest-indexed position of the frame-stack of this NetMQMessage.
  109. /// </summary>
  110. /// <param name="message">a string containing the message to append onto the frame-stack of this NetMQMessage</param>
  111. public void Append(string message)
  112. {
  113. m_frames.Add(new NetMQFrame(message));
  114. }
  115. /// <summary>
  116. /// Add the given string - which gets converted into a NetMQFrame - onto
  117. /// the highest-indexed position of the frame-stack of this NetMQMessage.
  118. /// </summary>
  119. /// <param name="message">a string containing the message to append onto the frame-stack of this NetMQMessage</param>
  120. /// <param name="encoding">an Encoding that specifies how to convert the string into bytes</param>
  121. public void Append(string message, Encoding encoding)
  122. {
  123. m_frames.Add(new NetMQFrame(message, encoding));
  124. }
  125. /// <summary>
  126. /// Convert the given integer value into an array of bytes and add it as a new frame onto this NetMQMessage.
  127. /// </summary>
  128. /// <param name="value">a 32-bit integer value that is to be converted into bytes and added to this message</param>
  129. public void Append(int value)
  130. {
  131. Append(NetworkOrderBitsConverter.GetBytes(value));
  132. }
  133. /// <summary>
  134. /// Convert the given long value into an array of bytes and add it as a new frame onto this NetMQMessage.
  135. /// </summary>
  136. /// <param name="value">a 64-bit number that is to be converted into bytes and added to this message</param>
  137. public void Append(long value)
  138. {
  139. Append(NetworkOrderBitsConverter.GetBytes(value));
  140. }
  141. /// <summary>
  142. /// Add an empty frame to this NetMQMessage.
  143. /// </summary>
  144. public void AppendEmptyFrame()
  145. {
  146. m_frames.Add(NetMQFrame.Empty);
  147. }
  148. #endregion
  149. #region Pushing frames
  150. /// <summary>
  151. /// Push the given NetMQFrame into the frame-stack of this NetMQMessage.
  152. /// </summary>
  153. /// <param name="frame">the NetMQFrame to be inserted into the frame-stack</param>
  154. /// <remarks>
  155. /// The concept is the same as pushing an element onto a stack.
  156. /// This inserts the given NetMQFrame into the lowest-indexed position of this NetMQMessage,
  157. /// pushing all of the other frames upward in index-position.
  158. /// </remarks>
  159. public void Push(NetMQFrame frame)
  160. {
  161. m_frames.Insert(0, frame);
  162. }
  163. /// <summary>
  164. /// Push a new frame containing the given byte-array into the frame-stack of this NetMQMessage.
  165. /// </summary>
  166. /// <param name="buffer">the byte-array to create a new frame from</param>
  167. /// <remarks>
  168. /// The concept is the same as pushing an element onto a stack.
  169. /// This creates a new frame from the given data (in this case a byte-array) and inserts it into the lowest-indexed position of
  170. /// the collection of frames of this NetMQMessage,
  171. /// pushing all of the other frames upward in index-position.
  172. /// </remarks>
  173. public void Push(byte[] buffer)
  174. {
  175. m_frames.Insert(0, new NetMQFrame(buffer));
  176. }
  177. /// <summary>
  178. /// Push a new frame containing the given string (converted into a byte-array) into the frame-stack of this NetMQMessage.
  179. /// </summary>
  180. /// <param name="message">the string to create a new frame from</param>
  181. /// <remarks>
  182. /// The concept is the same as pushing an element onto a stack.
  183. /// This creates a new frame from the given data (in this case a string which gets converted into a byte-array using the default ASCII encoding) and inserts it into the lowest-indexed position of
  184. /// the collection of frames of this NetMQMessage,
  185. /// pushing all of the other frames upward in index-position.
  186. /// </remarks>
  187. public void Push(string message)
  188. {
  189. m_frames.Insert(0, new NetMQFrame(message));
  190. }
  191. /// <summary>
  192. /// Push a new frame containing the given string (converted into a byte-array) into the frame-stack of this NetMQMessage.
  193. /// </summary>
  194. /// <param name="message">the string to create a new frame from</param>
  195. /// <param name="encoding">the Encoding that dictates how to encode the string into bytes</param>
  196. /// <remarks>
  197. /// The concept is the same as pushing an element onto a stack.
  198. /// This creates a new frame from the given data (in this case a string which gets converted into a byte-array using the given Encoding) and inserts it into the lowest-indexed position of
  199. /// the collection of frames of this NetMQMessage,
  200. /// pushing all of the other frames upward in index-position.
  201. /// </remarks>
  202. public void Push(string message, Encoding encoding)
  203. {
  204. m_frames.Insert(0, new NetMQFrame(message, encoding));
  205. }
  206. /// <summary>
  207. /// Push a new frame containing the given integer (converted into a byte-array) into the frame-stack of this NetMQMessage.
  208. /// </summary>
  209. /// <param name="value">the integer to create a new frame from</param>
  210. /// <remarks>
  211. /// The concept is the same as pushing an element onto a stack.
  212. /// This creates a new frame from the given data (in this case a 32-bit integer which gets converted into a byte-array in big-endian order) and inserts it into the lowest-indexed position of
  213. /// the collection of frames of this NetMQMessage,
  214. /// pushing all of the other frames upward in index-position.
  215. /// </remarks>
  216. public void Push(int value)
  217. {
  218. Push(NetworkOrderBitsConverter.GetBytes(value));
  219. }
  220. /// <summary>
  221. /// Push a new frame containing the given long (converted into a byte-array) into the frame-stack of this NetMQMessage.
  222. /// </summary>
  223. /// <param name="value">the 64-bit number to create a new frame from</param>
  224. /// <remarks>
  225. /// The concept is the same as pushing an element onto a stack.
  226. /// This creates a new frame from the given data (in this case a 64-bit long which gets converted into a byte-array in big-endian order) and inserts it into the lowest-indexed position of
  227. /// the collection of frames of this NetMQMessage,
  228. /// pushing all of the other frames upward in index-position.
  229. /// </remarks>
  230. public void Push(long value)
  231. {
  232. Push(NetworkOrderBitsConverter.GetBytes(value));
  233. }
  234. /// <summary>
  235. /// Push an empty frame (a NetMQFrame.Empty) onto the frame-stack.
  236. /// </summary>
  237. public void PushEmptyFrame()
  238. {
  239. m_frames.Insert(0, NetMQFrame.Empty);
  240. }
  241. #endregion
  242. /// <summary>
  243. /// Remove and return the first frame.
  244. /// </summary>
  245. /// <returns>the first frame, which was popped - which is the frame from the lowest-indexed position</returns>
  246. public NetMQFrame Pop()
  247. {
  248. NetMQFrame frame = m_frames[0];
  249. m_frames.RemoveAt(0);
  250. return frame;
  251. }
  252. /// <summary>
  253. /// Delete the given frame from the frame-stack.
  254. /// </summary>
  255. /// <param name="frame">the frame to remove</param>
  256. /// <returns><c>true</c> if removed, otherwise <c>false</c>.</returns>
  257. public bool RemoveFrame(NetMQFrame frame)
  258. {
  259. return m_frames.Remove(frame);
  260. }
  261. /// <summary>
  262. /// Clear (empty) the frame-stack, so that it no longer contains any frames.
  263. /// </summary>
  264. public void Clear()
  265. {
  266. m_frames.Clear();
  267. }
  268. #region IEnumerable
  269. /// <summary>
  270. /// Return an enumerator over the frames contained within this message.
  271. /// </summary>
  272. /// <returns>an IEnumerator over the frames in this message</returns>
  273. public IEnumerator<NetMQFrame> GetEnumerator()
  274. {
  275. return m_frames.GetEnumerator();
  276. }
  277. /// <summary>
  278. /// Return an enumerator over the frames contained within this message.
  279. /// </summary>
  280. /// <returns>an IEnumerator over the frames in this message</returns>
  281. IEnumerator IEnumerable.GetEnumerator()
  282. {
  283. return GetEnumerator();
  284. }
  285. #endregion
  286. #region Formatting
  287. /// <summary>
  288. /// Returns a string showing the frame contents.
  289. /// </summary>
  290. /// <returns></returns>
  291. public override string ToString()
  292. {
  293. if (m_frames.Count == 0)
  294. return "NetMQMessage[<no frames>]";
  295. var sb = new StringBuilder("NetMQMessage[");
  296. bool first = true;
  297. foreach (var f in m_frames)
  298. {
  299. if (!first)
  300. sb.Append(",");
  301. sb.Append(f.ConvertToString());
  302. first = false;
  303. }
  304. return sb.Append("]").ToString();
  305. }
  306. #endregion
  307. }
  308. }