queue.h 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. // queue.h - originally written and placed in the public domain by Wei Dai
  2. /// \file
  3. /// \brief Classes for an unlimited queue to store bytes
  4. #ifndef CRYPTOPP_QUEUE_H
  5. #define CRYPTOPP_QUEUE_H
  6. #include "cryptlib.h"
  7. #include "simple.h"
  8. NAMESPACE_BEGIN(CryptoPP)
  9. class ByteQueueNode;
  10. /// \brief Data structure used to store byte strings
  11. /// \details The queue is implemented as a linked list of byte arrays.
  12. /// Each byte array is stored in a ByteQueueNode.
  13. /// \sa <A HREF="https://www.cryptopp.com/wiki/ByteQueue">ByteQueue</A>
  14. /// on the Crypto++ wiki.
  15. /// \since Crypto++ 2.0
  16. class CRYPTOPP_DLL ByteQueue : public Bufferless<BufferedTransformation>
  17. {
  18. public:
  19. virtual ~ByteQueue();
  20. /// \brief Construct a ByteQueue
  21. /// \param nodeSize the initial node size
  22. /// \details Internally, ByteQueue uses a ByteQueueNode to store bytes,
  23. /// and <tt>nodeSize</tt> determines the size of the ByteQueueNode. A value
  24. /// of 0 indicates the ByteQueueNode should be automatically sized,
  25. /// which means a value of 256 is used.
  26. ByteQueue(size_t nodeSize=0);
  27. /// \brief Copy construct a ByteQueue
  28. /// \param copy the other ByteQueue
  29. ByteQueue(const ByteQueue &copy);
  30. // BufferedTransformation
  31. lword MaxRetrievable() const
  32. {return CurrentSize();}
  33. bool AnyRetrievable() const
  34. {return !IsEmpty();}
  35. void IsolatedInitialize(const NameValuePairs &parameters);
  36. byte * CreatePutSpace(size_t &size);
  37. size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking);
  38. size_t Get(byte &outByte);
  39. size_t Get(byte *outString, size_t getMax);
  40. size_t Peek(byte &outByte) const;
  41. size_t Peek(byte *outString, size_t peekMax) const;
  42. size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
  43. size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
  44. /// \brief Set node size
  45. /// \param nodeSize the new node size, in bytes
  46. /// \details The default node size is 256.
  47. void SetNodeSize(size_t nodeSize);
  48. /// \brief Determine data size
  49. /// \return the data size, in bytes
  50. lword CurrentSize() const;
  51. /// \brief Determine data availability
  52. /// \return true if the ByteQueue has data, false otherwise
  53. bool IsEmpty() const;
  54. /// \brief Empty the queue
  55. void Clear();
  56. /// \brief Insert data in the queue
  57. /// \param inByte a byte to insert
  58. /// \details Unget() inserts a byte at the head of the queue
  59. void Unget(byte inByte);
  60. /// \brief Insert data in the queue
  61. /// \param inString a byte array to insert
  62. /// \param length the size of the byte array
  63. /// \details Unget() inserts a byte array at the head of the queue
  64. void Unget(const byte *inString, size_t length);
  65. /// \brief Peek data in the queue
  66. /// \param contiguousSize the size of the data
  67. /// \details Spy() peeks at data at the head of the queue. Spy() does
  68. /// not remove data from the queue.
  69. /// \details The data's size is returned in <tt>contiguousSize</tt>.
  70. /// Spy() returns the size of the first byte array in the list. The
  71. /// entire data may be larger since the queue is a linked list of
  72. /// byte arrays.
  73. const byte * Spy(size_t &contiguousSize) const;
  74. /// \brief Insert data in the queue
  75. /// \param inString a byte array to insert
  76. /// \param size the length of the byte array
  77. /// \details LazyPut() inserts a byte array at the tail of the queue.
  78. /// The data may not be copied at this point. Rather, the pointer
  79. /// and size to external data are recorded.
  80. /// \details Another call to Put() or LazyPut() will force the data to
  81. /// be copied. When lazy puts are used, the data is copied when
  82. /// FinalizeLazyPut() is called.
  83. /// \sa LazyPutter
  84. void LazyPut(const byte *inString, size_t size);
  85. /// \brief Insert data in the queue
  86. /// \param inString a byte array to insert
  87. /// \param size the length of the byte array
  88. /// \details LazyPut() inserts a byte array at the tail of the queue.
  89. /// The data may not be copied at this point. Rather, the pointer
  90. /// and size to external data are recorded.
  91. /// \details Another call to Put() or LazyPut() will force the data to
  92. /// be copied. When lazy puts are used, the data is copied when
  93. /// FinalizeLazyPut() is called.
  94. /// \sa LazyPutter
  95. void LazyPutModifiable(byte *inString, size_t size);
  96. /// \brief Remove data from the queue
  97. /// \param size the length of the data
  98. /// \throw InvalidArgument if there is no lazy data in the queue or if
  99. /// size is larger than the lazy string
  100. /// \details UndoLazyPut() truncates data inserted using LazyPut() by
  101. /// modifying size.
  102. /// \sa LazyPutter
  103. void UndoLazyPut(size_t size);
  104. /// \brief Insert data in the queue
  105. /// \details FinalizeLazyPut() copies external data inserted using
  106. /// LazyPut() or LazyPutModifiable() into the tail of the queue.
  107. /// \sa LazyPutter
  108. void FinalizeLazyPut();
  109. /// \brief Assign contents from another ByteQueue
  110. /// \param rhs the other ByteQueue
  111. /// \return reference to this ByteQueue
  112. ByteQueue & operator=(const ByteQueue &rhs);
  113. /// \brief Bitwise compare two ByteQueue
  114. /// \param rhs the other ByteQueue
  115. /// \return true if the size and bits are equal, false otherwise
  116. /// \details operator==() walks each ByteQueue comparing bytes in
  117. /// each queue. operator==() is not constant time.
  118. bool operator==(const ByteQueue &rhs) const;
  119. /// \brief Bitwise compare two ByteQueue
  120. /// \param rhs the other ByteQueue
  121. /// \return true if the size and bits are not equal, false otherwise
  122. /// \details operator!=() is implemented in terms of operator==().
  123. /// operator==() is not constant time.
  124. bool operator!=(const ByteQueue &rhs) const {return !operator==(rhs);}
  125. /// \brief Retrieve data from the queue
  126. /// \param index of byte to retrieve
  127. /// \return byte at the specified index
  128. /// \details operator[]() does not perform bounds checking.
  129. byte operator[](lword index) const;
  130. /// \brief Swap contents with another ByteQueue
  131. /// \param rhs the other ByteQueue
  132. void swap(ByteQueue &rhs);
  133. /// \brief A ByteQueue iterator
  134. class Walker : public InputRejecting<BufferedTransformation>
  135. {
  136. public:
  137. /// \brief Construct a ByteQueue Walker
  138. /// \param queue a ByteQueue
  139. Walker(const ByteQueue &queue)
  140. : m_queue(queue), m_node(NULLPTR), m_position(0), m_offset(0), m_lazyString(NULLPTR), m_lazyLength(0)
  141. {Initialize();}
  142. lword GetCurrentPosition() {return m_position;}
  143. lword MaxRetrievable() const
  144. {return m_queue.CurrentSize() - m_position;}
  145. void IsolatedInitialize(const NameValuePairs &parameters);
  146. size_t Get(byte &outByte);
  147. size_t Get(byte *outString, size_t getMax);
  148. size_t Peek(byte &outByte) const;
  149. size_t Peek(byte *outString, size_t peekMax) const;
  150. size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
  151. size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
  152. private:
  153. const ByteQueue &m_queue;
  154. const ByteQueueNode *m_node;
  155. lword m_position;
  156. size_t m_offset;
  157. const byte *m_lazyString;
  158. size_t m_lazyLength;
  159. };
  160. friend class Walker;
  161. protected:
  162. void CleanupUsedNodes();
  163. void CopyFrom(const ByteQueue &copy);
  164. void Destroy();
  165. private:
  166. ByteQueueNode *m_head, *m_tail;
  167. byte *m_lazyString;
  168. size_t m_lazyLength;
  169. size_t m_nodeSize;
  170. bool m_lazyStringModifiable;
  171. bool m_autoNodeSize;
  172. };
  173. /// \brief Helper class to finalize Puts on ByteQueue
  174. /// \details LazyPutter ensures LazyPut is committed to the ByteQueue
  175. /// in event of exception. During destruction, the LazyPutter class
  176. /// calls FinalizeLazyPut.
  177. class CRYPTOPP_DLL LazyPutter
  178. {
  179. public:
  180. virtual ~LazyPutter() {
  181. try {m_bq.FinalizeLazyPut();}
  182. catch(const Exception&) {CRYPTOPP_ASSERT(0);}
  183. }
  184. /// \brief Construct a LazyPutter
  185. /// \param bq the ByteQueue
  186. /// \param inString a byte array to insert
  187. /// \param size the length of the byte array
  188. /// \details LazyPutter ensures LazyPut is committed to the ByteQueue
  189. /// in event of exception. During destruction, the LazyPutter class
  190. /// calls FinalizeLazyPut.
  191. LazyPutter(ByteQueue &bq, const byte *inString, size_t size)
  192. : m_bq(bq) {bq.LazyPut(inString, size);}
  193. protected:
  194. LazyPutter(ByteQueue &bq) : m_bq(bq) {}
  195. private:
  196. ByteQueue &m_bq;
  197. };
  198. /// \brief Helper class to finalize Puts on ByteQueue
  199. /// \details LazyPutterModifiable ensures LazyPut is committed to the
  200. /// ByteQueue in event of exception. During destruction, the
  201. /// LazyPutterModifiable class calls FinalizeLazyPut.
  202. class LazyPutterModifiable : public LazyPutter
  203. {
  204. public:
  205. /// \brief Construct a LazyPutterModifiable
  206. /// \param bq the ByteQueue
  207. /// \param inString a byte array to insert
  208. /// \param size the length of the byte array
  209. /// \details LazyPutterModifiable ensures LazyPut is committed to the
  210. /// ByteQueue in event of exception. During destruction, the
  211. /// LazyPutterModifiable class calls FinalizeLazyPut.
  212. LazyPutterModifiable(ByteQueue &bq, byte *inString, size_t size)
  213. : LazyPutter(bq) {bq.LazyPutModifiable(inString, size);}
  214. };
  215. NAMESPACE_END
  216. #ifndef __BORLANDC__
  217. NAMESPACE_BEGIN(std)
  218. template<> inline void swap(CryptoPP::ByteQueue &a, CryptoPP::ByteQueue &b)
  219. {
  220. a.swap(b);
  221. }
  222. NAMESPACE_END
  223. #endif
  224. #endif