summaryrefslogtreecommitdiff
path: root/queue.h
blob: f17efc5bce18ecaa6c9a6618e010bee07e9bb8e2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// specification file for an unlimited queue for storing bytes

#ifndef CRYPTOPP_QUEUE_H
#define CRYPTOPP_QUEUE_H

#include "simple.h"
//#include <algorithm>

NAMESPACE_BEGIN(CryptoPP)

/** The queue is implemented as a linked list of byte arrays, but you don't need to
    know about that.  So just ignore this next line. :) */
class ByteQueueNode;

//! Byte Queue
class ByteQueue : public Bufferless<BufferedTransformation>
{
public:
	ByteQueue(unsigned int m_nodeSize=0);
	ByteQueue(const ByteQueue &copy);
	~ByteQueue();

	unsigned long MaxRetrievable() const
		{return CurrentSize();}
	bool AnyRetrievable() const
		{return !IsEmpty();}

	void IsolatedInitialize(const NameValuePairs &parameters);
	byte * CreatePutSpace(unsigned int &size);
	unsigned int Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking);

	unsigned int Get(byte &outByte);
	unsigned int Get(byte *outString, unsigned int getMax);

	unsigned int Peek(byte &outByte) const;
	unsigned int Peek(byte *outString, unsigned int peekMax) const;

	unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true);
	unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const;

	// these member functions are not inherited
	void SetNodeSize(unsigned int nodeSize) {m_nodeSize = nodeSize;}

	unsigned long CurrentSize() const;
	bool IsEmpty() const;

	void Clear();

	void Unget(byte inByte);
	void Unget(const byte *inString, unsigned int length);

	const byte * Spy(unsigned int &contiguousSize) const;

	void LazyPut(const byte *inString, unsigned int size);
	void LazyPutModifiable(byte *inString, unsigned int size);
	void UndoLazyPut(unsigned int size);
	void FinalizeLazyPut();

	ByteQueue & operator=(const ByteQueue &rhs);
	bool operator==(const ByteQueue &rhs) const;
	byte operator[](unsigned long i) const;
	void swap(ByteQueue &rhs);

	class Walker : public InputRejecting<BufferedTransformation>
	{
	public:
		Walker(const ByteQueue &queue)
			: m_queue(queue) {Initialize();}

		unsigned long GetCurrentPosition() {return m_position;}

		unsigned long MaxRetrievable() const
			{return m_queue.CurrentSize() - m_position;}

		void IsolatedInitialize(const NameValuePairs &parameters);

		unsigned int Get(byte &outByte);
		unsigned int Get(byte *outString, unsigned int getMax);

		unsigned int Peek(byte &outByte) const;
		unsigned int Peek(byte *outString, unsigned int peekMax) const;

		unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true);
		unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const;

	private:
		const ByteQueue &m_queue;
		const ByteQueueNode *m_node;
		unsigned long m_position;
		unsigned int m_offset;
		const byte *m_lazyString;
		unsigned int m_lazyLength;
	};

	friend class Walker;

private:
	void CleanupUsedNodes();
	void CopyFrom(const ByteQueue &copy);
	void Destroy();

	bool m_autoNodeSize;
	unsigned int m_nodeSize;
	ByteQueueNode *m_head, *m_tail;
	byte *m_lazyString;
	unsigned int m_lazyLength;
	bool m_lazyStringModifiable;
};

//! use this to make sure LazyPut is finalized in event of exception
class LazyPutter
{
public:
	LazyPutter(ByteQueue &bq, const byte *inString, unsigned int size)
		: m_bq(bq) {bq.LazyPut(inString, size);}
	~LazyPutter()
		{try {m_bq.FinalizeLazyPut();} catch(...) {}}
protected:
	LazyPutter(ByteQueue &bq) : m_bq(bq) {}
private:
	ByteQueue &m_bq;
};

//! like LazyPutter, but does a LazyPutModifiable instead
class LazyPutterModifiable : public LazyPutter
{
public:
	LazyPutterModifiable(ByteQueue &bq, byte *inString, unsigned int size)
		: LazyPutter(bq) {bq.LazyPutModifiable(inString, size);}
};

NAMESPACE_END

NAMESPACE_BEGIN(std)
template<> inline void swap(CryptoPP::ByteQueue &a, CryptoPP::ByteQueue &b)
{
	a.swap(b);
}
NAMESPACE_END

#endif