1// specification file for an unlimited queue for storing bytes
2
3#ifndef CRYPTOPP_QUEUE_H
4#define CRYPTOPP_QUEUE_H
5
6#include "simple.h"
7//#include <algorithm>
8
9NAMESPACE_BEGIN(CryptoPP)
10
11/** The queue is implemented as a linked list of byte arrays, but you don't need to
12    know about that.  So just ignore this next line. :) */
13class ByteQueueNode;
14
15//! Byte Queue
16class CRYPTOPP_DLL ByteQueue : public Bufferless<BufferedTransformation>
17{
18public:
19	ByteQueue(size_t nodeSize=0);
20	ByteQueue(const ByteQueue &copy);
21	~ByteQueue();
22
23	lword MaxRetrievable() const
24		{return CurrentSize();}
25	bool AnyRetrievable() const
26		{return !IsEmpty();}
27
28	void IsolatedInitialize(const NameValuePairs &parameters);
29	byte * CreatePutSpace(size_t &size);
30	size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking);
31
32	size_t Get(byte &outByte);
33	size_t Get(byte *outString, size_t getMax);
34
35	size_t Peek(byte &outByte) const;
36	size_t Peek(byte *outString, size_t peekMax) const;
37
38	size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
39	size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
40
41	// these member functions are not inherited
42	void SetNodeSize(size_t nodeSize);
43
44	lword CurrentSize() const;
45	bool IsEmpty() const;
46
47	void Clear();
48
49	void Unget(byte inByte);
50	void Unget(const byte *inString, size_t length);
51
52	const byte * Spy(size_t &contiguousSize) const;
53
54	void LazyPut(const byte *inString, size_t size);
55	void LazyPutModifiable(byte *inString, size_t size);
56	void UndoLazyPut(size_t size);
57	void FinalizeLazyPut();
58
59	ByteQueue & operator=(const ByteQueue &rhs);
60	bool operator==(const ByteQueue &rhs) const;
61	byte operator[](lword i) const;
62	void swap(ByteQueue &rhs);
63
64	class Walker : public InputRejecting<BufferedTransformation>
65	{
66	public:
67		Walker(const ByteQueue &queue)
68			: m_queue(queue) {Initialize();}
69
70		lword GetCurrentPosition() {return m_position;}
71
72		lword MaxRetrievable() const
73			{return m_queue.CurrentSize() - m_position;}
74
75		void IsolatedInitialize(const NameValuePairs &parameters);
76
77		size_t Get(byte &outByte);
78		size_t Get(byte *outString, size_t getMax);
79
80		size_t Peek(byte &outByte) const;
81		size_t Peek(byte *outString, size_t peekMax) const;
82
83		size_t TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
84		size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const;
85
86	private:
87		const ByteQueue &m_queue;
88		const ByteQueueNode *m_node;
89		lword m_position;
90		size_t m_offset;
91		const byte *m_lazyString;
92		size_t m_lazyLength;
93	};
94
95	friend class Walker;
96
97private:
98	void CleanupUsedNodes();
99	void CopyFrom(const ByteQueue &copy);
100	void Destroy();
101
102	bool m_autoNodeSize;
103	size_t m_nodeSize;
104	ByteQueueNode *m_head, *m_tail;
105	byte *m_lazyString;
106	size_t m_lazyLength;
107	bool m_lazyStringModifiable;
108};
109
110//! use this to make sure LazyPut is finalized in event of exception
111class CRYPTOPP_DLL LazyPutter
112{
113public:
114	LazyPutter(ByteQueue &bq, const byte *inString, size_t size)
115		: m_bq(bq) {bq.LazyPut(inString, size);}
116	~LazyPutter()
117		{try {m_bq.FinalizeLazyPut();} catch(...) {}}
118protected:
119	LazyPutter(ByteQueue &bq) : m_bq(bq) {}
120private:
121	ByteQueue &m_bq;
122};
123
124//! like LazyPutter, but does a LazyPutModifiable instead
125class LazyPutterModifiable : public LazyPutter
126{
127public:
128	LazyPutterModifiable(ByteQueue &bq, byte *inString, size_t size)
129		: LazyPutter(bq) {bq.LazyPutModifiable(inString, size);}
130};
131
132NAMESPACE_END
133
134#ifndef __BORLANDC__
135NAMESPACE_BEGIN(std)
136template<> inline void swap(CryptoPP::ByteQueue &a, CryptoPP::ByteQueue &b)
137{
138	a.swap(b);
139}
140NAMESPACE_END
141#endif
142
143#endif
144